Advanced Analysis of Sinowal
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 consists of 3 main parts:
- Infector File
- Bootkit Code
- Driver File
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.
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.
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 188.8.131.52: [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
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.