Blog by Saw Win Naung

Official

Finding Malicious Code in Memory: A Digital Forensics Guide


Understanding Memory-Based Attacks

Modern malware increasingly relies on memory-resident techniques to avoid detection. These attacks inject malicious code directly into legitimate processes, making them harder to spot with traditional antivirus solutions. The key to detecting these threats lies in analyzing memory dumps and looking for suspicious patterns in process behavior, memory permissions, and network connections.

Identifying Malicious Processes

Process List Analysis with pslist

The pslist command provides a comprehensive view of all running processes at the time the memory dump was created. This is typically your starting point for any memory analysis investigation.

❯ vol -f basicloading.mem windows.pslist
Volatility 3 Framework 2.5.0
Progress:  100.00               PDB scanning finished
PID     PPID    ImageFileName   Offset(V)       Threads Handles SessionId       Wow64   CreateTime      ExitTime        File output

4       0       System  0xb308f169d040  122     -       N/A     False   2023-09-29 06:28:30.000000      N/A     Disabled
92      4       Registry        0xb308f16c4080  4       -       N/A     False   2023-09-29 06:28:18.000000      N/A     Disabled
300     4       smss.exe        0xb308f471f040  2       -       N/A     False   2023-09-29 06:28:30.000000      N/A     Disabled
416     408     csrss.exe       0xb308f560c2c0  10      -       0       False   2023-09-29 06:28:34.000000      N/A     Disabled
488     408     wininit.exe     0xb308f5893140  1       -       0       False   2023-09-29 06:28:35.000000      N/A     Disabled
496     480     csrss.exe       0xb308f58952c0  13      -       1       False   2023-09-29 06:28:35.000000      N/A     Disabled
584     480     winlogon.exe    0xb308f5904100  6       -       1       False   2023-09-29 06:28:35.000000      N/A     Disabled
624     488     services.exe    0xb308f590c080  7       -       0       False   2023-09-29 06:28:35.000000      N/A     Disabled
648     488     lsass.exe       0xb308f591d0c0  10      -       0       False   2023-09-29 06:28:35.000000      N/A     Disabled

When analyzing process lists, pay attention to these key fields:

Process Tree Analysis with pstree

Understanding parent-child relationships between processes is crucial for spotting suspicious activity. The pstree command visualizes these relationships, making it easier to identify processes that shouldn’t be spawning certain child processes.

❯ vol -f basicloading.mem windows.pstree.PsTree
Volatility 3 Framework 2.5.0
Progress:  100.00               PDB scanning finished
PID     PPID    ImageFileName   Offset(V)       Threads Handles SessionId       Wow64   CreateTime      ExitTime

4       0       System  0xb308f169d040  122     -       N/A     False   2023-09-29 06:28:30.000000      N/A
* 1608  4       MemCompression  0xb308f62d0040  18      -       N/A     False   2023-09-29 06:28:39.000000      N/A
* 92    4       Registry        0xb308f16c4080  4       -       N/A     False   2023-09-29 06:28:18.000000      N/A
* 300   4       smss.exe        0xb308f471f040  2       -       N/A     False   2023-09-29 06:28:30.000000      N/A
416     408     csrss.exe       0xb308f560c2c0  10      -       0       False   2023-09-29 06:28:34.000000      N/A
488     408     wininit.exe     0xb308f5893140  1       -       0       False   2023-09-29 06:28:35.000000      N/A
* 624   488     services.exe    0xb308f590c080  7       -       0       False   2023-09-29 06:28:35.000000      N/A
** 8    624     svchost.exe     0xb308f60ac080  7       -       0       False   2023-09-29 06:28:38.000000      N/A
** 3096 624     svchost.exe     0xb308f69b10c0  6       -       0       False   2023-09-29 06:28:45.000000      N/A
** 4136 624     svchost.exe     0xb308f7592080  5       -       1       False   2023-09-29 06:29:36.000000      N/A
** 1584 624     svchost.exe     0xb308f62cd0c0  3       -       0       False   2023-09-29 06:28:39.000000      N/A
** 6708 624     svchost.exe     0xb308f821c080  12      -       0       False   2023-09-29 06:30:46.000000      N/A
** 1592 624     svchost.exe     0xb308f62d2080  5       -       0       False   2023-09-29 06:28:39.000000      N/A
** 3132 624     svchost.exe     0xb308f69dd080  14      -       0       False   2023-09-29 06:28:45.000000      N/A
** 1092 624     svchost.exe     0xb308f6461080  8       -       0       False   2023-09-29 06:28:41.000000      N/A
*** 4692        1092    sihost.exe      0xb308f6371080  13      -       1       False   2023-09-29 06:29:36.000000      N/A

The tree structure uses asterisks (*) to indicate the depth of parent-child relationships. Look for unusual patterns like:

Identifying Malicious Network Connections

Network Scan Analysis with netscan

Network connections can reveal command and control (C2) communications or data exfiltration attempts. The netscan command shows all network connections associated with processes in the memory dump.

vol -f basicloading.mem windows.netscan
Volatility 3 Framework 2.5.0
Progress:  100.00               PDB scanning finished
Offset  Proto   LocalAddr       LocalPort       ForeignAddr     ForeignPort     State   PID     Owner   Created

0xb308f6c32010  TCPv4   192.168.228.129 52503   172.16.10.100   9001    SYN_SENT        6444    notepad.exe     2023-09-29 06:32:03.000000

Key fields to analyze:

In this example, notepad.exe making a network connection to port 9001 is highly suspicious and warrants further investigation.

Detecting Injected Code

Finding Suspicious Memory Regions with malfind

The malfind command is your primary tool for detecting code injection. It identifies memory regions with suspicious characteristics, particularly those with Read-Write-Execute (RWX) permissions that may contain injected code.

❯ vol -f basicloading.mem windows.malfind
Volatility 3 Framework 2.5.0
Progress:  100.00               PDB scanning finished
PID     Process Start VPN       End VPN Tag     Protection      CommitCharge    PrivateMemory   File output     Hexdump Disasm

6444    notepad.exe     0x2234ec10000   0x2234ec10fff   VadS    PAGE_EXECUTE_READWRITE  1       1       Disabled
fc 48 83 e4 f0 e8 cc 00 .H......
00 00 41 51 41 50 52 48 ..AQAPRH
31 d2 51 56 65 48 8b 52 1.QVeH.R
60 48 8b 52 18 48 8b 52 `H.R.H.R
20 4d 31 c9 48 8b 72 50 .M1.H.rP
48 0f b7 4a 4a 48 31 c0 H..JJH1.
ac 3c 61 7c 02 2c 20 41 .<a|.,.A
c1 c9 0d 41 01 c1 e2 ed ...A....
0x2234ec10000:  cld
0x2234ec10001:  and     rsp, 0xfffffffffffffff0
0x2234ec10005:  call    0x2234ec100d6
0x2234ec1000a:  push    r9
0x2234ec1000c:  push    r8
0x2234ec1000e:  push    rdx
0x2234ec1000f:  xor     rdx, rdx
0x2234ec10012:  push    rcx
0x2234ec10013:  push    rsi
0x2234ec10014:  mov     rdx, qword ptr gs:[rdx + 0x60]
0x2234ec10019:  mov     rdx, qword ptr [rdx + 0x18]
0x2234ec1001d:  mov     rdx, qword ptr [rdx + 0x20]
0x2234ec10021:  xor     r9, r9
0x2234ec10024:  mov     rsi, qword ptr [rdx + 0x50]
0x2234ec10028:  movzx   rcx, word ptr [rdx + 0x4a]
0x2234ec1002d:  xor     rax, rax
0x2234ec10030:  lodsb   al, byte ptr [rsi]
0x2234ec10031:  cmp     al, 0x61
0x2234ec10033:  jl      0x2234ec10037
0x2234ec10035:  sub     al, 0x20
0x2234ec10037:  ror     r9d, 0xd
0x2234ec1003b:  add     r9d, eax
0x2234ec1003e:  loop    0x2234ec1002d

This output shows classic shellcode patterns in notepad.exe, including:

This command shows which pages are memory resident and can dump suspicious memory regions for further analysis.

Common Injection Techniques

1. Shellcode Injection

Shellcode injection is the most basic in-memory technique. The attack follows these steps:

  1. Open a target process (OpenProcess)
  2. Allocate memory in the process (VirtualAllocEx)
  3. Write shellcode payload to the allocated section (WriteProcessMemory)
  4. Create a new thread to execute the shellcode (CreateRemoteThread)

Detection indicators:

Here’s an example of shellcode injection detected by malfind:

6444    notepad.exe     0x2234ec10000   0x2234ec10fff   VadS    PAGE_EXECUTE_READWRITE  1       1       Disabled
fc 48 83 e4 f0 e8 cc 00 .H......
00 00 41 51 41 50 52 48 ..AQAPRH
31 d2 51 56 65 48 8b 52 1.QVeH.R
60 48 8b 52 18 48 8b 52 `H.R.H.R
20 4d 31 c9 48 8b 72 50 .M1.H.rP
48 0f b7 4a 4a 48 31 c0 H..JJH1.
ac 3c 61 7c 02 2c 20 41 .<a|.,.A
c1 c9 0d 41 01 c1 e2 ed ...A....
0x2234ec10000:  cld
0x2234ec10001:  and     rsp, 0xfffffffffffffff0
0x2234ec10005:  call    0x2234ec100d6
0x2234ec1000a:  push    r9
0x2234ec1000c:  push    r8
0x2234ec1000e:  push    rdx
0x2234ec1000f:  xor     rdx, rdx
0x2234ec10012:  push    rcx
0x2234ec10013:  push    rsi
0x2234ec10014:  mov     rdx, qword ptr gs:[rdx + 0x60]
0x2234ec10019:  mov     rdx, qword ptr [rdx + 0x18]
0x2234ec1001d:  mov     rdx, qword ptr [rdx + 0x20]
0x2234ec10021:  xor     r9, r9
0x2234ec10024:  mov     rsi, qword ptr [rdx + 0x50]
0x2234ec10028:  movzx   rcx, word ptr [rdx + 0x4a]
0x2234ec1002d:  xor     rax, rax
0x2234ec10030:  lodsb   al, byte ptr [rsi]
0x2234ec10031:  cmp     al, 0x61
0x2234ec10033:  jl      0x2234ec10037
0x2234ec10035:  sub     al, 0x20
0x2234ec10037:  ror     r9d, 0xd
0x2234ec1003b:  add     r9d, eax
0x2234ec1003e:  loop    0x2234ec1002d

This shows classic shellcode characteristics: PEB manipulation, API hashing, and direct assembly instructions without the MZ header that would indicate a full PE file.

2. Process Hollowing

Process hollowing creates a legitimate process in a suspended state, then replaces its memory with malicious code:

  1. Create the target process (e.g., notepad.exe) in a suspended state
  2. Query the process to extract its base address pointer from the Process Environment Block (PEB)
  3. Read memory pointed to by the image base address to get the actual base address value
  4. Read the PE structure to get the EntryPoint address
  5. Write shellcode to the EntryPoint address and resume thread execution

Detection indicators:

Here’s an example of process hollowing detected by malfind:

1730    smartscreen.exe 0x1ac37560000   0x1ac37577fff   VadS    PAGE_EXECUTE_READWRITE  1       1       Disabled
48 89 54 24 10 48 89 4c H.T$.H.L
24 08 4c 80 44 24 18 4c $.L.D$.L
39 4c 24 20 48 8b 41 28 9L$ H.A(
48 8b 48 08 48 8b 51 50 H.H.H.QP
48 83 c2 f8 48 8b ca 48 H...H..H
08 60 00 56 37 ac 01 00 .`.V7...
00 48 2b c8 48 81 f9 70 .H+.H..p
0f 00 00 76 09 48 c7 c1 ...v.H..
0x1ac37560000:  mov     qword ptr [rsp + 0x10], rdx
0x1ac37560005:  mov     qword ptr [rsp + 8], rcx
0x1ac3756000a:  mov     qword ptr [rsp + 0x18], r8
0x1ac3756000f:  mov     qword ptr [rsp + 0x20], r9
0x1ac37560014:  mov     rax, qword ptr [rcx + 0x28]
0x1ac37560018:  mov     rcx, qword ptr [rax + 8]
0x1ac3756001c:  mov     rdx, qword ptr [rcx + 0x50]
0x1ac37560020:  and     rdx, 0xfffffffffffffff8
0x1ac37560024:  mov     rcx, rdx
0x1ac37560027:  movabs  rax, 0x1ac37560060
0x1ac37560031:  sub     rcx, rax
0x1ac37560034:  cmp     rcx, 0x70f
0x1ac3756003b:  jbe     0x1ac37560046

2700    notepad.exe     0x400000        0x1392fff       VadS    PAGE_EXECUTE_READWRITE  3987    1       Disabled
4d 5a 90 00 03 00 00 00 MZ......
04 00 00 00 ff ff 00 00 ........
b8 00 00 00 00 00 00 00 ........
40 00 00 00 00 00 00 00 @.......
00 00 00 00 00 00 00 00 ........
00 00 00 00 00 00 00 00 ........
00 00 00 00 80 00 00 00 ........
0x400000:       pop     r10
0x400002:       nop
0x400003:       add     byte ptr [rbx], al
0x400005:       add     byte ptr [rax], al
0x400007:       add     byte ptr [rax + rax], al
0x40000a:       add     byte ptr [rax], al

This example shows process hollowing characteristics: the notepad.exe process has an MZ header at its base address (0x400000), but the memory region has RWX permissions, indicating the original executable has been replaced with malicious code while maintaining the PE structure.

3. Reflective DLL Injection

Reflective DLL injection uses a self-mapping DLL that loads itself into memory without relying on the Windows loader:

  1. Open target process and allocate memory
  2. Copy the DLL into the allocated memory
  3. Copy function name hash and arguments after the DLL
  4. Copy bootstrap shellcode that calls the reflective loader
  5. Create a remote thread using the shellcode address as entry point

Detection indicators:

Here’s an example of what reflective DLL injection looks like in malfind output:

7516    notepad.exe     0x1f67c8c0000   0x1f67c91afff   VadS    PAGE_EXECUTE_READWRITE  91      1       Disabled
4d 5a 90 00 03 00 00 00 MZ......
04 00 00 00 ff ff 00 00 ........
b8 00 00 00 00 00 00 00 ........
40 00 00 00 00 00 00 00 @.......
00 00 00 00 00 00 00 00 ........

The key indicator here is the MZ header (4d 5a) at the beginning of the memory region, which is the signature of a Windows PE (Portable Executable) file. This suggests that a complete DLL has been loaded into memory through reflective injection, rather than just shellcode.


Reference: [Process Injection Detection with Malfind](https://www.linkedin.com/pulse /process-injection-detection-malfind-britton-manahan/) by Britton Manahan