{
	"id": "67c0fb63-4ed9-4036-8729-41ffab04a646",
	"created_at": "2026-04-06T00:11:04.530497Z",
	"updated_at": "2026-04-10T13:12:58.820706Z",
	"deleted_at": null,
	"sha1_hash": "3916e3ed6d741e58129d4f60e4253aff7cd59c3a",
	"title": "Hidden in Plain Sight: Identifying Cryptography in BLACKMATTER Ransomware | Mandiant",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 243393,
	"plain_text": "Hidden in Plain Sight: Identifying Cryptography in\r\nBLACKMATTER Ransomware | Mandiant\r\nBy Mandiant\r\nPublished: 2021-10-20 · Archived: 2026-04-05 15:18:55 UTC\r\nWritten by: Jacob Thompson\r\nOne of the main goals of evaluating a ransomware sample is to determine what kind of cryptography the sample\r\nuses. Sometimes this is straightforward; for a BLACKMATTER sample we analyzed, it was not. We found the\r\nprocess we used to identify the mathematical operations of RSA cryptography from the BLACKMATTER code\r\ninteresting and reusable for other malware samples and for becoming a better reverse engineer in general.\r\nIntroduction\r\nThe BLACKMATTER ransomware family has been identified in several recent attacks. Other authors have\r\npublished summaries of BLACKMATTER, including its relationship to prior families REVIL and DARKSIDE,\r\nand method of encryption. Additionally, the U.S. Department of Health and Human Services has published a\r\nsummary of BLACKMATTER covering historical timeline, associated threat groups, and types of victims.\r\nMandiant’s FLARE team performed an internal analysis on a 32-bit BLACKMATTER variant (sha256:\r\n5da8d2e1b36be0d661d276ea6523760dbe3fa4f3fdb7e32b144812ce50c483fa). Like many ransomware families,\r\nBLACKMATTER uses a combination of symmetric and asymmetric cryptography to hold its victims’ data for\r\nransom. A BLACKMATTER sample has an asymmetric public key inside its configuration, and only the threat\r\nactor holds the corresponding private key. When attacking each of a victim’s files, BLACKMATTER first uses\r\nsymmetric cryptography to encrypt the file. BLACKMATTER then uses the asymmetric public key to encrypt the\r\nsymmetric key and appends that encrypted key to the end of the file. The symmetric key is then thrown away. The\r\ndesign means that no amount of reverse engineering of the BLACKMATTER binary alone can allow the victim to\r\ndecrypt the files, because only the attacker’s private key can decrypt the per-file keys and recover the original\r\ndata.\r\nAs we reversed BLACKMATTER, we quickly found its symmetric encryption to be a modified version of\r\nSalsa20. The asymmetric cryptography was not as obvious. Ransomware samples often employ a cryptographic\r\nlibrary such as Windows wincrypt, OpenSSL, or Crypto++; often the library is statically linked to make it\r\nsomewhat more difficult to identify. BLACKMATTER was unique and used no identifiable cryptographic\r\nlibraries. Some cryptographic routines have telltale behaviors—RC4 fills an array of 256 bytes with the values 0\r\nto 255, and Salsa20 performs left rotations of 7, 9, 13, and 18 bits. We did not immediately recognize asymmetric\r\ncode in BLACKMATTER as a familiar algorithm. Magic numbers can identify cryptographic algorithms, such as\r\nChaCha20’s “expand 32-byte k,” AES’s Te and Td tables, and ASN.1-related byte sequences such as 30 82 02 (or\r\nMIIC after base64 encoding); neither did we recognize any magic numbers.\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 1 of 10\n\nUltimately, we identified BLACKMATTER’s asymmetric cryptography as 1024-bit RSA, a common and\r\nunremarkable choice that we identified partly through the process of elimination (and previous analysis of\r\nBLACKMATTER and its predecessor families), but also by locating the mathematical operations employed by\r\nBLACKMATTER and connecting them to the raw math behind RSA. It is the process we employed to locate and\r\nidentify the RSA algorithm that we thought of as interesting and reusable for other malware samples and reverse\r\nengineers, and that is the focus of this blog post.\r\nReview of RSA\r\nFirst, let us begin with a brief review of how RSA works. RSA (Rivest-Shamir-Adleman) is an archetypical\r\ncryptosystem for asymmetric cryptography. An individual generates a key pair (public and private key) according\r\nto the algorithm; the private key is kept secret while the public key is widely distributed. Among other uses, any\r\nparty can send the individual a secret message by encrypting the message with the public key and delivering it\r\nover an unprotected communication channel. In legitimate use, RSA could be used in e-commerce to establish a\r\nshared secret for encrypting information in a credit card transaction. In illicit use like ransomware, RSA is\r\nperfectly suited for concealing the information needed to decrypt files until payment is received and then\r\nexchanged for the private key.\r\nRSA operates on the principle of modular exponentiation, which is easy to perform but hard to reverse. Here is a\r\ngreatly simplified explanation of how RSA keys are generated:\r\n1. Select two distinct large prime numbers p and q. Let n = pq and ϕ(n) = (p-1)(q-1). n is not secret and may\r\nbe freely shared as part of the public key, while also knowing ϕ(n) would allow anyone to break the\r\nencryption.\r\n2. Select an exponent for encryption, e. In practice, e = 65537 is almost always used.\r\n3. Determine the corresponding exponent for decryption, d ≡ e-1\r\n (mod ϕ(n)), which is straightforward using\r\nthe Extended Euclidean Algorithm, but intractable without knowing ϕ(n).\r\n4. The pair (n, e) is the public key; d is the private key. Information sufficient to derive d (such as p and q or\r\nϕ(n)) must also be kept secret.\r\nA message may then be encrypted by computing E(m) = m\r\ne mod n and decrypted by computing D(E(m)) = (me)d\r\nmod n ≡ m\r\n1\r\n(mod n). This property of n, m, e, and d comes from Fermat’s Little Theorem and can be explored by\r\nreviewing a more detailed explanation of RSA.\r\nBinary Exponentiation\r\nThe choice of e = 65537 is intentional and allows encryption to be performed efficiently while remaining secure.\r\nSince e = 65537 = 65536 + 1 = 216+1, m\r\n65537mod n can be computed using binary exponentiation as follows:\r\nx=m\r\nfor i = 1 to 16:\r\nx = x2mod n\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 2 of 10\n\nx = xm mod n\r\nOnce RSA encryption is distilled to this form, the only complication is that a function is needed to perform “big\r\nnumber” modular multiplication, i.e., f (x, y, n) = xy mod n. Inevitably, while analyzing BLACKMATTER, our\r\nattention was diverted to a function which performs modular multiplication, but whose purpose was not obvious.\r\nCompounding that, the constant 65537 never appears in the code when implemented as above. Next, we present\r\nan explanation showing how we verified how each asymmetric cryptographic function in the BLACKMATTER\r\nsample fit in as part of the RSA encryption process.\r\nMultiplication Function\r\nThe multiplication of two unsigned binary integers can be expressed as a series of additions and multiplications by\r\ntwo, e.g.:\r\n145 ∙ 113\r\n145 ∙ (26+25+24+20\r\n)\r\n(145 ∙ 22 + 145 ∙ 2 + 145) ∙ 24 + 145 ∙ 20\r\n((145 ∙ 2 + 145) ∙ 2 + 145) ∙ 2 ∙ 2 ∙ 2 ∙ 2 + 145\r\nSince a multiplication by two is just a left bit shift by one bit, this makes it possible to multiply x ∙ y using only left\r\nshifts and additions, examining each bit of x to determine whether y should be added into the running product on\r\neach iteration before shifting the running product to the left. The BLACKMATTER big number multiplication\r\nfunction sub_401B24 (x, y, n), based on this exact principle, calculates x = (x * y) % n.\r\nOf course, x86 machines do not have 1024-bit registers or immediate values, so an operation on a 1024-bit integer\r\nmust be broken down into 32 operations on each 32-bit chunk of the 1024-bit integer. The x86 instructions rcl,\r\nadc, and sbb make such big number arithmetic possible, using the carry flag to propagate a 0- or 1-bit to the next\r\n32-bit chunk as appropriate.\r\nFirst, the big number multiplication function allocates some stack space for a temporary 1024-bit integer z to hold\r\nthe running product, and initializes it to zero (Figure 1).\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 3 of 10\n\nFigure 1: The big number multiplication function starts by initializing a 1024-bit integer z to zero\r\nNext, the big number multiplication function loops over each bit in its inputs and outputs. For each iteration, the\r\nfunction first shifts z left by one bit (Figure 2).\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 4 of 10\n\nFigure 2: The big number multiplication function shifts z to the left by one bit. Since z is 1024 bits long, the rcl\r\ninstruction allows the shift to be done on each 32-bit chunk\r\nThis calculation multiplies z by two, and therefore may cause z to exceed n. To ensure the calculation is performed\r\nmod n, the function next subtracts n from z (Figure 3).\r\nFigure 3: After doubling z, the big number multiplication must subtract n from z to ensure the calculation is done\r\nmod n\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 5 of 10\n\nNote that the malware did not check whether z ≥ n before performing the subtraction, so if the result was negative,\r\nthe function adds n to z to reverse the previous subtraction and restore z to the range [0, n) (Figure 4). The\r\nmalware operates this way because comparing z to n before performing the previous subtraction would have been\r\njust as computationally expensive as performing the subtraction.\r\nFigure 4: If z -= n produced a negative result, n is added back to z to restore z to the correct range mod n\r\nNow, the function shifts x to the left by one bit. The formerly leftmost bit of x is then left in the carry flag. If the\r\nbit was 1, y is added to z; if it was 0, y is not added to z (Figure 5).\r\nFigure 5: The big number multiplication function shifts x to the left by one bit and uses the formerly-leftmost bit\r\nto determine whether y should be added to the running product z on this iteration\r\nIn either case, z is again restored into the range [0,n) so that all calculations remain mod n. This process continues\r\nfor 1024 iterations. Put another way, x is examined bit-by-bit to determine whether or not y should be added to the\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 6 of 10\n\nintermediate product z on each iteration before it is shifted. After all the iterations, x is overwritten with the\r\nproduct z (Figure 6).\r\nFigure 6: The value x is overwritten with the running product z once the calculation is complete\r\nNote that sub_401B24 can be used to calculate x\r\n2mod n by calling sub_401B24(x, x, n).\r\nBinary Exponentiation Function\r\nWe found that the big number multiplication function previously described was repeatedly called by what we\r\nanalyzed to be a binary exponentiation function, sub_4019C0 (x, buf, n, m). This binary exponentiation function\r\ncomputes x = x256mod n if m is NULL, or x = mx256mod n if m is not NULL. When the binary exponentiation\r\nfunction squares x eight times, and optionally multiplies by m, the binary exponentiation function makes nine\r\nseparate calls to the big number multiplication function in an “unrolled” fashion, making its purpose slightly more\r\ndifficult to identify. Here is an excerpt of the IDA pseudocode from the binary exponentiation function:\r\nconst __m128i *__stdcall sub_4019C0 (const __m128i *x, __m128i *buf, int n, int m)\r\n{\r\n…\r\nx0 = x;\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 7 of 10\n\ny0 = buf;\r\ni0 = 8;\r\ndo\r\n{\r\n*y0++ = _mm_load_si128 (x0++) ;\r\n--i0;\r\n}\r\nwhile ( i0 );\r\ny1 = buf;\r\nx1 = x;\r\nsub_401B24((__m128i *)x, (int)buf, (_DWORD *) n);\r\ni1 = 8;\r\ndo\r\n{\r\n*y1++ = _mm_load_si128(x1++);\r\n--i1;\r\n}\r\nwhile ( i1 );\r\n...\r\ny8 = buf;\r\nx8 = x;\r\nresult = sub_401B24 ((__m128i *)x, (int) buf, (_DWORD *) n);\r\nif ( m )\r\n{\r\ni8 = 8;\r\ndo\r\n{\r\n*y8++ = _mm_load_si128 (x8++);\r\n--i8;\r\n}\r\nwhile ( i8 );\r\nreturn sub_401B24 ((__m128i *) x, m, (_DWORD *) n);\r\n}\r\nreturn result;\r\n}\r\nRSA Encryption Function\r\nWith the pieces put together, now we can understand the RSA encryption function in BLACKMATTER that wraps\r\nthe other routines. The RSA encryption function sub_40183C (m, n) encrypts m by calculating m=m65537mod n.\r\nAs individual steps it operates as follows:\r\n1. Let buf and x be 1024-bit integers, and let x = 1.\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 8 of 10\n\n2. Call the binary exponentiation function sub_4019C0 (x, buf, n, m) to calculate x = mx256\r\n mod n, which,\r\nsince x = 1, is just x = m.\r\n3. Call the binary exponentiation function sub_4019C0 (x, buf, n, 0) to calculate x = x256\r\n mod n.\r\n4. Call the binary exponentiation function sub_4019C0 (x, buf, n, m) to calculate x = mx256\r\n mod n\r\nAt the end of these steps, x = m(m\r\n256\r\n)\r\n256\r\n mod n = m65537mod n.\r\nHere is an excerpt of the IDA pseudocode from the overall RSA encryption function:\r\n__m128i *__stdcall sub_40183C(__m128i *m, __m128i *n)\r\n{\r\n…\r\nx [0] .m128i_i64 [1] = 0i64;\r\nmemset (\u0026x [1], 0, 112);\r\nx [0] .m128i_i64 [0] = 1i64;\r\nsub_4019C0 (x, buf, n, m);\r\nsub_4019C0 (x, buf, n, 0);\r\nsub_4019C0 (x, buf, n, m);\r\npx = x;\r\npm = m;\r\ni = 8;\r\ndo\r\n{\r\n*pm++ = *px++;\r\n--i;\r\n}\r\nwhile ( i );\r\nreturn px;\r\n}\r\nSince Python natively supports big number integers, the entire BLACKMATTER calculation could be simplified\r\nin Python as follows:\r\nx = m\r\nfor i in range (16):\r\nx = x * x % n\r\nx = x * m % n\r\nConclusion\r\nIn analyzing BLACKMATTER we found that the author accomplishes RSA encryption with only three\r\nfreestanding functions with no external libraries. The RSA public key does not stand out as it is simply a 1024-bit\r\ninteger in the binary. There are no magic numbers—not even 65537—because of how the code is structured; the\r\nnumber 65537 is implicit in performing the sixteen squarings followed by one final multiplication by m; it is\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 9 of 10\n\npossible the author used inline assembly within the three routines. We hope the reader will find these observations\r\nuseful in spotting RSA implementations in other malware. We also found an insightful reminder in that instead of\r\nobscuring the meaning of code through obfuscation and packing, an attacker can also hide it in plain sight by\r\ncreating freestanding and minimalistic implementations of cryptographic algorithms with no external\r\ndependencies.\r\nPosted in\r\nThreat Intelligence\r\nSecurity \u0026 Identity\r\nSource: https://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nhttps://www.mandiant.com/resources/cryptography-blackmatter-ransomware\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.mandiant.com/resources/cryptography-blackmatter-ransomware"
	],
	"report_names": [
		"cryptography-blackmatter-ransomware"
	],
	"threat_actors": [],
	"ts_created_at": 1775434264,
	"ts_updated_at": 1775826778,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/3916e3ed6d741e58129d4f60e4253aff7cd59c3a.pdf",
		"text": "https://archive.orkl.eu/3916e3ed6d741e58129d4f60e4253aff7cd59c3a.txt",
		"img": "https://archive.orkl.eu/3916e3ed6d741e58129d4f60e4253aff7cd59c3a.jpg"
	}
}