In this short analysis paper I want to give a technical overview about one of the latest MBR rootkit updates. The sample which is going to be analyzed is dated April 2012.
The bootkit part of this rootkit remain almost the same as the one that we have just seen in my previous analysis (available here). Sinowal uses the same algorithm to recover the start sector where it’s storing its loader and the main executable file – Last MBR partition sector + 1 for loader and Last MBR partition sector + 0x19 for the main rootkit driver. It hooks Int13h, then hooks BlOsLoader function from NT OS loader, and finally IoInitSystem API from Windows kernel. To identify the right target disk port driver it calculates a DWORD key with the following simple algorithm:
It’s interesting to see that the loader is not error-proof, it shows a bug which sometimes identifies the wrong disk port driver – especially when the target system uses more disk controllers. Yet the loader, and the malware entry point routine located at the infected disk port driver, were built in the same way as the older sample I analyzed in December 2011.
Rootkit main driver structure
The really cool part of this new sample is in its rootkit main driver. This is a quite huge driver, which implements whole logic, and now it has been upgraded from its previous release. While an untrained eye could spot no difference, a more in depth analysis allow us to discover a very cool trick . All the previous technologies used to unhook MBR rootkit hooks and restore original Master Boot Record fail, the rootkit will be alive at the next system reboot again, no matter what you try to use to remove it. What trick is it using?
Main driver is encrypted using its own specific packer, which generates spaghetti-code used to make the reversing job much more difficult. This stage of encryption uses many tricks like the following one (quite easy to spot out):
Encrypted driver entry point is called just after IoInitSystem API. Then it firstly relocates itself and rebuild its IAT and then creates a new system thread. The rootkit then creates some synchronization objects (needed for synchronization between encrypted driver, and real one), waits until the system is fully operative and extracts and decrypts real driver. Finally it gives control to real Sinowal driver entry point and ends execution. Main driver entry point is not a standard DriverEntry. It is called in the following way:
Typical of sinowal is the following obfuscated code schema of rootkit functions:
A Jump variable is initialized at the start of rootkit functions together with a lot of stack variables. Inside the body of the function we can see:
This is a chunk representing main obfuscation. Every block of code ends moving the returned value from a function or API call, mixed together with some math operations, to the previous showed jmpVar. In this way static analysis is very difficult, though you can reconstruct the right code sequence easily.
Rootkit system main thread synchronize itself with the encrypted driver, then, after it had discover that original crypted driver has finished its work, wipes it out. Sinowal is indeed designed to run on Windows 2000, XP, 2003, Vista, Vista SP1; if the infected OS is not one of these, the main thread ends with STATUS_UNSUCCESSFUL error code. Otherwise, “InitializeRootkitGlobalStructures” function is called, Sinowal allocates a data structure which is 0x42C bytes long, used to store all its global data. It then starts analyzing the original disk port driver and hooks its IRP_MJ_SCSI dispatch function. It then registers a Bug Check callback and start another system thread, which is the rootkit watchdog thread. At the end it terminates itself with STATUS_SUCCESS error code
Rootkit driver: IRP_MJ_SCSI hooked Dispatch Function and WatchDog Thread
IRP_MJ_SCSI System disk port driver hook is gone mostly unchanged from the previous release. Sinowal obtains the original system disk port driver, analyzes it and installs its hook function. To correctly install its hook, it recovers IoGetDmaAdapter nt kernel function address with MmGetSystemRoutineAddress, it then relocates two dummy nested functions. After, it searches for the “CALL HalDispatchTable + XXh” (where XX is an offset of Hal table) opcode, gets HalDispatchTable pointer and fills found table entry with its own address of the first of 2 previous functions. Inside the second dummy function resides the call to the real rootkit new SCSI dispatch function. The real Rootkit SCSI Dispatch function intercepts each MBR and rootkit sectors I/O. For read I/O, it hides the real sectors content, filling with zeroes for rootkit sectors, and replacing original MBR (stored as backup in the first rootkit sectors).
The real innovative feature of Sinowal is its watchdog thread. At startup time the main rootkit thread does an analysis of the original port driver. It gets the original filename (identify driver name and then get its Image path from registry), opens and maps it, resolving its IAT and relocations. At this stage we can see the following code:
As we can see, Sinowal evaluates the equation:
newMappedDrv Base Address – orgPortDrv Start Address + orgPortDrv Scsi Dispatch > newMappedDrv Base Address
If the above expression evaluates to FALSE, then the code jumps where a MemFree rootkit procedure is called, with Mapped Driver Base address as first parameter. Indeed in that case, Mapped Driver buffer will be freed.
Otherwise, code follows with another expression evaluation:
newMappedDrv Base Address + newMappedDrv Pe Size > newMappedDrv Base Address – orgPortDrv Start Address + orgPortDrv Scsi Dispatch
Also in this case, if the expression evaluate to FALSE new mapped driver will be freed, otherwise some information will be placed in rootkit global structure:
+ 0x328h – Original Disk port driver SCSI Dispatch Function pointer
+ 0x32ch – New Disk port driver SCSI Dispatch Function pointer
(pointer to IoGetDmaAdapter+155h function, call [HalDispatchTable+0x3c])
+ 0x330h – Disk port driver name rootkit key
+ 0x334h – Rootkit new mapped Disk port driver base address
+ 0x338h – Rootkit new mapped Disk port driver PE size
+ 0x33Ch – Rootkit new mapped Disk port calculated DELTA
Sinowal code analyzes if SCSI Dispatch function address is falling into the mapped driver address space; if not, it means that miniport disk port driver uses Dispatch functions of another one. This could be the case of some SCSI controller miniport drivers that uses Microsoft generic SCSI port driver services (scsiport.sys) to operate correctly. If the mapped driver wasn’t freed, Sinowal watchdog thread uses the IRP_MJ_SCSI function of new mapped driver for all its I/O. In this way, even if you try to rewrite the original MBR or delete rootkit sectors (bypassing hooked disk scsi dispatch function), watchdog thread, each second, checks and replace all of your modifications.
This new feature is really important, because even if an antirootkit succeed in MBR rewriting and sectors rewriting, Sinowal can still restore all its code.
The last thing to say is that the rootkit’s startup thread frees the mapped driver if it uses another dispatch function. Otherwise it should map and relocate also other modules and this could render the system unstable.
Sinowal rootkit is still active and it’s evolving its code after 4 years. Now it’s implementing a very effective trick to self-protect itself and to make antivirus vendors’s job very difficult. What we should expect in the next release is probably direct hardware I/O? I think that this could be something we should be ready to defeat in some way in the near future.