{
	"id": "0282048c-bab2-4e5d-9fa9-48a89f9b192b",
	"created_at": "2026-04-06T00:10:25.557138Z",
	"updated_at": "2026-04-10T03:21:56.10329Z",
	"deleted_at": null,
	"sha1_hash": "daf80dcda007b9e1dcec8cf9cafc26a0c6c99cd0",
	"title": "Malware development trick - part 36: Enumerate process modules. Simple C++ example.",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2027417,
	"plain_text": "Malware development trick - part 36: Enumerate process modules.\r\nSimple C++ example.\r\nBy cocomelonc\r\nPublished: 2023-09-25 · Archived: 2026-04-05 22:31:12 UTC\r\n3 minute read\r\n﷽\r\nHello, cybersecurity enthusiasts and white hackers!\r\nToday, this post is the result of my own research on another popular malware development trick: get list of\r\nmodules of target process.\r\nLet’s say we created successfully DLL injection to process. How to check if DLL in list of modules of our\r\nprocess?\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 1 of 11\n\npractical examplePermalink\r\nFirst of all, we just use one of the methods to find target process PID. For example I used this one:\r\ntypedef NTSTATUS (NTAPI * fNtGetNextProcess)(\r\n _In_ HANDLE ph,\r\n _In_ ACCESS_MASK DesiredAccess,\r\n _In_ ULONG HandleAttributes,\r\n _In_ ULONG Flags,\r\n _Out_ PHANDLE Newph\r\n);\r\nint findMyProc(const char * procname) {\r\n int pid = 0;\r\n HANDLE current = NULL;\r\n char procName[MAX_PATH];\r\n // resolve function address\r\n fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle(\"ntdll.dll\"), \"NtGet\r\n // loop through all processes\r\n while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, \u0026current)) {\r\n GetProcessImageFileNameA(current, procName, MAX_PATH);\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 2 of 11\n\nif (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {\r\n pid = GetProcessId(current);\r\n break;\r\n }\r\n }\r\n return pid;\r\n}\r\nThen, just use Module32First and Module32Next functions from Windows API.\r\n// function to list modules loaded by a specified process\r\nint listModulesOfProcess(int pid) {\r\n HANDLE mod;\r\n MODULEENTRY32 me32;\r\n mod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);\r\n if (mod == INVALID_HANDLE_VALUE) {\r\n printf(\"CreateToolhelp32Snapshot error :(\\n\");\r\n return -1;\r\n }\r\n me32.dwSize = sizeof(MODULEENTRY32);\r\n if (!Module32First(mod, \u0026me32)) {\r\n CloseHandle(mod);\r\n return -1;\r\n }\r\n \r\n printf(\"modules found:\\n\");\r\n printf(\"name\\t\\t\\t base address\\t\\t\\tsize\\n\");\r\n printf(\"=================================================================================\\n\");\r\n do {\r\n printf(\"%#25s\\t\\t%#10llx\\t\\t%#10d\\n\", me32.szModule, me32.modBaseAddr, me32.modBaseSize);\r\n } while (Module32Next(mod, \u0026me32));\r\n CloseHandle(mod);\r\n return 0;\r\n}\r\nAs you can see, the code is a bit similar to the PID search logic with CreateToolHelp32Snapshot ,\r\nProcess32First and Process32Next .\r\nSo, the full source code is looks like this ( hack.c ):\r\n/*\r\n * hack.c - get the list of modules of the process. C++ implementation\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 3 of 11\n\n* @cocomelonc\r\n * https://cocomelonc.github.io/malware/2023/09/25/malware-tricks-36.html\r\n*/\r\n#include \u003cwindows.h\u003e\r\n#include \u003cstdio.h\u003e\r\n#include \u003cwinternl.h\u003e\r\n#include \u003ctlhelp32.h\u003e\r\n#include \u003cshlwapi.h\u003e\r\n#include \u003cpsapi.h\u003e\r\n#pragma comment(lib, \"ntdll.lib\")\r\n#pragma comment(lib, \"shlwapi.lib\")\r\ntypedef NTSTATUS (NTAPI * fNtGetNextProcess)(\r\n _In_ HANDLE ph,\r\n _In_ ACCESS_MASK DesiredAccess,\r\n _In_ ULONG HandleAttributes,\r\n _In_ ULONG Flags,\r\n _Out_ PHANDLE Newph\r\n);\r\nint findMyProc(const char * procname) {\r\n int pid = 0;\r\n HANDLE current = NULL;\r\n char procName[MAX_PATH];\r\n // resolve function address\r\n fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle(\"ntdll.dll\"), \"NtGet\r\n // loop through all processes\r\n while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, \u0026current)) {\r\n GetProcessImageFileNameA(current, procName, MAX_PATH);\r\n if (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {\r\n pid = GetProcessId(current);\r\n break;\r\n }\r\n }\r\n return pid;\r\n}\r\n// function to list modules loaded by a specified process\r\nint listModulesOfProcess(int pid) {\r\n HANDLE mod;\r\n MODULEENTRY32 me32;\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 4 of 11\n\nmod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);\r\n if (mod == INVALID_HANDLE_VALUE) {\r\n printf(\"CreateToolhelp32Snapshot error :(\\n\");\r\n return -1;\r\n }\r\n me32.dwSize = sizeof(MODULEENTRY32);\r\n if (!Module32First(mod, \u0026me32)) {\r\n CloseHandle(mod);\r\n return -1;\r\n }\r\n \r\n printf(\"modules found:\\n\");\r\n printf(\"name\\t\\t\\t base address\\t\\t\\tsize\\n\");\r\n printf(\"=================================================================================\\n\");\r\n do {\r\n printf(\"%#25s\\t\\t%#10llx\\t\\t%#10d\\n\", me32.szModule, me32.modBaseAddr, me32.modBaseSize);\r\n } while (Module32Next(mod, \u0026me32));\r\n CloseHandle(mod);\r\n return 0;\r\n}\r\nint main(int argc, char* argv[]) {\r\n int pid = 0; // process ID\r\n pid = findMyProc(argv[1]);\r\n printf(\"%s%d\\n\", pid \u003e 0 ? \"process found at pid = \" : \"process not found. pid = \", pid);\r\n if (pid != 0)\r\n listModulesOfProcess(pid);\r\n return 0;\r\n}\r\nYou can use this code to check if a DLL is in the list of modules of the target process.\r\ndemoPermalink\r\nLet’s go to see this logic in action.\r\nCompile it:\r\nx86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sec\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 5 of 11\n\nThen, open target process in the victim’s machine:\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 6 of 11\n\nAnd just run our hack.exe :\r\n.\\hack.exe mspaint.exe\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 7 of 11\n\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 8 of 11\n\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 9 of 11\n\nAlso, check with DLL injection logic:\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 10 of 11\n\nAs you can see, everything is worked perfectly! =^..^=\r\nKeep in mind that this code may have limitations and dependencies on specific Windows APIs. Additionally, it\r\nrelies on the process name for identification, which may not be unique.\r\nThis trick is used by 4H RAT and Aria-body in the wild.\r\nI hope this post spreads awareness to the blue teamers of this interesting malware dev technique, and adds a\r\nweapon to the red teamers arsenal.\r\nFind process ID by name and inject to it\r\nFind PID via NtGetNextProcess\r\n4H RAT\r\nAria-body\r\nsource code in github\r\nThis is a practical case for educational purposes only.\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/09/25/malware-trick-36.html\r\nhttps://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cocomelonc.github.io/malware/2023/09/25/malware-trick-36.html"
	],
	"report_names": [
		"malware-trick-36.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434225,
	"ts_updated_at": 1775791316,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/daf80dcda007b9e1dcec8cf9cafc26a0c6c99cd0.pdf",
		"text": "https://archive.orkl.eu/daf80dcda007b9e1dcec8cf9cafc26a0c6c99cd0.txt",
		"img": "https://archive.orkl.eu/daf80dcda007b9e1dcec8cf9cafc26a0c6c99cd0.jpg"
	}
}