Reverse Engineering the Vanquish Rootkit - Part 2
If you followed our prior post on the Vanquish rootkit, you might remember how we identified anomalies in a system that led us to finding a Vanquish rootkit infection. You can go back to Part 1 and review it on your own, but here is a quick summary of how we discovered the rootkit:
- Found a hidden module listed in WindowsSCOPE. We noted several strings in this module that made references to Vanquish, code injection, replacing APIs, etc.
- Found a function exported from the hidden module with “FindNexFile” in the name
- Knowing that “FindNextFile” is normally an export of Kernel32.dll, we chose to look at the code for this function
- Disassembling the “FindNextFile” function showed that the first instructions of the function had been replaced with a jump to the hidden module we found earlier
At this point we were pretty sure there was a rootkit present, so the next step was to take a look at the code FindNextFile was jumping to. The best way for us to reverse engineer the code with WindowsSCOPE was to generate a control flow graph for the rootkit module. To do this, we first switched to the disassembled view and navigated to the address FindNextFile was jumping to. Then we right clicked and did a workpad graph from this address. The control flow graph that we got is shown below:
We started out by looking at the code within the entry procedure, which was the destination of the jump that we saw in kernel32.dll. This procedure is the green diamond shaped node in the graph. The control flow graph for this procedure is shown below:
We found something suspicious in this control flow graph – code that was called by FindNextFileW is now calling FindNextFileW. But if you remember, when we looked at FindNextFileW we saw that it was hooked. At first this looks like a potential problem, but we took a close look at a procedure that was called just before FindNextFileW and found something interesting. Look at the instructions in the control flow graph for this procedure below:
Based on the Windows API functions this code is calling, it appears that this code is modifying instruction memory. It uses RtlLeaveCriticalSection for synchronization to make sure the code isn’t run by more than one thread at a time. Then it uses VirtualProtect to modify memory protections to allow the instruction memory to be modified. Then a procedure is called which rewrites the instruction memory. The last thing the function does is us VirtualProtect and RtlLeaveCriticalSection to restore the original memory protection and release the lock that prevents other threads from executing this code. Finally, FlushInstructionCache is called, which will resolve cache coherency problems that come up when modifying instruction memory. After a little bit of analysis, it appears that this function unhooks the FindNextFileW API call, which allows vanquish to use it when it needs to. We also found there was another function very similar to this one, which does the exact opposite. After the Vanquish rootkit is done with using the FindNextFileW function, it restores the hook that it placed in kernel32.dll. The end result is that when any other code on the system calls FindNextFileW, it calls the rootkit’s implementation of this code. Since Vanquish needs to use the real FindNextFileW function, it temporarily unhooks it while it uses it. Once the rootkit is done using the API, it puts the hook back in place, preventing other code on the system from using the real API function.
Now let’s look at how Vanquish uses the FindNextFile API. If you look back at the control flow graph we showed earlier (the second graph, which is the graph of this entry point into the rootkit), you can see that FindNextFile is called in a loop. At the beginning of the loop another procedure is called, and the return value of the procedure determines when to break from the loop. Below a piece of the control flow graph for this procedure:
You’ll notice the use of the “CharUpper” function here, which indicates that this function is doing some string manipulations. In particular, this function is using “CharUpper” to do a case insensitive compare. After some more analysis, we found that this function was looking for strings containing “vanquish”. So the loop that calls this function uses the real “FindNextFile” function and then uses this function to skip any result that contains the string “vanquish”.
This was just one of many hooks installed by Vanquish - there are others including directories, services, registry keys, etc. The same techniques demonstrated in this post can be applied to reverse engineer other hooks installed by Vanquish and other rootkits.