An important point to note is that when an executable image (such as EXE or DLL) is normally loaded into the memory, that memory region is given a memory protection of PAGE_EXECUTE_WRITECOPY(WCX) by the operating system. An application is generally not allowed to allocate a memory with PAGE_EXECUTE_WRITECOPY protection using an API call such as VirtualAllocEx. In other words, if an attacker wants to inject a PE file (such as EXE or DLL) or shellcode, then a memory with a PAGE_EXECUTE_READWRITE(RWX) protection needs be allocated. Normally, you will see that very few memory ranges have a memory protection of PAGE_EXECUTE_READWRITE. A memory range having a protection of PAGE_EXECUTE_READWRITE is not always malicious, because a program may allocate memory with that protection for a legitimate purpose. To detect code injection, we can look for memory ranges containing a memory protection of PAGE_EXECUTE_READWRITE and examine and verify its contents to confirm the maliciousness. To help you understand this, let's take an example of a memory image infected with SpyEye. This malware injects code into a legitimate explorer.exe process (pid 1608). The vadinfo plugin shows two memory ranges in the explorer.exe process having a suspicious memory protection of PAGE_EXECUTE_READWRITE:
$ python vol.py -f spyeye.vmem --profile=Win7SP1x86 vadinfo -p 1608
[REMOVED]
VAD node @ 0x86fd9ca8 Start 0x03120000 End 0x03124fff Tag VadS
Flags: CommitCharge: 5, MemCommit: 1, PrivateMemory: 1, Protection: 6
Protection: PAGE_EXECUTE_READWRITE
Vad Type: VadNone
VAD node @ 0x86fd0d00 Start 0x03110000 End 0x03110fff Tag VadS
Flags: CommitCharge: 1, MemCommit: 1, PrivateMemory: 1, Protection: 6
Protection: PAGE_EXECUTE_READWRITE
Vad Type: VadNone
Just from the memory protection, it is hard to conclude if the preceding memory regions contain any malicious code. To determine if there is any malicious code, we can dump the contents of these memory regions. To display the contents of a memory region, you can use the volshell plugin. The following command invokes volshell (an interactive Python shell) in the context of the explorer.exe process (pid 1608). The db command dumps the content of the given memory address. To get help information and display the supported volshell commands, just type hh() in the volshell. Dumping the contents of the memory address 0x03120000 (the first entry from the preceding vadinfo output) using the db command shows the presence of the PE file. The memory protection of PAGE_EXECUTE_READWRITE and the presence of the PE file is a clear indication that the executable was not normally loaded but was injected into the address space of the explorer.exe process:
$ python vol.py -f spyeye.vmem --profile=Win7SP1x86 volshell -p 1608
Volatility Foundation Volatility Framework 2.6
Current context: explorer.exe @ 0x86eb4780, pid=1608, ppid=1572 DTB=0x1eb1a340
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
>>> db(0x03120000)
0x03120000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ..............
0x03120010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......
0x03120020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x03120030 00 00 00 00 00 00 00 00 00 00 00 00 d8 00 00 00 ................
0x03120040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ........!..L.!Th
0x03120050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is.program.canno
0x03120060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t.be.run.in.DOS.
0x03120070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode....$.......
Sometimes, displaying the contents of a memory region may not be enough to identify malicious code. This is especially true when the shellcode is injected, and in that case, you need to disassemble the content. For instance, if you dump the contents of the address 0x03110000 (the second entry from the preceding vadinfo output) using the db command, you will see the following hex dump. From the output, it is not easy to say if this is a malicious code:
>>> db(0x03110000)
0x03110000 64 a1 18 00 00 00 c3 55 8b ec 83 ec 54 83 65 fc d......U....T.e.
0x03110010 00 64 a1 30 00 00 00 8b 40 0c 8b 40 1c 8b 40 08 .d.0....@..@..@.
0x03110020 68 34 05 74 78 50 e8 83 00 00 00 59 59 89 45 f0 h4.txP.....YY.E.
0x03110030 85 c0 74 75 8d 45 ac 89 45 f4 8b 55 f4 c7 02 6b ..tu.E..E..U...k
0x03110040 00 65 00 83 c2 04 c7 02 72 00 6e 00 83 c2 04 c7 .e......r.n.....
If you suspect that the memory region contains a shellcode, you can use the dis command in volshell to disassemble the code at a given address. From the disassembly output that's shown in the following code, you can probably tell that a shellcode has been injected into this memory region, because it contains valid CPU instructions. To verify if the memory region contains any malicious code, you need to analyze it further in order to determine the context. This is because injected code can also look similar to the legitimate code:
>>> dis(0x03110000)
0x3110000 64a118000000 MOV EAX, [FS:0x18]
0x3110006 c3 RET
0x3110007 55 PUSH EBP
0x3110008 8bec MOV EBP, ESP
0x311000a 83ec54 SUB ESP, 0x54
0x311000d 8365fc00 AND DWORD [EBP-0x4], 0x0
0x3110011 64a130000000 MOV EAX, [FS:0x30]
0x3110017 8b400c MOV EAX, [EAX+0xc]
0x311001a 8b401c MOV EAX, [EAX+0x1c]
0x311001d 8b4008 MOV EAX, [EAX+0x8]
0x3110020 6834057478 PUSH DWORD 0x78740534
0x3110025 50 PUSH EAX
0x3110026 e883000000 CALL 0x31100ae
[REMOVED]