A forum for reverse engineering, OS internals and malware analysis 

Forum for analysis and discussion about malware.
 #1175  by Evilcry
 Sat May 29, 2010 5:57 am
Hi,

Some day ago ( 2010/05/24 ) appeared in the various malware collector a set of websites compromised by Eleonore Exploits pack v1.4.1 this is the evidence of Eleonore infection:

* XXXXXXX.com/el2/
* XXXXXXX.com/el2/stat.php
* XXXXXXX.com/el2/load.php?spl=mdac&h=

Where stat.php belongs to the Control Panel and load.php delivers the SpyEye variant.
Dropped executable is named load.exe, let's observe its PE Structure:

FileName: load.exe
MD5: E8268FB6853E8B5A5E0F213873651D28
SHA-1: DFFD9D8AB989F94EFA30575B37C4A078E50DC821

Image

As you can see between sections we have .edata, the usual name of the section that belongs to the Export Directory, so let's observe this last one:

Image

The Import Directory presents two modules kernel32.dll and user32.dll between the classical imports we can see:

* CreateSemaphoreW
* FindResourceA

Especially the last one suggests that some of resources stored into the executable will be extracted and processed (usually processing means one or more Decryption Routines)

Image

RCData contains a block of data that appears to be encrypted, with good approsimation this resource entry will be the one that contains some embedded executable. PE Inspection is now complete we can move to disam && debugging.

Here the EntryPoint
Code: Select all
.text:0040101C start:
.text:0040101C                 push    ebp
.text:0040101D                 mov     ebp, esp
.text:0040101F                 sub     esp, 64h
.text:00401022                 mov     [ebp-4], esi
.text:00401025                 mov     edi, [ebp-38h]
.text:00401028                 mov     [ebp-34h], edx
.text:0040102B                 mov     [ebp-50h], ebx
.text:0040102E                 dec     ebx
.text:0040102F                 inc     ebx
.text:00401030                 inc     esi
Execution passes also through the two export functions, by performing a layer of decryption and finally landing here:
Code: Select all
.text:004011C9                 mov     ecx, 408634h
.text:004011CE                 push    ecx
.text:004011CF                 xor     edx, [ebp-10h]
.text:004011D2                 retn
Flow jump to 408634 that is the routine preciously decrypted.
Code: Select all
00408634   \55              PUSH EBP
00408635    8BEC            MOV EBP,ESP
00408637    83EC 3C         SUB ESP,3C
0040863A    8975 FC         MOV DWORD PTR SS:[EBP-4],ESI
0040863D    55              PUSH EBP
0040863E    50              PUSH EAX
0040863F    C70424 00000000 MOV DWORD PTR SS:[ESP],0
[b]00408646    E8 09000000     CALL 00408654        ;This call Cause an Exception[/b]
[b]0040864B    8B6424 08       MOV ESP,DWORD PTR SS:[ESP+8] ;Here starts ExceptionHandler[/b]
0040864F    E9 1E000000     JMP 00408672
00408654    33C0            XOR EAX,EAX
00408656    64:FF30         PUSH DWORD PTR FS:[EAX]  
[b]00408659    64:8920         MOV DWORD PTR FS:[EAX],ESP ;Install Exception Handler[/b]
0040865C    EB 03           JMP SHORT 00408661
..
00408678    FF0424          INC DWORD PTR SS:[ESP]
0040867B    813C24 59050000 CMP DWORD PTR SS:[ESP],559
00408682  ^ 0F82 BEFFFFFF   JB 00408646


In the latest instructions it's installed an Exception Hadler placed at 0040864B, this piece of code works as a second layer of decryption, but this time is performed in a little different way, we have a SEH that corresponds to the body of the decryption routine, immediately before this 'body' we have a call which causes an exception, this last one raises the core decryption and exits, at the end we have the conditional check of the cyle and if does not match, starts a new iteration that causes again an Exception.

This decryption loop was precisely coded to Visually Fool the Analyst, because if we do not place a break point into the handler, execution flow appears to be a classical loop that jumps after the call a block of instructions. In practice the 'body' is executed but without a breakpoint inside you can't fully trace the code.

By prosecuting analysis, what emerges is the massive usage of layer of encryption, the previously SEH Loop, decoded another block and inside we have another decryption loop. Finally we land here:
Code: Select all
004087F7 E8 02000000 CALL 004087FE
Inside the call
Code: Select all
0040881B    2B4D F8         SUB ECX,DWORD PTR SS:[EBP-8]
0040881E    81E8 68384000   SUB EAX,OFFSET load.00403868
00408824    81C0 0A344000   ADD EAX,OFFSET load.0040340A
0040882A    50              PUSH EAX
0040882B    EB 14           JMP SHORT 00408841

00408841    C3              RETN  ;Jump to 0040839E (the latest decoded block)

The essential scope of this decrypted piece of code is to extract from resources another block and successively decode it, by allocating a block of memory. It's important to say that analysis is harder because presents a good level of junk code. Let's observe a block of decrypted data:

Image

Carefully observe ASCII in the red circles, there are clear evidences of the PE nature of this block of code, that presents a low level on encryption. After dumping it, the obfuscated executable, is placed again in memory and deobfuscated, emerges as should be obvious an UPX packed one. At this point load.exe obtains the EntryPoint of this new executable (it's trivial Optional Header->AddressOfEntryPoint)
Execution now jumps to the new executable and after decrypting a block of code, builds by hand an Import Address Table.

As usual, after data block decoding let's see what we meet:
Code: Select all
0040221F    68 00000040     PUSH 40000000
00402224    68 00080000     PUSH 800               ;LOCALE_SYSTEM_INFO
00402229    68 5B1F4000     PUSH 401F5B       ;Callback's Address
[b]0040222E    FF15 9C804000   CALL DWORD PTR DS:[40809C] ;EnumTimeFormatsA[/b]
00402234    6A 00           PUSH 0
00402236    FF15 AC804000   CALL DWORD PTR DS:[4080AC] ;ExitProcess


Here emerges a truly interesting element, the malicious usage of EnumTimeFormats function, this is an original element in the common malware, due to the fact that is rarely/uniquely used. To understand how can be badly used this API let's what it does:

Enumerates the time formats that are available for a locale specified by identifier.
Code: Select all
BOOL EnumTimeFormats(
  __in  TIMEFMT_ENUMPROC lpTimeFmtEnumProc,
  __in  LCID Locale,
  __in  DWORD dwFlags
);

SpyEye overworks the fact that EnumTimeFormats executes a Callback. The first effect of this method is merely visual, done to fool analysts, because if you execute normally this call, suddenly execution ends, by checking SEH nothing seems to happen because does not occur any Execption. What we have to do is to place a breakpoint on the Callback address 00401F5B, executing the call and suddenly execution in blocked by the BP.

We are now inside the Callback, that presents an interesting structure, that will be reversed in the second episode.

Regards,
Giuseppe 'Evilcry' Bonfa
 #1179  by Evilcry
 Sat May 29, 2010 1:20 pm
Thank You :)

Here the second part of analysis, that has the common characteristics of usual malware that injects malicious code into explorer.exe and finally in attachement the sample..

In the latest episode we discovered that EnumTimeFormats was maliciously used to execute code by overworking its first parameter that is a CallBack. We have to insert a BreakPoint into to the address specified in the first parameter of EnumTimeFormats and execute it, when execution stops we are in the Callback; let's see what happens here:
Code: Select all
00401F5B    55              PUSH EBP
00401F5C    8BEC            MOV EBP,ESP
..
00401F67    6A 00           PUSH 0
00401F69    6A 00           PUSH 0
00401F6B    3E:FF15 A880400 CALL DWORD PTR DS:[4080A8] ;SetThreadAffinityMask

00401FC1    57              PUSH EDI
00401FC2    57              PUSH EDI
00401FC3    E8 15F5FFFF     CALL 004014DD  ;Inside This Call -> follows
Inside we meet another call that builds the string 'user32.dll'

Code: Select all
00403530    E8 F0030000     CALL 00403925  ;Obtain ntdll BaseAddress
00403535    8985 88FCFFFF   MOV DWORD PTR SS:[EBP-378],EAX
0040353B    83A5 ACFCFFFF 0 AND DWORD PTR SS:[EBP-354],00000000
00403542    C685 98FCFFFF 4 MOV BYTE PTR SS:[EBP-368],4C
00403549    C685 99FCFFFF 6 MOV BYTE PTR SS:[EBP-367],64
00403550    C685 9AFCFFFF 7 MOV BYTE PTR SS:[EBP-366],72
00403557    C685 9BFCFFFF 4 MOV BYTE PTR SS:[EBP-365],4C
0040355E    C685 9CFCFFFF 6 MOV BYTE PTR SS:[EBP-364],6F
00403565    C685 9DFCFFFF 6 MOV BYTE PTR SS:[EBP-363],61
0040356C    C685 9EFCFFFF 6 MOV BYTE PTR SS:[EBP-362],64
00403573    C685 9FFCFFFF 4 MOV BYTE PTR SS:[EBP-361],44
0040357A    C685 A0FCFFFF 6 MOV BYTE PTR SS:[EBP-360],6C
00403581    C685 A1FCFFFF 6 MOV BYTE PTR SS:[EBP-35F],6C
00403588    C685 A2FCFFFF 0 MOV BYTE PTR SS:[EBP-35E],0
builds the string LdrLoadDll and successively obtains CsrAllocateCaptureBuffer


This function allocates a buffer from the Port Memory section for use by the client in capture arguments into Port Memory. In addition to specifying the size of the data that needs to be captured, the caller needs to specify how many pointers to captured data will be passed. Pointers can be located in either the request message itself, and/or the capture buffer. The return value is a pointer to the capture buffer header.

Successively obtain the following function addresses (but not used except someone)

CsrAllocateMessagePointer
CsrCaptureMessageMultiUnicodeStringsInPlace
CsrCaptureMessageString
CsrCaptureTimeout
CsrClientCallServer
CsrClientConnectToServer
CsrFreeCaptureBuffer
CsrGetProcessId
CsrProbeForRead
CsrProbeForWrite
CsrSetPriorityClass
DbgBreakPoint
DbgPrint
DbgPrintEx
DbgPrintReturnControlC
DbgPrompt
DbgQueryFilterState
DbgSetFilterState
DbgUi*

Each address is stored, this means that SpyEye builds an Import Address Table on fly.

Code: Select all
004035EE    50              PUSH EAX
004035EF    B8 00000000     MOV EAX,0
004035F4    50              PUSH EAX
004035F5    B8 00000000     MOV EAX,0
004035FA    50              PUSH EAX
004035FB    FF95 ACFCFFFF   CALL DWORD PTR SS:[EBP-354] ;LdrLoadDll

LdrLoadDll is used insted LoadLibrary that is over-checked by anti malware products, by using this function SpyEye can escape from commont anti-malware checks.
Code: Select all
00403601    8985 A8FCFFFF   MOV DWORD PTR SS:[EBP-358],EAX
00403607    83BD A8FCFFFF 0 CMP DWORD PTR SS:[EBP-358],0
0040360E    7D 07           JGE SHORT 00403617
00403610    33C0            XOR EAX,EAX
00403612    E9 91020000     JMP 004038A8
00403617    FF75 0C         PUSH DWORD PTR SS:[EBP+0C]
0040361A    FFB5 F0FDFFFF   PUSH DWORD PTR SS:[EBP-210]
00403620    E8 50F4FFFF     CALL 00402A75  ;Extract functions from Loaded Dll
 ..
00403B2C    FF75 0C         PUSH DWORD PTR SS:[EBP+0C]
00403B2F    FF75 08         PUSH DWORD PTR SS:[EBP+8]
00403B32    FF55 F4         CALL DWORD PTR SS:[EBP-0C]   ;IsWow64Process

What we can observe is that functions addresses are obtained always with the same procedure, embedded into a set of calls. These addresses are obtain immediately before they're used:

Code: Select all
00403ABC    68 3C9A4E53     PUSH 534E9A3C ;Hardcoded value for ZwMapViewOfSection
00403AC1    6A 09           PUSH 9
00403AC3    E8 8EF0FFFF     CALL 00402B56  ;Obtain the Function specified by hardcoded value
00403AC8    59              POP ECX
00403AC9    59              POP ECX
00403ACA    8945 F4         MOV DWORD PTR SS:[EBP-0C],EAX
00403ACD    837D F4 00      CMP DWORD PTR SS:[EBP-0C],0
00403AD1    75 04           JNE SHORT 00403AD7
00403AD3    33C0            XOR EAX,EAX
00403AD5    EB 2D           JMP SHORT 00403B04
00403AD7    8965 F8         MOV DWORD PTR SS:[EBP-8],ESP
00403ADA    FF75 2C         PUSH DWORD PTR SS:[EBP+2C]
...
00403AF5    FF75 08         PUSH DWORD PTR SS:[EBP+8]
00403AF8    FF55 F4         CALL DWORD PTR SS:[EBP-0C] ;ZwMapViewOfSection
..

00401516    FF75 0C         PUSH DWORD PTR SS:[EBP+0C]
00401519    FF75 08         PUSH DWORD PTR SS:[EBP+8]
0040151C    FF55 EC         CALL DWORD PTR SS:[EBP-14]  ;Inside

..
0088D4DE    B8 2B120000     MOV EAX,122B
0088D4E3    BA 0003FE7F     MOV EDX,7FFE0300
0088D4E8    FF12            CALL DWORD PTR DS:[EDX]  ;KiFastSystemCall

Any user-mode software can call a kernel function simply by putting the function’s C-style arguments on the stack, loading EAX with the function number and calling the address 0x7FFE0300, as long as it is done such that the arguments are 8 bytes above ESP when the instruction at 0x7FFE0300 executes. So what we have to do is to find in the syscall table which value belongs to 122B

+syscall(122b) NtUserShowWindow

Code: Select all
00401FD6    68 0CBAC833     PUSH 33C8BA0C
00401FDB    E8 20F0FFFF     CALL 00401000
The Hardcoded value works as selector for a block of bytes to decode, at exit of 00401000 we have in EAX the following string: __SPYNET__
Code: Select all
00404950    50              PUSH EAX
00404951    FF15 80804000   CALL DWORD PTR DS:[408080] ;GetWindowsDirectory
 ..
0040495C    56              PUSH ESI    ;Hardcoded value for 'cleansweep.exe'
0040495D    C685 FFFEFFFF 0 MOV BYTE PTR SS:[EBP-101],0
00404964    E8 97C6FFFF     CALL 00401000
..
0040497D    68 30814000     PUSH 408130                                             ; ASCII "%s%s\%s"
00404982    50              PUSH EAX
00404983    E8 99FFFFFF     CALL 00404921
This is what we obtain "C:\cleansweep.exe\cleansweep.exe" and successively "explorer.exe" string. Here I want to summarize a bit what happens after, SpyEye inject via CreateRemoteThread injects itself into explorer.exe and by creating a new section dumps into the victim HD:

* C:\cleansweep.exe\cleansweep.exe
* config.bin

To carve these two files I've used the classic forensics approach by using WinHex, by loading the partition where resides the OS and dumping these two files.

SpyEye is a direct competitor of ZeuS botnet, all features are located in the config.bin file, between the various option there is also Kill ZeuS.
Attachments
pwd: infected
(138.72 KiB) Downloaded 62 times
 #1183  by NOP
 Sat May 29, 2010 4:24 pm
Nice analysis. That EnumTimeFormats trick fooled me first time round. :D
Carefully observe ASCII in the red circles, there are clear evidences of the PE nature of this block of code, that presents a low level on encryption.
That is actually aPlib compression.