{
	"id": "8a64aa27-c7e2-45d7-9e5b-28b3a8ee5701",
	"created_at": "2026-04-06T00:21:17.547676Z",
	"updated_at": "2026-04-10T03:20:55.720532Z",
	"deleted_at": null,
	"sha1_hash": "061d77d0b1e20594063859088fa456371a94a6ed",
	"title": "A Deep Dive Into IcedID Malware: Part I - Unpacking, Hooking and Process Injection",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1898793,
	"plain_text": "A Deep Dive Into IcedID Malware: Part I - Unpacking, Hooking\r\nand Process Injection\r\nBy Kai Lu\r\nPublished: 2019-07-09 · Archived: 2026-04-05 15:29:55 UTC\r\nFortiGuard Labs Threat Analysis Report Series\r\nIcedID is a banking trojan which performs web injection on browsers and acts as proxy to inspect and manipulate\r\ntraffic. It steals information, such as credentials, from victims. It then sends that stolen information to a remote\r\nserver.\r\nRecently, the FortiGuard Labs team started to investigate some IcedID samples. In this series of blogs, I will\r\nprovide a detailed analysis of a new IcedID malware sample. The entire detailed analysis is divided into three\r\nparts.\r\nPart I: Unpacking, Hooking, and Process Injection\r\nPart II: Analysis of the core IcedID Payload (Parent process)\r\nPart III: Analysis of the child processes\r\nThis blog is Part I below. Let’s dive in.\r\n0x01 Malicious PE Executable\r\nThe sample being analyzed is a PE executable, and is most commonly distributed by a compromised Office file.\r\nThe following image is the process tree after executing the PE file. We can see that this sample of IcedID\r\neventually creates a svchost.exe parent process and three svchost.exe child processes. In addition, it can deliver a\r\nTrickbot payload, highlighted in red. In this series of blogs, the analysis of the Trickbot payload won’t be covered.\r\nWe will only focus on how IcedID works internally. \r\nFigure 1. The process tree after executing the IcedID sample\r\nAs shown in Figure 1, the PE executable first launches itself with a command line parameter “-q=xxxxxxxxxx”.\r\nThis new process then continues by launching a svchost.exe process. Once the first svchost.exe process is\r\nlaunched, the previous two processes exit. Finally, this svchost.exe parent process then launches three svchost.exe\r\nprocesses.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 1 of 9\n\n0x02 Unpacking PE Executable\r\nWe can now start to dynamically analyze the PE execution. After tracing a few steps from the entry point, the\r\nprogram goes into the function sub_00415CAE() as follows.\r\nFigure 2. Jump to the trampoline code\r\nIn the trampoline code, it is used for decrypting the code segment. Eventually, it can jump to the real entry point of\r\nthe program. At that point, the unpacking of the PE executable is complete.\r\nFigure 3. Jump back to the real entry point 0x401000\r\nThe following is the pseudo code of the real entry point of the program.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 2 of 9\n\nFigure 4. The pseudo code of the real entry point\r\nHere is a list of the key functions:\r\n1. Check if the command line parameter starts with “-q=”. If yes, it jumps to step 2. Otherwise, it jumps to\r\nstep 3.\r\n2. Create the svchost.exe process and perform process injection.\r\n3. Create a new process with a TSC parameter (“-q=xxxxxxxxx”).\r\nWe ran this sample without any parameters so it could go into the third step (sub_4012E9).\r\nFigure 5. The function sub_4012E9()\r\nAfter performing the rdtsc instruction, the return value is converted into a string as a parameter of the new process\r\nexecution. Next, the program sets an environment variable in the process context. The name of the variable is the\r\ncommand line parameter without the prefix “-q=”.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 3 of 9\n\nFigure 6. Set an environment variable in process context\r\nFinally, it invokes the CreateProcessA function to create itself with a parameter.\r\nNext, we will continue the analysis with the new running process.\r\n0x03 Hooking Technique and Process Injection\r\nAfter launching the new process, the program goes to the real entry point of the program, as shown in Figure 4. At\r\nthis point, the check_parameter() function returns TRUE because the command line parameter starts with “-q=”. It\r\nthen goes to the sub_40124A() function.\r\nFigure 7. The pseudo code of sub_40124A()\r\nIn the function hook_NtCreateUserProcess(), it first invokes the function NtProtectVirtualMemory to change the\r\nprotection of the first five bytes of the function NtCreateUserProcess to PAGE_EXECUTE_READWRITE. It then\r\nmodifies those five bytes with a JMP instruction. Finally, it again invokes the function NtProtectVirtualMemory to\r\nrestore protection to the first five bytes.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 4 of 9\n\nFigure 8. Hooking the function NtCreateUserProcess\r\nThe following is the assembly code of the function NtCreateUserProcess hooked.\r\nFigure 9. The assembly code of the function NtCreateUserProcess hooked\r\nInside the function CreateProcessA, the code invokes the low-level API NtCreateUserProcess. After the function\r\nCreateProcessA is invoked in Figure 7, the program goes to the trampoline code sub_4010B7(). The following is\r\nthe pseudo code of the trampoline code.\r\nFigure 10. The trampoline pseudo code of NtCreateUserProcess hooked\r\nThe following list is what the trampoline code actually does.\r\n1. Unhooks the function NtCreateUserProcess.\r\n2. Calls the function NtCreateUserProcess, which performs the main work of creating a new process.\r\n3. Decompresses the buffer using RtlDecompressBuffer.\r\n4. Performs process injection into the svchost.exe process and hooks RtlExitUserProcess in the process space\r\nof svchost.exe.\r\nLet’s take a closer look at step four. The following is the pseudo code of the function sub_401745() in that step.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 5 of 9\n\nFigure 11. Perform process injection into the svchost.exe process and hook its RtlExitUserProcess\r\nIt first uses NtAllocateVirtualMemory to allocate the memory region in the remote process space(svchost.exe).\r\nNext, it uses ZwWriteVirutalMemory to perform the code injection into the memory region in the svchost.exe\r\nprocess. \r\nFigure 12. Process injection into in svchost.exe process\r\nIt then sets up a hook for the RtlExitUserProcess API in the process space of svchost.exe. It should be noted that\r\nthere is a little difference between hooking RtlExitUserProcess and hooking NtCreateUserProcess in Figure 8. The\r\nformer is to hook the API of remote process space, while the latter is to hook the API in its current process space.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 6 of 9\n\nFigure 13. Hook RtlExitUserProcess\r\nThe assembly code of the hooked RtlExitUserProcess is shown in Figure 14. \r\nFigure 14. The hooked RtlExitUserProcess in svchost.exe process\r\nAs shown in Figure 7, the process svchost.exe was created without a parameter. It could immediately exit if\r\nrunning svchost.exe without parameter, and after it exits, it could invoke the low-level API RtlExitUserProcess.\r\nBecause IcedID hooks the RtlExitUserProcess, it could jump to the trampoline code to execute the IcedID\r\npayload.\r\nThe injected memory regions in the remote process svchost.ext are shown in Figure 15. We can see that two\r\nmemory regions have been injected. The code segment is stored in the memory region(0xa1000 ~ 0xa7000).\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 7 of 9\n\nFigure 15. The injected memory regions of svchost.exe process\r\nAs shown in Figure 14, it jumps to 0xA2B2D, which is in memory region(0xA0000 ~ 0xAC000). The offset of\r\nthe trampoline code from this memory region is 0x2B2D.\r\n0x03 Conclusion\r\nWe have walked through how to unpack the IcedID malware, hooking, and process injection techniques used by\r\nIcedID, as well as how to execute the IcedID payload. In the next blog, I will provide a deep analysis of the\r\nIcedID payload (0xA2B2D). \r\n0x04 Solution\r\nThis malicious PE file has been detected as “W32/Kryptik.GTSU!tr” by the FortiGuard AntiVirus service.\r\n0x05 Reference\r\nSHA256 Hash:\r\nPE executable (b8113a604e6c190bbd8b687fd2ba7386d4d98234f5138a71bcf15f0a3c812e91)\r\nLearn more about FortiGuard Labs and the FortiGuard Security Services portfolio. Sign up for our weekly\r\nFortiGuard Threat Brief. \r\nRead about the FortiGuard Security Rating Service, which provides security audits and best practices.\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 8 of 9\n\nSource: https://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nhttps://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one.html"
	],
	"report_names": [
		"icedid-malware-analysis-part-one.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434877,
	"ts_updated_at": 1775791255,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/061d77d0b1e20594063859088fa456371a94a6ed.pdf",
		"text": "https://archive.orkl.eu/061d77d0b1e20594063859088fa456371a94a6ed.txt",
		"img": "https://archive.orkl.eu/061d77d0b1e20594063859088fa456371a94a6ed.jpg"
	}
}