Latest available version: IDA and decompilers v8.4.240320 see all releases
Hex-Rays logo State-of-the-art binary code analysis tools
email icon

Bochs debugger plugin is in alpha stage now, all of the 3 loaders mentioned in the
previous blog entry, are now complete.

Since we demonstrated briefly the IDB loader last time, we will demonstrate the PE loader this time,
which will allow you to debug PE executables. For this we continue using the same malware however
using the PE loader instead. Throughout the video you will see numerous tricks used by this malware
and you will see how the debugger works smoothly with them.

Here are some of the features supported by it:

  • SEH support: we try to mimic Windows as much as possible, for example the ICEBP instruction is
    a privileged instruction, but Windows report back a single step exception. Similarly Windows
    does not distinguish between 0xCC and 0xCD 0x03, so when an exception occurs, it reports that
    the exception address is always one byte before the trap. So if it was an INT 0x3 (CD03) then
    exception address will point to the 0x03 (in the middle of the instruction). We behave the same as Windows.
  • TLS callbacks: TLS callbacks are normally parsed by IDA and presented as entry points (ctrl+E),
    so you can put breakpoints there and run your program.
  • Extendible API emulation: you can provide implementation of a given API using scripting facilities,
    for example, in the video you see a call to GlobalAlloc, here is how it is actually implemented (from api_kernel32.idc):
  • ///func=GlobalAlloc entry=k32_GlobalAlloc purge=8
    static k32_GlobalAlloc()
    {
    eax = BochsVirtAlloc(0, BX_GETPARAM(2), 1);
    return 0;
    }
    ///func=GlobalFree entry=k32_GlobalFree purge=4
    static k32_GlobalFree()
    {
    eax = BochsVirtFree(BX_GETPARAM(1), 0);
    return 0;
    }

    A simple MessageBoxA replacement can be (from api_user32.idc):

    ///func=MessageBoxA entry=messagebox purge=0x10
    static messagebox()
    {
    auto param2;
    param2 = BX_GETPARAM(2);
    Message("I am messagebox function; %s\n", GetString(param2, -1, ASCSTR_C));
    eax = 1;
    // continue execution
    return 0;
    }

    Use your own code: You can also write your own DLL and map it into the process’ space. You can then redirect
    existing APIs to your own functionality, for example:

    ///func=GetProcAddress entry=bochsys.BxGetProcAddress purge=8
    ///func=ExitProcess entry=bochsys.BxExitProcess purge=4
    ///func=GetModuleFileNameA entry=bochsys.BxGetModuleFileNameA purge=12
    ///func=GetModuleHandleA entry=bochsys.BxGetModuleHandleA purge=4

    We redirect some functions to bochsys.dll which will do the job inside the process’ space.

    Less demanding PE loader: by that you can for example load any PE file, including system drivers or dlls.
    Given that you emulate the API calls, you can theoretically trace such targets too.

    Dependency resolution: You don’t have to emulate all APIs to use this plugin, by default if an API
    is not present, then a stub will be generated for it. For example, you can define a stub that will
    always return 0 for CreateFileA call, as:

    ///func=CreateFileA retval=0

    Since CreateFileA is recognized by IDA’s IDS files, no need to specify the “purge” value, otherwise a full definition would look like:

    ///func=FuncName purge=N_bytes retval=VALUE

    NT structures emulation: Some malware don’t use GetProcAddress or GetModuleHandle() for example, instead they try to
    parse the system structures and deduce these values.
    For this we also provide and build the basic structure of PEB and PEB_LDR_DATA, LDR_MODULE(s) and RTL_USER_PROCESS_PARAMETERS.
    If you need to inspect PEB structure of Win32 programs, then remember to grab
    the ldrmodule.idc script from IDA’s download area.

    Here’s the video: