Some time ago a new rootkit appeared that at first glance seemed more similar to initial variants of TDL3 than to the updated TDL4 variants we have seen this year. Like TDL3, it also parasitically infected a driver by inserting code in the resource directory of the PE file. In this case the name of the file it infected was hard-coded to volsnap.sys. Also similar to the early variants of TDL3, this rootkit also hooked some pointers in the dispatch table (IRP hook) of the driver below disk on the device stack of the hard disk.
But it was very interesting to see some of the anti-rootkit tools not showing the dispatch table hooks that are usually pretty straightforward to identify. Also this malware would not allow an external debugger (WinDbg) to break, which was annoying.
The reason for hooks not being reported was that the memory being read by the tools was not the actual memory! The dispatch table as “seen” by the tools appeared not to be hooked–whereas in reality it was hooked. The part that made it interesting was that the memory was being read at the correct address with a mov instruction and not using some system API that could be hooked. We know of some proof-of-concept ways to achieve this, but I had not seen this behavior before from a threat in the wild.
Obviously the motivation for malware authors to use such techniques is to prevent tools from showing their hooks so that administrators are not alarmed of suspicious activity.
So how does it fake memory on read access? This rootkit is using hardware breakpoints (DRX register setting) to monitor access to memory areas of the kernel that it patches. In addition to modifying the DR0 register, it hooks the KiDebugRoutine pointer so that it gets notification when the hardware breakpoint is encountered due to memory access. This rootkit installs IRP hooks and sets the DR0 register to the memory address where the IRP hook is installed. So when the memory of the dispatch table is read, a “fake” image with no hook in it is presented by the malware’s KiDebugRoutine hook. Here is a brief overview of the KiDebugRoutine hook code.
This is the beginning of the malware’s KiDebugRoutine handler code. If it encounters a breakpoint, then the malware simply increments the instruction pointer for the thread where the exception occurred and returns it as handled. Otherwise we take the jump.
Next comes the target from the above jump (loc_403BCC). If the exception occurred at a kernel mode address, then we jump to loc_404026.
At the target of the above jump, first the exception is processed normally by checking access flags, clearing the DR6 register, etc. Then the following code is used to identify if this is a read access to the protected memory and if the malware wants to block this particular access. If both of these conditions are true, then the read location is altered to point to a memory area with contents the malware wants to forge. Thus anyone who the malware does not like ends up reading the wrong memory. The comments in the code below explain the details. The assumption about ESI in the code below is interesting.
This technique has been discussed before, and this example shows again just how modern rootkits are adopting techniques and evolving rapidly. In fact, after this malware we have seen yet another update in the master boot record infecting the TDL4 strain that is still using DKOM to put a fake device object on the device stack of the hard disk. At McAfee Labs we will continue to investigate and provide protection against such threats.