0% found this document useful (0 votes)
84 views

Unpacking Ida Pro

Uploaded by

hughJ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
84 views

Unpacking Ida Pro

Uploaded by

hughJ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Using the Universal PE Unpacker Plug-in included in IDA Pro

4.9 to unpack compressed executables. © DataRescue 2005

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.

The compressed application.

Here is what appear on our screen if we execute the sample program:

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...

IDA Pro 4.9 Unpacking Tutorial 1


Here is what we observe if we have a look at the Imports window:

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.

Using the Universal PE Unpacker plugin.

Let's now start the unpacker through the Plug-ins sub-menu:

IDA Pro 4.9 Unpacking Tutorial 2


The plug-in options dialog appears:

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.

IDA Pro 4.9 Unpacking Tutorial 3


In order to rebuild original import section of the program, the plug-in created a new segment.

IDA Pro 4.9 Unpacking Tutorial 4


Once unpacked, we now recognize the more typical structure of the start() function:

However, let's try to improve this again in order to obtain the nicest disassembly possible!

IDA Pro 4.9 Unpacking Tutorial 5


Applying signatures.

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:

The final disassembly listing looks like this:

Much better, isn't it?

IDA Pro 4.9 Unpacking Tutorial 6


Behind the scene.

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;
}

// Let's start the debugger


if ( !run_to(inf.beginEA) )
{
warning("Sorry, could not start the process");
unhook_from_notification_point(HT_DBG, callback, NULL);
}

Events will be sent to our notification handler, defined as follow:


static int idaapi callback(void * /*user_data*/,
int notification_code,
va_list va)
{
switch ( notification_code )
{
case dbg_process_start:
...
case dbg_library_load:
...
case dbg_run_to:
...
case dbg_bpt:
...
case dbg_trace:
...
case dbg_process_exit:
...
...
}
return 0;
}

IDA Pro 4.9 Unpacking Tutorial 7


When we start our process through a call to run_to(), we will receive a corresponding dbg_run_to
event, indicating the run_to() command was properly executed. We are now at the entry point of the
packed program, and setup a breakpoint on the GetProcAddress() dynamic-link library function
(assuming the unpacking engine has terminated its work before recreating the original import table
of the original application):
case dbg_run_to: // Parameters: thread_id_t tid
dbg->stopped_at_debug_event(true);
gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress");
...
else if( !add_bpt(gpa) )
{
bring_debugger_to_front();
warning("Sorry, can not set bpt to kernel32.GetProcAddress");
goto FORCE_STOP;
}
else
{
++stage;
set_wait_box("Waiting for a call to GetProcAddress()");
}
continue_process();
break;

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:

case dbg_bpt: // A user defined breakpoint was reached.


// Parameters: thread_id_t tid
// ea_t breakpoint_ea
{
/*tid_t tid =*/ va_arg(va, tid_t);
ea_t ea = va_arg(va, ea_t);
...
if ( ea == gpa )
{
regval_t rv;
if ( get_reg_val("esp", &rv) )
{
ea_t esp = rv.ival;
invalidate_dbgmem_contents(esp, 1024);
ea_t ret = get_long(esp);
...
if ( !del_bpt(gpa) || !add_bpt(ret) )
error("Can not modify breakpoint");

IDA Pro 4.9 Unpacking Tutorial 8


Do you remember the two breakpoint messages we saw during the unpacking, occurring at
addresses 0x7C80AC28 and 0x00040C68D? The first one was our GetProcAddress() breakpoint,
while the second one was our breakpoint at the return address. In the following disassembly, you
can see the call leading to our GetProcAddress() breakpoint. We now only have to execute
instructions until the unpacking engine restores the program's original register contents and then
jumps to the real entry point of the unpacked program:

IDA Pro 4.9 Unpacking Tutorial 9


Step tracing is by far the easiest way to execute instructions until we reach an address in the
previously defined range. So let's enable step tracing as soon as we reach our second breakpoint:

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!

IDA Pro 4.9 Unpacking Tutorial 10


This tutorial is © DataRescue SA/NV 2005
Revision 1.1

DataRescue SA/NV
40 Bld Piercot
4000 Liège, Belgium
T: +32-4-3446510 F: +32-4-3446514

IDA Pro 4.9 Unpacking Tutorial 11

You might also like