Unpacking Ida Pro
Unpacking Ida Pro
Since version 4.9, IDA Pro comes with an Universal PE Unpacker plug-in, whose source
code is available in the IDA Pro SDK. This tutorial will show how to use this plug-in in practice
and will briefly describe how it works internally.
Quite innocent! However, if we open this executable in IDA Pro, the following warning appears:
IDA detects an unusual imports segment, and tells us the file might be packed...
Our program only imports three functions from KERNEL32.DLL. We can recognize the usual
LoadLibrary() and GetProcAddress() dynamic-link library functions, which will be more than
probably used by the unpacker engine to restore the original executable's imports.
In this dialog, we can adjust the address range which, once reached, will cause the debugger to
suspend the program's execution. It is also possible to specify a file where unpacked resources will
be saved. After pressing OK, the plug-in starts our program, which will unpack itself until an
address inside the previously defined range is reached. This indicates the unpacking is terminated,
and the following dialog box appears, offering to take a memory snapshot of the result:
Note that two breakpoints were reached during the unpacking: we'll say more on these later.
However, let's try to improve this again in order to obtain the nicest disassembly possible!
If we look at the strings found after the program was unpacked, we see that our program was
compiled by the Visual C++ compiler. Let's apply the associated FLIRT library signatures:
Let's now have some deeper look at how the SDK debugger API functions were used to implement
this unpacking in practice.
The main idea is to start the process, then react in an adequate way to various events caught by the
debugger, until we determine the program was properly unpacked. So we first setup a handler to
receive debugger events and to start the process until its entry point:
if ( !hook_to_notification_point(HT_DBG, callback, NULL) )
{
warning("Could not hook to notification point\n");
return;
}
When our GetProcAddress() breakpoint is reached, we receive a dbg_bpt event. We can extract the
return address from the stack, delete this first breakpoint, and setup a second breakpoint at the
return address in order to get notified as soon as the GetProcAddress() function returns:
del_bpt(ea);
if ( !is_library_entry(ea) )
{
deb(IDA_DEBUG_PLUGIN, "%a: reached unpacker code, switching to trace mode\n",
ea);
enable_step_trace(true);
...
set_wait_box("Waiting for the unpacker to finish");
}
else
{
warning("%a: bpt in library code", ea); // how can it be?
add_bpt(gpa);
}
At each instruction step, we now check if the address matches the previously defined range. If we
reached this range, we stop to trace, reanalyze the unpacked code, adjust the entry point, rebuild the
import table, save resources, and... finally take a snapshot!
case dbg_trace: // A step occured (one instruction was executed). This event
// notification is only generated if step tracing is enabled.
// Parameter: none
..
/*tid_t tid =*/ va_arg(va, tid_t);
ea_t ip = va_arg(va, ea_t);
if ( oep_area.contains(ip) )
{
// stop the trace mode
enable_step_trace(false);
// reanalyze the unpacked code
set_wait_box("Reanalyzing the unpacked code");
do_unknown_range(oep_area.startEA, oep_area.endEA, false);
auto_make_code(ip);
noUsed(oep_area.startEA, oep_area.endEA);
auto_mark_range(oep_area.startEA, oep_area.endEA, AU_FINAL);
// mark the program's entry point
move_entry(ip);
set_wait_box();
...
set_wait_box("Recreating the import table");
invalidate_dbgmem_config();
...
create_impdir();
set_wait_box("Storing resources to 'resource.res'");
if ( resfile[0] != '\0' )
extract_resource(resfile);
set_wait_box();
if ( take_memory_snapshot(true) )
goto FORCE_STOP;
The user has obtained a memory dump of the process in his IDA database, allowing him to start
analyzing the unpacked code as usual.
Don't hesitate to further look at the source code in the SDK, for all implementation details!
DataRescue SA/NV
40 Bld Piercot
4000 Liège, Belgium
T: +32-4-3446510 F: +32-4-3446514