In Part One of this article, we learned about two injection techniques such as remote DLL injection and hollow process injection. In this article, we will learn about Remote Code injection and a hybrid technique of remote DLL injection and remote code injection known as reflective DLL injection.
Remote Code Injection
In Remote code injection, malicious process M writes code into the memory section of legitimate process L and executes it. The code can be shellcode or a PE file. Remote Code Injection works as follows:
- Since malicious process ‘M’ needs to write to legitimate process ‘L,’ it should have appropriate rights to do so. So first process M enables debug privilege (SE_DEBUG_PRIVILEGE).
- Process M then opens a handle to process L using OpenProcess.
- Process M then allocate memory using VirtualAlloc in Process L with PAGE_EXECUTE_READWRITE protection.
- Process M then transfers a block of code to Process L using WriteProcessMemory
- Process M then call CreateRemoteThread to create a thread and points it starting address in Process L where the shifted block of code resides.
We can detect remote code injection using Volatility’s plugin named malfind. Malfind works by identifying the memory sections which have PAGE_EXECUTE_READWRITE protections and have code which is not backed on disk. Also, it goes a step ahead and shows the complete code at that memory page. Let us look at some examples from publicly available Stuxnet image.
As we can see above that memory section has PAGE_EXECUTE_READWRITE and it is not backed by disk (not shown in output but a necessary precondition for Malfind to give output). Also take a look at the hex dump in the section; it has the standard MZ header which corresponds to PE files. Below is the complete disassembled code.
0x1000000 4d DEC EBP
0x1000001 5a POP EDX
0x1000002 90 NOP
0x1000003 0003 ADD [EBX], AL
0x1000005 0000 ADD [EAX], AL
0x1000007 000400 ADD [EAX+EAX], AL
0x100000a 0000 ADD [EAX], AL
0x100000c ff DB 0xff
0x100000d ff00 INC DWORD [EAX]
0x100000f 00b800000000 ADD [EAX+0x0], BH
0x1000015 0000 ADD [EAX], AL
0x1000017 004000 ADD [EAX+0x0], AL
0x100001a 0000 ADD [EAX], AL
0x100001c 0000 ADD [EAX], AL
0x100001e 0000 ADD [EAX], AL
0x1000020 0000 ADD [EAX], AL
0x1000022 0000 ADD [EAX], AL
0x1000024 0000 ADD [EAX], AL
0x1000026 0000 ADD [EAX], AL
0x1000028 0000 ADD [EAX], AL
0x100002a 0000 ADD [EAX], AL
0x100002c 0000 ADD [EAX], AL
0x100002e 0000 ADD [EAX], AL
0x1000030 0000 ADD [EAX], AL
0x1000032 0000 ADD [EAX], AL
0x1000034 0000 ADD [EAX], AL
0x1000036 0000 ADD [EAX], AL
0x1000038 0000 ADD [EAX], AL
0x100003a 0000 ADD [EAX], AL
0x100003c d000 ROL BYTE [EAX], 0x1
0x100003e 0000 ADD [EAX], AL
Malfind does not only look out for only MZ header at the start but also look out for potential injected code. For example, look at the below hex dump, it does not have MZ header at the start but still it has injected code.
Ethical Hacking Training – Resources (InfoSec)
If you have my previous article well on this then you should have recognized that the above injected code calls API which is used for Process Hollowing. Below is the complete disassembled code
0x680000 90 NOP
0x680001 06 PUSH ES
0x680002 6800c60768 PUSH DWORD 0x6807c600
0x680007 002400 ADD [EAX+EAX], AH
0x68000a 6800a50400 PUSH DWORD 0x4a500
0x68000f 00f2 ADD DL, DH
0x680011 0468 ADD AL, 0x68
0x680013 004806 ADD [EAX+0x6], CL
0x680016 0000 ADD [EAX], AL
0x680018 c9 LEAVE
0x680019 0468 ADD AL, 0x68
0x68001b 0029 ADD [ECX], CH
0x68001d 0000 ADD [EAX], AL
0x68001f 0000 ADD [EAX], AL
0x680021 006f00 ADD [EDI+0x0], CH
0x680024 e813000000 CALL 0x68003c
0x680029 5a POP EDX
0x68002a 774d JA 0x680079
0x68002c 61 POPA
0x68002d 7056 JO 0x680085
0x68002f 6965774f665365 IMUL ESP, [EBP+0x77], 0x6553664f
0x680036 6374696f ARPL [ECX+EBP*2+0x6f], SI
0x68003a 6e OUTS DX, BYTE [ESI]
0x68003b 005a51 ADD [EDX+0x51], BL
0x68003e 81 DB 0x81
0x68003f c1 DB 0xc1
Sometimes you might have some hex and disassembled code which looks legit, and there can be false positives from malfind but it can very well a technique known as code wiping employed by a malicious author. Be sure to look at the code of process adjacent memory section using Volatility plugin Volshell.
Reflective DLL Injection
This is a combination of remote DLL injection and remote code injection in a way that DLL is transferred/injected into the legitimate process instead of code but then DLL executes/loads on its own instead of a call to LoadLibrary (which we have seen in Remote DLL injection. Remember?) Which means that DLL is no longer needs to be stored in disk and also does need Windows Loader to load. I hope you can mark the difference of this with remote DLL injection. In remote DLL injection, we have just passed the DLL path as an argument and DLL was residing somewhere on the disk whereas in reflective DLL injection we are moving the whole DLL into the target process memory but since we are not using LoadLibrary then how to execute the DLL loaded into the target process memory. It turns out that we need to find out the entry point to DLL by calculating offset plus the base address of the target image. There is a good project from Stephen Fewer on this here.
So in both part of these articles we have seen four types of code injection namely reflective DLL injection, remote DLL injection, remote code injection and process hollowing.