PMA Lab 19-1: Shellcode Analysis
Analyze the file Lab19-01.bin using shellcodelauncher.exe.
Lab 19-1
Analyze the file Lab19-01.bin using shellcode_launcher.exe.
Analysis
For this exercise I’ll use Ollydbg, since I couldn’t get x32dbg to run as a “just-in-time debugger”. In order to start the exercise we need to execute shellcode_launcher.exe as follows:
shellcode_launcher.exe -i Lab19-01.bin -bp

Right away, Ollydbg opens and sets a breakpoint at the address 00350000, as mentioned in the command line output. Nothing really interesting so far, just the breakpoint and a jump to 00350100:

As it is possible to see in the following image, there’s a big “nop-sled” which actually doesn’t use NOPs, but in a way its exactly the same, they have no impact in the code.

These instructions start incrementing ecx, and in the end ecx is set to zero with a xor ecx, ecx. After that we see a decode stub. The code moves to CX the value 18D (it will be used a size counter). Then there’s an unconditional jump, followed by a call. When the call is made, the address of the next instruction is pushed into the stack. The call instruction moves EIP to 00350308:

This is a rather simple decoding stub that uses the combination of call and pop, to locate itself in memory. The stub does the following:
- Obtains the encoded shellcode address using pop ESI;
- Pushes ESI to the stack, and then moves it to EDI. EDI will be used as a destination register, which means the shellcode will be decoded on top of itself (same address);
- ESI is loaded into AL using the instruction lods, this instruction moves the pointer to the string forward;
- The byte currently in AL is subtracted 41 (sub AL, 41), and then shifts DL to the left 4 bits (SHL DL, 4);
- Then, lods is called again, remember that the last lods instruction moved the pointer forward. Again this instruction loads ESI into AL;
- This time, AL is subtracted 41 (sub AL, 41), and added DL (ADD AL, DL);
- The stos copies the data item from AL, AX or EAX into EDI;
- The size counter (ecx) is decremented, and it will loop, by jumping back to 00350308, until ecx is zero.
This Stub is picking up the buffer that starts at 00350324, and every 2 encoded bytes become 1 decoded byte. Each decoded byte is the sum of the high nibble of the odd bytes and the low nibble of the even bytes.
At the end of the loop, the shellcode will be decoded, and the retn instruction will jump to it.

This Shellcode uses the same technique as the decoder, there’s an unconditional jump, towards a call instruction that will basically push the following address (00350469) to the stack:

When EIP gets to the address that was called, Ollydbg recognizes the string “URLMON”. Address 00350469, as seen in the previous image points to the beginning of the following bytes “55 52 4C 4D 4F 4E 00” (URLMON and a Null byte terminating the string):

This string is going to be moved to EBX (pop ebx), and there’s a call to 0035039E:

This function tries to look for the base address of kernel32.dll.
First, it gets a pointer to PEB through TEB (highlighted in yellow), and then accesses PEB_LDR_DATA (highlighted in red). The test eax, eax and the jump at 003503A7 will cause an infinite loop if a version of Win9x is detected.
Assuming the infected machine is running a supported version (Windows Vista or earlier), the second LDR_DATA_TABLE_ENTRY in the InInitializationOderLinks linked list is obtained. After that, EAX gets LDR_DATA_TABLE_ENTRY.DllBase (highlighted in blue).
Finally, the function will return. And start executing a function that is looking for an exported function using a hash. It will load the dllBase, and get an offset to the PE signature, and then loop over all the symbols, hashing them and comparing to the hash

It is possible to see in the stack a big string (the hash) that is being used in the string compare:

When this function finds the symbol that matches the hash, EIP will reach 0035037C. Here the address of the function the Shellcode is looking for in kernel32.dll is obtained using the AddressOfOrdinals array and the AddressOfFunctions array:

All of this is explained in Pages 413 through 420 of PMA.
At some point it is possible to see a path being pushed into the stack. Part of that path is obtained by calling GetSystemDirectoryA:

The full path can be seen in the following image:

That path is used as a parameter to a call to URLDownloadToFileA. EAX holds the url being queried:

Using InetSim it is possible to receive the HTTP Request:

It is also possible to see that the Downloaded file is executed:

This is done by calling WinExec:

Finally, the shellcode obtains a handle to the current process:

And terminates the process:

Questions
1) How is the Shellcode encoded?
The Shellcode is encoded with a custom base-41-like encoding to stay within printable ASCII range. This Stub is picking up the buffer that starts at 00350324, and every 2 encoded bytes become 1 decoded byte. Each decoded byte is the sum of the high nibble of the odd bytes and the low nibble of the even bytes.even bytes.
2) Which function does the shellcode manually import?
There are several functions that the shellcode manually imports. It is easy to spot them after the Shellcode being decoded, since they will all be called with addresses that are pushed into the stack:

In order, the functions that the shellcode manually import are:
-
LoadLibraryA
-
GetSystemDirectoryA
-
URLDownloadToFileA
-
WinExec
-
GetCurrentProcess
-
TerminateProcess
3) What network host does the shellcode communicate with?
The Network host used by the shellcode is http://www.practicalmalwareanalysis.com/shellcode/annoy_user.exe
4) What filesystem residue does the shellcode leave?
The Shellcode leaves a file on the filesystem (C:\Windows\system32\1.exe), which is the payload that has been downloaded and executed:

5) What does the shellcode do?
This Shellcode finds kernel32.dll in memory, and manually imports some functions. Then it downloads a file from a C2 server and execute it.