Advanced Analysis of Sinowal

Abstract

Last month I analysed Sinowal (Analysis of Sinowal), a wide-spread bootkit/trojan + phishing program. I covered 2 of 3 main parts of Sinowal in that article, the Infector file and the Bootkit part. Now I want to discuss the last part, the driver, how it works and what it does.

- Peter Kleissner, Software Engineer

Sinowal

Sinowal consists of 3 main parts:

Sinowal comes as single infector file which infects the system with the Bootkit Code and writes the Driver File to the hard disk. The bootkit code loads and executes the Driver File during startup of the computer and windows.

The driver file

The driver file is 353.5 KB big and loaded from the very end of the partition by the Bootkit Code. It is written to the hard disk by the infector file. Though it doesn't have a name (the driver file), it's official name is now "CutPartition.ex_". I've named it so because when I extracted the file from hard disk I looked at the end (Ctrl + End) and saw as last string "CurPartition". The ending "ex_" should be "sys", when I extracted the file I didn't know it was a driver.

I have currently no complete analysis of the driver file yet. This comes from the fact it is a driver and not a usual Windows executable which are easier to reverse engineer. The analysis represented here is mainly based on static analysis and help of others.

Imports

The driver imports following functions from ntoskrnl.exe:

KeDelayExecutionThread
ExAllocatePoolWithTag
ExFreePool
except_handler3
RtlFreeAnsiString
atoi
RtlFreeUnicodeString
RtlUnicodeStringToAnsiString
RtlQueryRegistryValues
ZwClose
ObfDereferenceObject
ObReferenceObjectByHandle
ObOpenObjectByName
RtlInitUnicodeString
PsTerminateSystemThread
PsCreateSystemThread

It is interesting that there is no GetProcAddress import, so the drivers Windows API function usage is restricted to the above listed functions.

Hiding the malicious Master Boot Record

To hide its modified malicious Master Boot Record, Sinowal driver hooks the ReadFile function. Whenever someone wants to read the MBR, Sinowal replaces the read content with the backup of the MBR (which resists in sector 62).

Unkown strings at end of file

Some unknown strings appear at end of file, outside any PE section:

CutPartition(): SetFilePointer() failed with last error 0x%08X (disk offset 0x%I64X)
CutPartition(): ReadFile() failed to read the MBR at disk offset 0x%I64X with last error 0x%08X
CutPartition(): '55 AA' magic value was not found in MBR at given disk offset (0x%I64X)
CutPartition(): SetFilePointer() failed with last error 0x%08X (disk offset 0x%I64X)
CutPartition():

I currently don't have a clue what CutPartition is doing here. The size of this extra data is 1C8h and just contains this strings. When I investigated these strings, I found also the Windows Bootloader copied one sector before the driver file on hard disk. This may be a relic of previous versions of Sinowal.

Log files

I found three log files I could assign to Sinowal. I can not publish or name them here, they contain highly confidential content. But I can tell you about this files. The first file contains just 4 bytes. The second is 46 KB size and contains encrypted data.

The third file is the real true log file. It contains the whole life of the Computers user in plain text. This file is sent to the people behind Sinowal. The log file has its own format, it consists of a list of entries. The log file I investigated has 1383 entries, data which had been collected for about half a year. It is full with logins, passwords, accounts, bank transactions etc. I am really scared how much sensitive data was collected.

The log file has following format (entry example):

  ‚AH   IP 91.141.127.189:
[dxtr_216]
Process: c:\program files\internet explorer\iexplore.exe
REQUEST:
HEADERS:
POST /login.php HTTP/1.1
Referer: http://www.******.com/

POST_FORM:
username=Toaster
password=Toaster
action=Login
rememberme=1
REGMATCHES:

Every record starts with 05h, control code "enquiry". The next character seems always to be zero (00h). The third character tells us what "object" we have, note (0Eh) means Internet Explorer phishing content, cross (10h) means Outlook phishing content. The further strings are dynamic, for example the string "rememberme" is only available if asked by Internet Explorer. There are numerous other keywords and some are copied directly from HTTP protocoll data. Note there is a lot of data collected, also bank transmissions or cookies, ftp accounts and many many other.

I reversed the log entry format (the log file just contains such entries):

  00h   WORD    Signature (0005h for normal phishing content, 0007h for uninterpreted raw data captured)
  02h   WORD    Record Type
                  0001h = visited internet domains in username@domain format
                  0002h = basic login capture (for example Windows logon)
                  000Eh = Internet Explorer phishing content
                  0010h = Outlook phishing content
  04h   DWORD   Checksum
  08h   WORD    Record Size
                  how many bytes of data (text encoded) will follow

Encrypted file

The file I found got encrypted. It is full with names of online banking sites Sinowal can phish. The encryption of the file is an xor with 11h.

Some sites from the file (how it looks like):

*rabobank.nl *raiffeisen.hu *raiffeisen.lu *raiffeisendirect.ch *redfcu.org *reuschel.com *robecodirect.nl *ruralvia.com *sampo.fi *sanostra.es *sebank.se *secure.lcf-rothschild.lu *secureinternetbank.com *sgbt.lu *skandiabanken.no *snet.lu

The file contains also a script and html code.

DNS Name Generator

For Sinowal DNS Name Generator take a look at http://mnin.blogspot.com/2008/01/mbr-rootkit-domain-name-prediction.html. The date is used for generating the 8 characters long domain name (for every day there is another domain). F-Secure registered (with Symantec) some of these domains. Note the domain name prediction algorithm changed already a few times, so be sure to have the most up to date one.

Operational Takedown (2008)

I got information that Sinowal operation was shut downed by law enforcement agencies, mainly because of information given by RSA Security. There has been done a lot of reverse engineering behind Sinowal, everything helped there to its shut down. Its future DNS names are prohibited for registration, so online banking information can no longer be uploaded and used by the people behind Sinowal. Sinowal is out of order. Great deal!

Update (January 2009)

Two weeks there were no sign of Sinowal. But since few days Sinowl is back with a new domain generating algorithm, and the domain names are still active and in use. So the game is going on... Well but I decided to take a further look on Sinowal, I'm going to reverse engineer the complete Sinowal driver and put my reverse engineering results here.

Special thanks to Raiffeisen Czech.

Analysing the Driver Code

So, three months later, I'm back with analysing the driver code. Let's take a look on the Driver Entry. As previously mentioned the driver resists at the end of the hard disk - but as full driver (dll) image. So it has everything as a dll has, a normal PE header and can also be normally statically analyzed like every other file. The entry point is the first thing to start with, Sinowals main entry point is a small initializing routine:

Driver_Entry:

; this is the normal entry point of a driver (according to Windows Driver Kit):

; NTSTATUS
;    DriverEntry(
;      IN PDRIVER_OBJECT  DriverObject,
;      IN PUNICODE_STRING  RegistryPath
;      ); 

; but Sinowal has its own entry point:

; DriverEntry(Module Address, PsLoadedModuleList Address);

; Arguments:
;   esi     = Pointer to PE Header of driver
;   Param1  = Module Address (first value pushed on stack)
;   Param2  = PsLoadedModuleList Address

; create frame
push ebp
mov ebp,esp

; initialize image (call with argument as Module Address)
push ecx
push [ebp+08h]                                              ; Module Address
call InitImage

mov ecx,[ebp+12]                                            ; PsLoadedModuleList
mov eax,[ecx]
mov edx,[eax+18h]
mov eax,[eax+20h]
mov [dword_1ADE8],eax                                       ; store to some variable for usage in Thread

; call ****
lea eax,[ecx+10h]
push eax
push ecx
push [ebp+08h]                                              ; Module Address
mov [dword_1ADE4],edx
call SUB_L0001079C

; (exit if return value is negative)
movzx	eax,al
xor	ecx,ecx
cmp	eax,ecx
jl Driver_Entry_Exit

; PsCreateSystemThread(&Thread Handle, Access Mask = 0, Object Attributes = NULL, Process Handle = NULL, ClientID = 0, Thread_Entry_Point, Param1);
push [ebp+08h]                                              ; StartContext = Argument passed to new thread (= Module Address in our case)
lea eax,[ebp-04h]                                           ; address of ThreadHandle
push Thread_Entry_Point                                     ; StartRoutine, the address where the thread starts execution
push ecx                                                    ; ClientId (= NULL)
push ecx                                                    ; ProcessHandle (= NULL, runs under System Context)
push ecx                                                    ; ObjectAttributes (not required)
push ecx                                                    ; DesiredAccess
push eax                                                    ; ThreadHandle
mov	dword ptr [L0001ADDC],L0001C180
call ntoskrnl.exe!PsCreateSystemThread                      ; this direct call is possible because ntoskrnl resists always on the same memory

Driver_Entry_Exit:

; exit from entry point to Stage 5 code (ntoskrnl hook code)
leave

retn 8

First there are two main facts: 1. it calls PsCreateSystemThread and 2. it returns with ret 8. This means we have 2 parameters passed, as previously given in my analysis the parameters ("arguments") are the module address (where the file lays in memory at) and the Windows PsLoadedModuleList.

This analysis will be updated within the next days.