{
	"id": "38424dec-1260-4a49-ae2a-d34161c35c73",
	"created_at": "2026-04-06T00:15:33.678281Z",
	"updated_at": "2026-04-10T03:24:16.825632Z",
	"deleted_at": null,
	"sha1_hash": "62a8c0d6236ebcd2eacff1c682923f380f6ee125",
	"title": "Virus Bulletin :: VB2017 paper: Nine circles of Cerber",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1032040,
	"plain_text": "Virus Bulletin :: VB2017 paper: Nine circles of Cerber\r\nArchived: 2026-04-05 17:36:03 UTC\r\nStanislav Skuratovich \u0026 Neomi Rona\r\nCheck Point Software Technologies, Belarus \u0026 Israel\r\nCopyright © 2017 Virus Bulletin\r\nAbstract\r\nWithout any doubt, 2016 was the year of ransomware. What makes ransomware so attractive to attackers is that it\r\noffers the possibility of large profits while not requiring too much effort. With the availability of ransomware-as-a-service, someone with very little actual knowledge of computers can easily manage a highly profitable campaign.\r\nA wide variety of different ransomware families appeared over the course of the last year, including Locky,\r\nCryptoWall and CryptXXX, to name just a few. Let's talk about the very profitable Cerber.\r\nThe Cerber ransomware was mentioned for the first time in March 2016 on some Russian underground forums, on\r\nwhich it was offered for rent in an affiliate program. Since then, it has been spread massively via exploit kits,\r\ninfecting more and more users worldwide, mostly in the APAC (Asia-Pacific) region. At the time of writing this\r\npaper, there are six major versions.\r\nThere have been multiple successful attempts to decrypt users' files without paying a ransom. At the end of July\r\n2016, Trend Micro released a partially working decryptor for the first version of Cerber [1]. In early August, we\r\nhad a chance to take a look at the original Cerber decryptor code that was available for download upon payment of\r\nthe ransom. Our main goal was to discover a flaw, based on the standard approaches we use against ransomware.\r\nFrom our perspective, it wouldn't be as much fun if this was one of the expected bugs – and fortunately, the one\r\nwe discovered wasn't. However, as with any flaw, you need to hide the solution from the criminals. In an ironic\r\ntwist, the ransomware authors released a new Cerber 2 version the day before we were due to release the\r\ndecryptor.\r\nIn order to be able to provide our decryption tool to as many victims as possible, we gathered forces and adapted it\r\nto the new version on the same day, thus managing to release it on time. The tool was used by many victims\r\nworldwide.\r\nThis paper details the story of the ransomware's fatal flaw and our free decryption service [2, 3]. We will dive\r\ndeep into the background of Cerber as a service, the business operations, the money flow between the attacker and\r\nthe affiliate, full global infection statistics and the estimated overall profit of the criminals [4].\r\n1. Introduction\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 1 of 20\n\nIn this paper we discuss one of the largest recent ransomware campaigns, known as Cerber. We describe the\r\nransomware's encryption routine and reveal technical details of the server-side vulnerability that was used for the\r\nsuccessful decryption of thousands of infected machines. We also share information on the money flow and\r\nestimated overall profit of the criminals, together with the tools used to collect that information. The decryption\r\nsoftware will be available as open source on our GitHub repository [5].\r\n2. Encryption scheme\r\nLet's describe the encryption scheme used by the Cerber ransomware. It uses mix of symmetric and asymmetric\r\nencryption algorithms, such as RC4 and RSA. Almost all the encryption keys are generated randomly on the\r\nvictim's machine.\r\nFirst, let's take a look at the keys that are used by Cerber during the encryption process:\r\nKey Appearance/description Scope\r\nRSA_M_PUB (2048 bits)\r\nConfiguration\r\nThis is a master public key\r\nGlobal\r\nRSA_X_PUB/PRI (X bits)\r\nRandom\r\nThis is a local key pair\r\nGlobal\r\nRC4_KEY (128 bytes) Random Per file\r\nThe structure of the encrypted file is presented in Figure 1.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 2 of 20\n\nFigure 1: Structure of encrypted file.\r\nThe goal of the encryption routine is to encrypt a single file from the file system. The number of bytes that are\r\nstolen from the beginning of each encrypted file (hereafter called N) is calculated once and depends on the local\r\nRSA key size. The steps performed by Cerber to encrypt a single file are as follows:\r\n1. Calculate the number of blocks that will be encrypted (up to the maximum number of blocks specified in\r\nthe configuration).\r\n2. Steal N bytes from the beginning of the file by replacing them with random bytes.\r\n3. Encrypt each block with the RC4 algorithm using RC4_KEY as a key.\r\n4. The following meta information is encrypted and appended to the end of the processed file:\r\nInformation Algorithm Key\r\nFileMetainfo RC4 RC4_KEY\r\nFileStolenHeader RSA RSA_X_PUB\r\nRSA_X_PUB/PRI RSA RSA_M_PUB\r\nThe FileStolenHeader contains RC4_KEY, which can be used to restore the encrypted blocks, thus it is\r\nencrypted using RSA_X_PUB. RSA_X_PRI is encrypted by the master RSA_M_PUB key, because it can\r\nbe used for the FileStolenHeader decryption.\r\nTwo main data structures that represent the encrypted file are presented below:\r\nstruct FileStolenHeader {\r\n char ver_magic[4]; // magic header (version)\r\n uint32_t rand_bytes; // random bytes\r\n uint16_t fn_len; // Unicode filename length\r\n uint8_t blocks; // blocks to encrypt\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 3 of 20\n\nuint32_t block_size; // block size\r\n uint16_t N_to_steal; // number of bytes to steal\r\n uint32_t N_bytes_mmh; // murmur3 hash of stolen\r\n char RC4_KEY[16]; // RC4_KEY\r\n char stolen_bytes[0]; // stolen bytes\r\n};\r\nstruct FileMetainfo {\r\n FILETIME Creation; // original CR time\r\n FILETIME LastAccess; // original LA time\r\n FILETIME LastWrite; // original LW time\r\n char orig_fn[0]; // original filename\r\n uint64_t blocks_mmh[0]; // murmur3 hash of blocks\r\n};\r\nThe overall structure of an encrypted file was presented in Figure 1, however this can vary depending on the size\r\nof encrypted file.\r\nIf a single block is encrypted:\r\nstruct EncryptedFile {\r\n char rand_bytes[N]; // stolen bytes repl\r\n char ct[FileSize-N]; // encrypted file data\r\n FileMetainfo enc_fmi; // encrypted FMI stru\r\n char enc_fsh[0]; // encrypted FSH stru\r\n char enc_RSA_X[0]; // encrypted RSA_X_*\r\n};\r\nIf multiple blocks are encrypted:\r\nstruct EncryptedFile {\r\n char rand_bytes[N]; // stolen bytes repl\r\n char pt_0[K]; // plaintext chunk\r\n char ct_0[max_block_size]; // ciphertext chunk\r\n ...\r\n char pt_y[M]; // plaintext chunk\r\n char ct_y[max_block_size]; // ciphertext chunk\r\n FileMetainfo enc_fmi; // encrypted FMI stru\r\n char enc_fsh[0]; // encrypted FSH stru\r\n char enc_RSA_X[0]; // encrypted RSA_X_*\r\n};\r\nIf the file is small:\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 4 of 20\n\nstruct EncryptedFile {\r\n char rand_bytes[N]; // stolen bytes repl\r\n FileMetainfo enc_fmi; // encrypted FMI stru\r\n char enc_fsh[0]; // encrypted FSH stru\r\n char enc_RSA_X[0]; // encrypted RSA_X_*\r\n};\r\n3. Decryption scheme\r\nLet's discuss the decryption scheme that is used by the Cerber ransomware, after the ransom has been paid. An\r\noverview of the decryption scheme is shown in Figure 2.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 5 of 20\n\nFigure 2: Decryption scheme.\r\nThe following steps are performed by the decryptor in order to restore encrypted files:\r\n1. Extract encrypted blob of RSA_X_PUB/PRI (hereafter ENC_RSA_X_BLOB) from the end of the\r\nencrypted file and send it to the server.\r\n2. Decrypt RSA_X_PRI on the server by using RSA_M_PRI and send it to the client. RSA_M_PRI is the\r\nmaster private key and is known only to the attacker.\r\n3. Use the obtained RSA_X_PRI to decrypt the FileStolenHeader structure, thus restoring RC4_KEY and the\r\nstolen bytes.\r\n4. Decrypt encrypted blocks by using RC4_KEY.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 6 of 20\n\n5. Restore original file content by combining stolen header with the decrypted blocks.\r\n6. Decrypt FileMetainfo structure using RC4_KEY and restore file meta information.\r\nAs we can see, the decryption routine is not complicated. The only blind spot is the RSA_M_PRI key.\r\nFactorization of a 2048-bit number is a nice challenge [6], but is definitely not what we want to deal with, because\r\ncracking such a long key is not feasible in a reasonable amount of time.\r\nLet's take a look at how the decryptor communicates with the server in order to obtain RSA_X_PRI, which is\r\ncritical for the decryption process. The decryptor encodes ENC_RSA_X_BLOB using a base64 algorithm\r\n(hereafter PRIVATE_KEY). The ID of the infected machine is calculated as an MD5 of the previously encoded\r\nblock (hereafter SIGN) (see Figure 3).\r\nFigure 3: Signature generation.\r\nThe first message contains only the machine ID, which is sent using the following format:\r\n\"sign=%s\" % SIGN\r\nThe response from the server contains a CAPTCHA image, which must be solved to continue decryption. We\r\nassume that this is done to protect the decryption server from the DDoS.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 7 of 20\n\nFigure 4: CAPTCHA.\r\nThe CAPTCHA solution, together with PRIVATE_KEY and SIGN, are sent to the server using the following\r\nformat:\r\n\"captcha=%d\u0026sign=%s\u0026private_key=%s\" % (CAPTCHA, SIGN, PRIVATE_KEY)\r\nIf the CAPTCHA has successfully been solved and the specified machine ID has made the ransom payment, the\r\nserver decrypts RSA_X_PRI and sends it back to the client. Then the decryptor starts the file restore process.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 8 of 20\n\nFigure 5: Successful decryption.\r\nIf the ransom for the specified machine ID is not paid, the user receives the message shown in Figure 6 during\r\ncommunication with decryption server.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 9 of 20\n\nFigure 6: Ransom not paid.\r\nNow we have familiarized ourselves with the decryption scheme and communication method, let's consider what\r\ncan go wrong in the existent solution.\r\n4. Fatal flaw\r\nThis section describes the approaches that were used to find a flaw in the decryptor. First, we should understand\r\nhow exactly the server validates that the ransom has been paid for a specific machine. The most obvious answer is\r\nthe use of the SIGN field. If the ransom is paid for SIGN, the server decrypts PRIVATE_KEY and sends\r\nRSA_X_PRI to the user. Let's try to rewrite the server code that is responsible for handling decryption requests\r\nfrom users based on received responses:\r\ndef handle_request_decrypt_private_key(packet):\r\n if not captcha_correct(packet['captcha']):\r\n send('{\"error\": \"Captcha expired or invalid\"}')\r\n return\r\n if not paid(packet['sign']):\r\n send('{\"error\":\"Not paid\"}')\r\n return\r\n pk = urls_to_b64(packet['private_key'])\r\n #**********************************************\r\n # DOES SERVER SIDE HAVE SUCH INTEGRITY CHECK ?#\r\n if md5(pk).hexdigest() != packet['sign'])\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 10 of 20\n\nsend('{???}')\r\n return\r\n #**********************************************\r\n RSA_X_PRI = decrypt(b64decode(pk))\r\n send('{\"error\": \"null\", \"private_key\": \"%s\"}' %\\\r\n encode(RSA_X_PRI))\r\nNow let's try to recreate the server's exact behaviour based on the received responses and common sense:\r\n1. Check if CAPTCHA is correct.\r\n2. Check if SIGN is paid. Server treats SIGN as a unique machine ID.\r\n3. Perform integrity check on delivered PRIVATE_KEY using SIGN, because SIGN is the hexlified MD5 of\r\nPRIVATE_KEY.\r\n4. Decrypt PRIVATE_KEY and extract RSA_X_PRI.\r\nThe first two steps can easily be checked by sending an incorrect CAPTCHA solution and SIGN that is unpaid.\r\nThe third step is what we are really interested in.\r\nLet's imagine that SIGN_A signature is paid and we have a possibility to restore RSA_X_PRI_A. RSA_X_PRI_A\r\nis restored from the PRIVATE_KEY data that is under the sender's control. So what happens if the user spoofs that\r\ndata?\r\nFigure 7: Original PRIVATE_KEY for the paid\r\nSIGN.\r\nLet's think what exactly we can achieve by setting PRIVATE_KEY to prepared data assuming SIGN_A is paid.\r\nWhat will happen if we can calculate PRIVATE_KEY_V for another infection? Assuming that a data integrity\r\ncheck is absent, then the server will simply decrypt PRIVATE_KEY_V and extract RSA_X_PRI_V, thus giving\r\nthe possibility to restore infected files for the user who hasn't paid! By applying the same tactics to all infected\r\nmachines, we can restore them by using only one valid SIGN.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 11 of 20\n\nIf the server does not perform an integrity check of the PRIVATE_KEY data, then it is decrypted and the\r\nRSA_X_PRI_V key is sent to the user. The user then adopts that key to restore encrypted files.\r\nFigure 8: Spoofed PRIVATE_KEY for the paid\r\nSIGN.\r\nTo showcase this theory we paid the ransom for one infection that was performed on a specially prepared\r\nmachine. All the checks on the server side passed and the decryption process succeeded (Figure 9).\r\nFigure 9: Successful decryption for original PRIVATE_KEY.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 12 of 20\n\nNext, a second machine was infected and encrypted with the Cerber ransomware. It obviously had a different\r\nPRIVATE_KEY. The original decryptor was dirty patched to use the same SIGN as was previously paid. We\r\nstarted the decryptor on the second infected machine, and all the data on the infected machine was decrypted!\r\n(Figure 10).\r\nFigure 10: Successful decryption for spoofed PRIVATE_KEY.\r\nThe Cerber authors simply did not perform a data integrity check, thus giving us the possibility to exploit this bug\r\nand decrypt machines with only one paid signature.\r\nFigure 11: Data integrity\r\ncheck that authors have skipped.\r\n5. Decryption service installation\r\nThis section provides a general description of what actions were performed in order to establish a decryption\r\nservice as soon as possible after the vulnerability was discovered. Our two main goals were to hide the flaw from\r\nthe attackers for as long as possible and to make the bandwidth for decryption as wide as possible.\r\nIn order to fulfil both requirements we decided to set up a server that would be responsible for fetching the keys.\r\nAfter being fetched, the obtained key would be sent to the infected user. This key would then be used by the\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 13 of 20\n\nclient-side decryptor to restore the files. Figure 12 provides an overview of the process.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 14 of 20\n\nFigure 12: Fetching decryption key for specific\r\ninfection.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 15 of 20\n\nThe following steps are taken in order to retrieve the decryption key for a specific infection:\r\n1. User uploads encrypted file from the infected machine to the Check Point Decryption Service (CPDS).\r\n2. CPDS extracts ENC_RSA_X_BLOB from the received file, which is aliased with PRIVATE_KEY_K.\r\n3. PRIVATE_KEY_K is sent to the Cerber Decryption Server (CDS) together with the paid SIGN_A.\r\n4. CDS checks if SIGN_A is paid and decrypts the RSA_X_PRI client private key by using RSA_M_PRI.\r\n5. CDS sends RSA_X_PRI_K in a specific format to the CPDS.\r\n6. CPDS extracts RSA_X_PRI_K and sends the file with its content to the user.\r\n7. User uses the obtained file together with the RSA_X_PRI_K in order to restore encrypted files by the\r\nrunning prepared application.\r\nFigure 13: Infected machine decryption process.\r\nIn order to parallelize victims' requests and reduce both the waiting time and server bug fixing, four decryption\r\nsignatures were purchased. With that number of keys we were able to handle up to 20,000 decryption requests per\r\nday.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 16 of 20\n\nFigure 14: Check Point Cerber Ransomware Decryption Tool.\r\nNow that we have examined the server-side flaw that gave us the chance to decrypt infected computers, let's take a\r\nlook at the Cerber ecosystem and associated money laundering.\r\n6. A ransomware-as-a-service ecosystem\r\nCerber ransomware-as-a-service illustrates every aspect of an effective business franchise. The actor behind the\r\noperation, dubbed 'crbr', offers the ransomware for sale through a private, carefully managed affiliate program –\r\nactors who are willing to distribute the ransomware are granted a comprehensive use panel through which they\r\ncan monitor the rate of the infections, encryption process and ransom payments. In return, 40% of the profits are\r\ntransferred to 'crbr' as a fee. Based on data collected by our sensors, during July 2016 Cerber affiliates ran over\r\n150 active campaigns, infecting nearly 150,000 victims, with a total estimated profit of US$195,000 per month,\r\nwhich adds up to US$2.3 million per year (the numbers are based on a Bitcoin conversion rate of US$590). In\r\nfact, the Cerber ransomware demonstrates a growth rate higher than that of major global fast food chains.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 17 of 20\n\nFigure 15: Cerber global distribution map.\r\n7. Following the money trail\r\nCerber generates a unique Bitcoin wallet to receive funds from each victim. The generated wallet appears in the\r\nlanding page shown to the victim, represented by an encoded string in the URL. Check Point researchers\r\nexamined tens of thousands of victim Bitcoin wallets, and found that only 0.3% of the victims chose to pay the\r\nransom. But the bigger question is: once a Bitcoin transaction occurs, what happens to the money? Based on our\r\nanalysis, it seems that Cerber uses a Bitcoin mixing service as part of its money flow in order to remain\r\nuntraceable. A mixing service allows the ransomware author to transfer Bitcoins and receive the same amount\r\nback to a wallet that cannot be associated with the original owner. This is achieved by mixing multiple users' funds\r\ntogether, using tens of thousands of Bitcoin wallets, making it almost impossible to track them individually (see\r\nFigure 16). Based on our research, automated tools distribute the affiliate shares only after the money has been\r\nswapped by the mixing service and the malware author's share has been collected.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 18 of 20\n\nFigure 16: Cerber Bitcoin flow.\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 19 of 20\n\nSummary\r\nThousands of users restored their files while the Check Point Cerber Decryption Service was active.\r\nUnfortunately, the attackers were quite responsive and fixed the vulnerability within 24 hours.\r\nCerber ransomware-as-a-service uses a business model that has been proven to be effective by some of the biggest\r\nfranchise businesses worldwide. Furthermore, the malware author uses a sophisticated money flow to ensure that\r\nthe profits remain sealed and that its Bitcoin wallets cannot be associated with the attack operation. It is therefore\r\nlittle wonder that Cerber ransomware is one of the most widespread pieces of ransomware of our time.\r\nAcknowledgements\r\nWe would like to thank the Check Point Malware Research and Threat Intelligence teams and in particular\r\nAliaksandr Trafimchuk for his devoted help throughout the research.\r\nReferences\r\n[1] Cerber Decryptor. http://blog.trendmicro.com/trend-micro-ransomware-file-decryptor-updated/.\r\n[2] Check Point Releases Working Decryptor for the Cerber Ransomware.\r\nhttps://www.bleepingcomputer.com/news/security/check-point-releases-working-decryptor-for-the-cerber-ransomware/.\r\n[3] Cerber 2 Ransomware: Free Decryption Tool Released. http://www.bankinfosecurity.com/cerber-2-\r\nransomware-free-decryption-tool-released-a-9341.\r\n[4] Cerber. http://blog.checkpoint.com/2016/08/16/cerberring/.\r\n[5] Source code. https://github.com/CheckPointSW/CerberDecryptionService.\r\n[6] RSA Factoring Challenge. https://en.wikipedia.org/wiki/RSA_Factoring_Challenge.\r\nSource: https://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nhttps://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/\r\nPage 20 of 20",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.virusbulletin.com/virusbulletin/2017/12/vb2017-paper-nine-circles-cerber/"
	],
	"report_names": [
		"vb2017-paper-nine-circles-cerber"
	],
	"threat_actors": [
		{
			"id": "dfee8b2e-d6b9-4143-a0d9-ca39396dd3bf",
			"created_at": "2022-10-25T16:07:24.467088Z",
			"updated_at": "2026-04-10T02:00:05.000485Z",
			"deleted_at": null,
			"main_name": "Circles",
			"aliases": [],
			"source_name": "ETDA:Circles",
			"tools": [],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434533,
	"ts_updated_at": 1775791456,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/62a8c0d6236ebcd2eacff1c682923f380f6ee125.pdf",
		"text": "https://archive.orkl.eu/62a8c0d6236ebcd2eacff1c682923f380f6ee125.txt",
		"img": "https://archive.orkl.eu/62a8c0d6236ebcd2eacff1c682923f380f6ee125.jpg"
	}
}