Friday, June 8, 2012

In this post, i am going to share with you a case that i met while trying to debug a tiny webserver. In the beginning i have to clarify there is no security issue or anti-debug trick discussed here.

The first thing i did with this file was trying to resolve symbol names using IDA 6.2 Demo. Unfortunately, few symbols were resolved and that was not satisfying at all. OllyDbg couldn't do anything with that, either.

The next thing i tried was opening the executable in Stud_PE. I was amazed to see the "PointerToSymbolTable" and "NumberOfSymbols" fields of the "_IMAGE_FILE_HEADER" structure set to valid values.

So, if COFF debug info exists why does not IDA read it?. Trying to answer this question, i built an executable with COFF debug info using MS VC++ 6 and loaded it in IDA. Strange enough, IDA successfully read COFF debug info from the MSVC-built executable.

Trying harder to solve that, i compared PE headers of both executables. I found that the MSVC-built executable has the "_IMAGE_DEBUG_DIRECTORY" structure set, while the executable of question does not.

Now i figured out that to have IDA reading COFF debug info i have to manually create the "_IMAGE_DEBUG_DIRECTORY" structure.

And here are the steps i followed to create the new "_IMAGE_DEBUG_DIRECTORY" structure:

1) Searching for any 0x1C unused bytes in any section of the executable.N.B. 0x1Cis thesizeof(_IMAGE_DEBUG_DIRECTORY). A good candidate place is at the end of the resources section.

2) Filling the important fields of this structure with corresponding values. The structure is defined in winnt.h, see below.

The fields in question are:a)Type. Set it to IMAGE_DEBUG_TYPE_COFF (0x1).

N.B. 0x20 is sizeof(_IMAGE_COFF_SYMBOLS_HEADER). we will see that later.

c)PointerToRawData. Set it to the value of the "PointerToSymbolTable" field.The rest of fields can be left zeros.N.B. Coff debug info is usually tailing the executable.

3) Fill the "VirtualAddress" and "Size" fields in the "_IMAGE_OPTIONAL_HEADER" structure.

4) Displace data at PointerToSymbolTable forward by 0x20 bytes to create gap for the "_IMAGE_COFF_SYMBOLS_HEADER" structure. This can be easily done using HexEditor Neo in the "insert mode".5) Fill fields of the "_IMAGE_COFF_SYMBOLS_HEADER"structure so that first field is set to the number of COFF symbols (as found in the "NumberOfSymbols" field of the "_IMAGE_FILE_HEADER" structure) and second field is set to 0x20, sizeof(_IMAGE_COFF_SYMBOLS_HEADER). The rest are not important.

After the aforementioned five steps were taken, IDA read COFF debug info successfully.

Loading the fixed executable in OllyDbg v1.10, i again got no symbols resolved. To discover why, i debugged both IDA and OllyDbg v1.10 and found out that OllyDbg uses the "Dbghelp.SymLoadModule" function to read COFF debug info while IDA uses its own routine.

As you can see in the image above, the "Dbghelp.SymGetModuleInfo" function returned IMAGE_DEBUG_TYPE_UNKNOWN in the "SymType" field of the "IMAGEHLP_MODULE" structure and this is why OllyDbg cancelled symbol loading.

I quickly moved to XP SP3 and tried the fixed executable and again nothing. After renaming the dbghelp.dll6.8.4.0 residing in OllyDbg directory, OllyDbg loaded symbols like a charm.

So, the conclusion here is that Microsoft has dropped support for COFF symbols in newer versions of Dbghelp.dll.

N.B. For more info. about reading COFF debug info, you can refer to this link.

Any comments are very welcome. Also, if you see any mistake or misconception, please don't hesitate to contact me.