Monday, December 26, 2011

New OllyDbg Anti-Debug Trick

Actually, it is not just a trick. It is a buffer overflow in OllyDbg v1.10, which does not affect OllyDbg v2.0 since the compromised functionality seems to be dropped or subject to some enhancements. The story begins when i was trying to create the longest possible pathname for an Exe file to see if olly would crash upon loading that file. And olly really did.

Loading olly into another instance of olly did not help, and the child olly gracefully exited.

So, I quickly opened the minidump into windbg and then issued a ".ecxr" command to see the exception that caused my beloved olly to suffer.

The eip, as you can see above, is 0x0303906F, which belongs to dbghelp.dll version

The faulty address has mov esp,ebp, which doesn't look like an instruction triggering exceptions. So, i took one step back and checked the preceding "call" instruction.
It was easy to notice it is the cookie checking procedure.  I easily figured out that olly crashed due to a an invalid cookie value.

I then reloaded olly into another instance of olly and searched for all references to the call instruction at 0x03039065, trying to find the procedure/stack frame whose cookie was compromised.
Three references were found.  Okay, easy to be tried one by one.

I placed a breakpoint on each reference and also instructions around it.

As you can see in the image above, push 57 was hit but instructions before it were not. Also, no references to push 57 were found. Weird, isn't it?

In the image above, if we follow the very first value on the stack, we find will ourselves in ollydbg.exe.
 Ollydbg.exe executes call dword ptr[ebp-0x1c] and then goes to push 57 at 0x03039000.
 Let's stop here for a while, dbghelp.dll does not export push 57 and olly is less likely to call a non-exported procedure.

Now, the only assumption i got is that variable at ebp-0x1c in ollydbg.exe was compromised so that only one byte was overwritten (An off-by-one).

Given that my assumption is true, has Microsoft intentionally placed the push 57 at 0xXXXXXX00 to handle such cases? Abit off-topic, i know.

Back to ollydbg.exe, i put a breakpoint on the prologue of our compromised procedure and at call dword ptr[ebp-0x1c] and started tracing over.

I think the two images above should confirm my assumptions.

I spent one hour to see what occurs in the compromised ollydbg procedure and summarized it into the following steps:

1) Addresses of some dbghelp.dll functions are retrieved and stored into stack variables. The one of interest is the address of the "SymGetModuleInfo" function stored into dword ptr[ebp-0x1c].

2) The "SymSetOptions", "SymInitialize" functions are called to start symbol loading.
3) The being-loaded Exe filename is split into parts, e.g. "C:\walied\xxx\walied\mostafaaaaaaaa.exe" would be split into "c:", "\walied\xxx\walied\", "mostafaaaaaaaa", and "exe", and each part is stored in a sufficiently wide buffer.
4) The "SymSetSearchPath" function is called.
5) The "CreateFileA" and "GetFileTime" functions are called.
6) The "FindDebugInfoFile" function is called.

After these 6 steps have been executed successfully, a loop is entered. In the loop, different paths are copied into a buffer at [ebp-0x128] (i think it is 0x10C bytes long). Given that ollydbg.exe resides in "c:\walied\ollydbg110\", paths are copied in following manner.

1) "c:\walied\ollydbg110\" + "symbols\sym\" + mostafaaaaaaaa + ".sym". If not found, jump to 2.
2) "c:\walied\ollydbg110\" + "sym\" + mostafaaaaaaaa + ".sym". If not found, jump to 3.
3) "c:\walied\ollydbg110\" + mostafaaaaaaaa+ ".sym". If not found, jump to 4.
4) "c:\walied\xxx\walied\" + "symbols\sym\" + mostafaaaaaaaa + ".sym". And so on.
Now it is easy to notice that [ebp-0x1C] was compromised at path no. 4.

Here is a screenshot of where exactly the buffer overflow occurs.

A question urgently arises here, that is, how can we practically use the aformentioned buffer overflow as an anti-debug trick?

Given the fact that olly tries to find the .sym file for every module, including the dynamically loaded one, we can ask the to-be-protected application to recursively create the longest valid pathname, then copy any .dll into the newest directory, and finally LoadLibrary the .dll.

A simple PoC has been created to reproduce this Buffer Overflow. 

Here is the source code.

Here is VT report.

You can follow me on Twitter @waleedassar 


  1. This bug was known since 2008.
    I even described it publicly in Virus Bulletin.

  2. It is different from those mentioned in your paper, as the above mentioned buffer overflow is in ollydbg.exe, not dbghelp.dll.