Binary Auditing Introduction

Reconstructing Class Definitions

When analyzing C++ code, having an understanding of the object structure is very helpful. This information can be difficult to gather if an auditor is not looking in the right places; many object structures are quite complex and contain nested objects.

The general methodology for reconstructing objects is to find all accesses relative to the object pointer, and therefore enumerate members of that class. In most cases, types for these members must be inferred or guessed, but in some cases you can determine whether they're used as arguments to known functions or in some other familiar context.

If you are trying to reconstruct an object manually, generally the best places to begin looking are the constructor and deconstructor for that class. These are functions that initialize and free up objects, and therefore are functions that generally access the most members of an object in any one place. These two functions will generally give a lot of information about a class, but not necessarily all the necessary information. It may be necessary to go to other methods in the class to get a more complete picture of the object.

If a program has symbol information, the constructor and destructor can be found quickly for any given application. They will have the notation Classname::Classname and Classname::~Classname . However, if they cannot be found by their name , they can often be recognized by their structure and where they are referenced. Constructors are often linear blocks of code that initialize a large number of structure members. They are generally void of comparisons or conditional jumps , and will often zero out structure members or large portions of a structure. Destructors will often free many structure members.

Halvar Flake has written an excellent tool as a plug-in for IDA Pro that will take some of the tedium out of manually enumerating structure members for an object. This tool is available for download from BlackHat Consulting at www.blackhat.com/html/bh-consulting/bh-consulting-tools.html .

vtables

The manner in which compilers deal with virtual function tables ( vtables ) can add much annoyance when you are auditing binaries. When a function from the vtable is called, it can be challenging to track down exactly where that call is going without runtime analysis. For example, the following type of code will commonly be seen in compiled C++ code.

 mov     eax, [esi] lea     ecx, [ebp+var_8] push    ebx push    ecx mov     ecx, esi push    [ebp+arg_0] push    [ebp+var_4] call    dword ptr [eax+24h] 

In this case, ESI contains the object pointer, and some function pointer is called from its vtable . To discover where this function call goes, it is necessary to know the structure of the vtable . The structure can usually be found in the constructor for the class. In this case, the following code is found in the constructor.

 mov     dword ptr [esi], offset vtable 

For this particular example, it was easy to locate the function call in the vtable , but quite often a function pointer from the vtable of a nested object is called. This type of situation can require quite a bit of work to resolve.

Quick but Useful Tidbits

Some of the points presented here are fairly obvious but nonetheless useful; if you don't already know them, you will miss several key points when auditing binaries.

  • The return value for a function call is in the EAX register.

  • The jump instructions JL/JG are used in signed comparisons.

  • The jump instructions JB/JA are used in unsigned comparisons.

  • MOVSX sign extends the destination register, while MOVZX zero-extends it.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net