back to write-ups
PMA April 5, 2025

PMA Lab 19-2: Shellcode Analysis

The file Lab19-02.exe contains a piece of shellcode that will be injected into another process and run. Analyze this file.

pmachapter-19

Lab 19-2

The file Lab19-02.exe contains a piece of shellcode that will be injected into another process and run. Analyze this file.

Analysis

After opening the program in IDA, it seems a straightforward piece of Malware. The very first function that is called (sub_4010B0) takes one parameter which is the string “SeDebugPrivilege”:

image-20250404150111068

With that parameter its kind of obvious what the Malware will do, but inside that function we can confirm it. The malware attempts to enable the SeDebugPrivilege, which allows it to interact with and modify other processes, including those it wouldn’t normally have access to. It does this by retrieving a handle to its own process token using GetCurrentProcess and OpenProcessToken, then looks up the SeDebugPrivilege constant with LookupPrivilegeValueA.

image-20250404150131942

Finally, it calls AdjustTokenPrivileges to enable the privilege. This behavior is typically used to gain elevated access, such as injecting code into or reading memory from protected processes. If successful this function will return 1, otherwise it will return 0:

image-20250404150846786

If sub_4010B0 returns 1, the Malware will call sub_401000, which takes two parameters, of types lpData and int:

image-20250404151343822

The lpData type variable is used in the call to RegQueryValueExA, hence, it will retrieve the data for the specified value:

image-20250404151444895

The registry key that is opened defines the default command executed when a URL using the http protocol is opened. In this case, it’s chrome:

image-20250404152838724

The buffer that received this string is then passed to another two functions (sub_40143D, and sub_401180). The first one is a print function, and the second one is more interesting:

image-20250404153043772

sub_401180 is responsible to launch a process, whose path is received as the first parameter and used as lpCommandLine:

image-20250404153212506

Finally there’s a call to sub_401230. This function takes three parameters:

  • A processID (returned after spawning a process, in this case chrome)
  • An lpBuffer (loc_407030)
  • A dwSize (1A7 bytes - 423 in decimal)

image-20250404153709925

Inside sub_401230 it is possible to see an handle to the process with the PID provided in the first parameter being obtained using OpenProcess, and then VirtualAllocEx is called to allocate an amount of memory provided by the dwSize parameter (in this case 423 bytes).

WriteProcessMemory is called and writes to the address previously allocated the content of lpBuffer. Then a Thread is launched in the remote process provided by the PID (chrome), and the newly written memory address is provided as the lpBaseAddress. This means that something has been written to this memory address and it is being executed by this thread:

image-20250404154230357

This pretty much covers Lab19-02.exe. Now, we can analyze the injected Shellcode. As mentioned earlier, the Shellcode (lpBuffer) written to memory resides in loc_407030:

image-20250404154510783

Attempting to make IDA interpret the content of loc_407030 as code, made possible to recognize a small decode stub. However, there are a couple of instructions that do not make much sense.

Nevertheless, it is possible to understand the technique that the Shellcode is trying to pull-off, which is a jump call. Which means that everything after teh call instruction should be treated as data (the encoded shellcode):

image-20250404173138364

In order to fully analyze the Shellcode I made a small Python script that allowed me to dump the Shellcode using IDA:

image-20250404180043477

Now that the Shellcode has been dumped to disk, we can analyze it using the provided shellcode_launcher.exe:

image-20250404162930761

This opens Ollydbg, which is configured as the “just-in-time debugger”. Advancing on the jump it is possible to reach the beginning of the decode stub:

image-20250404163056296

By placing a breakpoint outside the decode stub, and hitting Run, the Shellcode will be decoded, and EIP points to its start:

image-20250404163402771

This Shellcode is fairly similar to the one in Lab19-01, it manually import functions as detailed here. So, focusing on the different parts of this Shellcode, and its objectives, it is possible to see that it loads LoadLibrary, WSAStartup, WSASocketA, connect, CreateProcessA, GetCurrentProcess, and TerminateProcess.

It’s easy to spot the calls, because they are made by calling addresses that are on the stack (here highlighted with breakpoints):

image-20250404164229746

Focusing on the connect call. Where is the shellcode connecting to?

image-20250404165140912

In the highlighted lines we can see the struct sockaddr_in being pushed into the stack. The values are in little-endian, but the sockaddr_in structure uses network byte order, which is big-endian, so the values need to be converted:

OffsetFieldPushed ValueConvert to Big EndianMeaning
+0sin_family0x0002(AF_INET)
+2sin_port0x12340x3412Port 13330
+4sin_addr0x02C8A8C0C0.A8.C8.02IP Address 192.168.200.2

Although this isn’t the Network range of the Malware Lab I’m using, there’s no need to change the IP Address since accept-all-ips from Remnux is being used. Now that the connection is successful the Shellcode continues to execute and reaches the reverse shell part.

image-20250404171254349

It launches a cmd.exe process using CreateProcessA

image-20250404171356686

Now the remote host can interact with the infected machine via the remote shell:

image-20250404171709548

Questions

1) What process is injected with the shellcode?

The Shellcode injects into the default browser, in this case it was chrome.exe.

2) Where is the shellcode located?

The Shellcode is located in loc_407030.

3) How is the shellcode encoded?

The Shellcode is encoded with a simple XOR, and the key is 0xE7:

image-20250404173210596

4) Which functions does the shellcode manually import?

The Shellcode manually imports the following functions:

  • LoadLibrary
  • WSAStartup
  • WSASocketA
  • connect
  • CreateProcessA
  • GetCurrentProcess
  • TerminateProcess

5) What network hosts does the shellcode do?

The Shellcode launches a reverse shell to 192.168.200.2 on port 13330.