{
	"id": "665f5815-7188-4d25-900d-d3f0148cc714",
	"created_at": "2026-04-06T00:11:10.573083Z",
	"updated_at": "2026-04-10T03:21:53.466316Z",
	"deleted_at": null,
	"sha1_hash": "e52941d08e5123b99fbe66682bbef8ee0eeb04c1",
	"title": "Malware analysis: part 7. Yara rule example for CRC32. CRC32 in REvil ransomware",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1851951,
	"plain_text": "Malware analysis: part 7. Yara rule example for CRC32. CRC32 in\r\nREvil ransomware\r\nBy cocomelonc\r\nPublished: 2023-02-02 · Archived: 2026-04-05 18:56:38 UTC\r\n6 minute read\r\n﷽\r\nHello, cybersecurity enthusiasts and white hackers!\r\nThis post is the result of my own research on Yara rule for CRC32 hashing. How to use it for malware analysis in\r\npractice.\r\nAt first I wanted to focus on the WinAPI hashing method by CRC32 at malware development. But then this article\r\nwould differ from this one only in the hashing algorithm. Then I decided to see how to create a Yara rule which\r\nindicate using this algorithm at malware samples. I also consider the implementation of this algorithm in the REvil\r\nransomware.\r\nCRC32Permalink\r\nIn short, this is one of the checksum calculation methods. CRC32 (Cyclic Redundancy Check 32) is a type of\r\nhashing algorithm used to generate a small, fixed-size checksum value from any data. It is used to detect errors in\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 1 of 10\n\ndata stored in memory or transmitted over a network or other communication channel. The checksum is calculated\r\nusing a polynomial function and is often expressed as a 32-bit hexadecimal number.\r\nIn fact, CRC is not a sum, but the result of dividing a certain amount of information (information message) by a\r\nconstant, or rather, the remainder of dividing a message by a constant.\r\nAlgorithm of the simplest calculation method is:\r\n1. initialize a remainder r to be 0xFFFFFFFF\r\n2. for each byte in the message, do the following:\r\na. divide the current remainder r by the polynomial x^8 + x^7 + x^6 + x^4 + x^2 + 1 (0xEDB88320)\r\nb. store the remainder in an 8-bit register.\r\nc. XOR the 8-bit register with the next byte of the message.\r\nd. replace the current remainder with the 8-bit register\r\n3. after the last byte of the message has been processed, the final remainder is the CRC result.\r\npractical examplePermalink\r\nAnd, where can this be applied in the malware development? This algorithm is often used for hashing function\r\nnames.\r\nI used my example from the previous article and just replaced the hashing algorithm to CRC32 :\r\n/*\r\n * hack.cpp - hashing Win32API functions via CRC32. C++ implementation\r\n * @cocomelonc\r\n * https://cocomelonc.github.io/malware/2023/01/27/malware-analysis-7.html\r\n*/\r\n#include \u003cwindows.h\u003e\r\n#include \u003cstdio.h\u003e\r\ntypedef UINT(CALLBACK* fnMessageBoxA)(\r\n HWND hWnd,\r\n LPCSTR lpText,\r\n LPCSTR lpCaption,\r\n UINT uType\r\n);\r\nunsigned int crc32(const char *data, size_t len) {\r\n unsigned int crc_table[256], crc;\r\n for (int i = 0; i \u003c 256; i++) {\r\n crc = i;\r\n for (int j = 0; j \u003c 8; j++) crc = (crc \u003e\u003e 1) ^ (crc \u0026 1 ? 0xEDB88320 : 0);\r\n crc_table[i] = crc;\r\n };\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 2 of 10\n\ncrc = 0xFFFFFFFF;\r\n while (len--) crc = (crc \u003e\u003e 8) ^ crc_table[(crc ^ *data++) \u0026 0xFF];\r\n return crc ^ 0xFFFFFFFF;\r\n}\r\nstatic LPVOID getAPIAddr(HMODULE h, unsigned int myHash) {\r\n PIMAGE_DOS_HEADER img_dos_header = (PIMAGE_DOS_HEADER)h;\r\n PIMAGE_NT_HEADERS img_nt_header = (PIMAGE_NT_HEADERS)((LPBYTE)h + img_dos_header-\u003ee_lfanew);\r\n PIMAGE_EXPORT_DIRECTORY img_edt = (PIMAGE_EXPORT_DIRECTORY)(\r\n (LPBYTE)h + img_nt_header-\u003eOptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);\r\n PDWORD fAddr = (PDWORD)((LPBYTE)h + img_edt-\u003eAddressOfFunctions);\r\n PDWORD fNames = (PDWORD)((LPBYTE)h + img_edt-\u003eAddressOfNames);\r\n PWORD fOrd = (PWORD)((LPBYTE)h + img_edt-\u003eAddressOfNameOrdinals);\r\n for (DWORD i = 0; i \u003c img_edt-\u003eAddressOfFunctions; i++) {\r\n LPSTR pFuncName = (LPSTR)((LPBYTE)h + fNames[i]);\r\n if (crc32(pFuncName, strlen(pFuncName)) == myHash) {\r\n printf(\"successfully found! %s - %x\\n\", pFuncName, myHash);\r\n return (LPVOID)((LPBYTE)h + fAddr[fOrd[i]]);\r\n }\r\n }\r\n return nullptr;\r\n}\r\nint main() {\r\n HMODULE mod = LoadLibrary(\"user32.dll\");\r\n //LPVOID addr = getAPIAddr(mod, 0x572d5d8e);\r\n LPVOID addr = getAPIAddr(mod, 1462590862);\r\n printf(\"0x%p\\n\", addr);\r\n fnMessageBoxA myMessageBoxA = (fnMessageBoxA)addr;\r\n myMessageBoxA(NULL, \"Meow-meow!\",\"=^..^=\", MB_OK);\r\n return 0;\r\n}\r\nAs you can see, I just used this constant 0xEDB88320 and also hardcoded MessageBoxA string:\r\nimport zlib\r\n# crc32\r\ndef crc32(data):\r\n hash = zlib.crc32(data)\r\n print (\"0x%08x\" % hash)\r\n print (hash)\r\n return hash\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 3 of 10\n\ncrc32(b\"MessageBoxA\")\r\nyara rulePermalink\r\nSo in the simplest implementation, the Yara rule will look like this:\r\nrule crc32_hash\r\n{\r\n meta:\r\n author = \"cocomelonc\"\r\n description = \"crc32 constants\"\r\n strings:\r\n $c = { 2083B8ED }\r\n condition:\r\n $c\r\n}\r\nAs you can see, we just add algorithm’s constant for identity:\r\nhexdump -C ./hack.exe | grep \"20 83 b8 ed\"\r\nLet’s check it:\r\nyara -w ./crc32.yar ./hack.exe\r\nDespite the fact that this rule may provide a large number of false-positive matches, it is useful to be aware that a\r\nsample may have implemented CRC32 , since this can speed up malware sample analysis.\r\ndemoPermalink\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 4 of 10\n\nFirst of all, compile our “malware”:\r\nx86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-se\r\nRun it at victim’s machine ( Windows 10 x64 ):\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 5 of 10\n\nAs you can see, everything is worked perfectly! =^..^=\r\nLet’s go to upload our “malware” to VirusTotal:\r\nSo, 4 of 70 AV engines detect our file as malicious.\r\nhttps://www.virustotal.com/gui/file/f2d076786b061b771f945243dbf755539b8170963cf89aadcccfb6e62acd4083/details\r\nThis is trick is used for example by REvil and MailTo ransomwares in the wild.\r\npractical example 2. REvil ransomwarePermalink\r\nREvil generates a unique identifier ( UID ) for the host using the following process. The UID is part of the payment\r\nURL referenced in the dropped ransom note:\r\nobtains the volume serial number for the system drive\r\ngenerates a CRC32 hash of the volume serial number using the hard-coded seed value of 0x539\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 6 of 10\n\ngenerates a CRC32 hash of the value returned by the CPUID assembly instruction using the CRC32 hash for\r\nthe volume serial number as a seed value\r\nappends the volume serial number to the CPUID CRC32 hash.\r\nIn the simplest implementation, it is look like ( hack2.cpp ):\r\n/*\r\n * hack2.cpp - get UID via CRC32 as REvil ransomware. C++ implementation\r\n * @cocomelonc\r\n * https://cocomelonc.github.io/malware/2023/01/27/malware-analysis-7.html\r\n*/\r\n#include \u003cstdio.h\u003e\r\n#include \u003cwindows.h\u003e\r\n#include \u003cintrin.h\u003e\r\n#include \u003cwincrypt.h\u003e\r\nDWORD crc32(DWORD crc, const BYTE *buf, DWORD len) {\r\n DWORD table[256];\r\n DWORD i, j, c;\r\n for (i = 0; i \u003c 256; i++) {\r\n c = i;\r\n for (j = 0; j \u003c 8; j++) {\r\n if (c \u0026 1)\r\n c = 0xEDB88320 ^ (c \u003e\u003e 1);\r\n else\r\n c = c \u003e\u003e 1;\r\n }\r\n table[i] = c;\r\n }\r\n crc = ~crc;\r\n while (len--)\r\n crc = table[(crc ^ *buf++) \u0026 0xFF] ^ (crc \u003e\u003e 8);\r\n return ~crc;\r\n}\r\nint main(void) {\r\n DWORD volumeSerial, cpuidHash, uid, i;\r\n char volumePath[MAX_PATH];\r\n BYTE cpuidData[16];\r\n DWORD cpuidDataSize = sizeof(cpuidData);\r\n DWORD hashBuffer[4];\r\n HCRYPTPROV hCryptProv;\r\n if (!GetVolumeInformation(NULL, NULL, 0, \u0026volumeSerial, NULL, NULL, NULL, 0)) {\r\n printf(\"failed to get the volume serial number.\\n\");\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 7 of 10\n\nreturn 1;\r\n }\r\n volumeSerial = crc32(0x539, (BYTE *)\u0026volumeSerial, sizeof(volumeSerial));\r\n __cpuid(hashBuffer, 0);\r\n for (i = 0; i \u003c 4; i++)\r\n cpuidData[i] = (BYTE)(hashBuffer[i] \u0026 0xff);\r\n __cpuid(hashBuffer, 1);\r\n for (i = 0; i \u003c 4; i++)\r\n cpuidData[4 + i] = (BYTE)(hashBuffer[i] \u0026 0xff);\r\n cpuidHash = crc32(volumeSerial, cpuidData, cpuidDataSize);\r\n uid = volumeSerial;\r\n uid = (uid \u003c\u003c 32) | cpuidHash;\r\n printf(\"UID: %llx\\n\", uid);\r\n return 0;\r\n}\r\nThis implementation calls GetVolumeInformation to retrieve the volume serial number for the system drive,\r\ncrc32 to build the CRC32 hash, and __cpuid to obtain the value returned by the CPUID assembly instruction.\r\nThe resulting uid is a 64-bit value that combines the serial number of the volume and the CPUID hash.\r\ndemo 2Permalink\r\nLet’s go to see in action. Compile it:\r\nx86_64-w64-mingw32-g++ -O2 hack2.cpp -o hack2.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-https://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 8 of 10\n\nRun it at victim’s machine ( Windows 10 x64 ):\r\nAs you can see, everything is worked perfectly!\r\nOf course, this is just “dirty PoC” of part of the REvil ransomware’s logic.\r\nLet’s go to upload this to VirusTotal:\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 9 of 10\n\nIn this example, 3 of 70 AV engines detect our file as malicious.\r\nhttps://www.virustotal.com/gui/file/871257db59da7bfb9346b120ba165924b60dafb45f3f940c9fb0a739504b29c5/details\r\nLet’s check it via YARA:\r\nyara -w ./crc32.yar -r ./\r\nI hope this post spreads awareness to the blue teamers of this interesting hashing technique, and adds a weapon to\r\nthe red teamers arsenal.\r\nThis is a practical case for educational purposes only.\r\nAV engines evasion techniques - part 5\r\nCRC32\r\nNovel Approach for Worm Detection using Modified Crc32 Algorithm\r\nREvil/Sodinokibi\r\nMailTo\r\nGetVolumeInformation\r\nsource code in github\r\nThanks for your time happy hacking and good bye!\r\nPS. All drawings and screenshots are mine\r\nSource: https://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nhttps://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cocomelonc.github.io/malware/2023/02/02/malware-analysis-7.html"
	],
	"report_names": [
		"malware-analysis-7.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434270,
	"ts_updated_at": 1775791313,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/e52941d08e5123b99fbe66682bbef8ee0eeb04c1.pdf",
		"text": "https://archive.orkl.eu/e52941d08e5123b99fbe66682bbef8ee0eeb04c1.txt",
		"img": "https://archive.orkl.eu/e52941d08e5123b99fbe66682bbef8ee0eeb04c1.jpg"
	}
}