Log in

View Full Version : SEH Graph


Hex Blog
October 5th, 2009, 22:17
It is said ("http://en.wikipedia.org/wiki/A_picture_is_worth_a_thousand_words") that a picture is worth a thousand words, and similarly many reversers would agree that a graph is worth a thousand lists! Recently, we added graphing support into IDAPython and now Python scripts can build interactive graphs.
To demonstrate this new addition, we will write a small script that graphs the structured exception handlers of a given process.

http://hexblog.com/ida_pro/pix/sehgraph_small.png
Writing the script

The steps needed to write the script:

For each thread in the process:

Retrieve the linear address of FS:[0]
Walk the exception registration record list and save the handler

Build the graph:

Allocate one node for each unique exception handler address
Add edges between the last exception handler and the current exception handler (so to create the chain visually)
Display the graph
Walking the exception registration records

In Win32, a new SEH is installed by filling an EXCEPTION_REGISTRATION_RECORD entry and linking it to the SEH chain (at FS:[0]).
Code:

typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION_RECORD *Prev;
PEXCEPTION_HANDLER Handler;
} EXCEPTION_REGISTRATION_RECORD;

Before walking the exception registration records, we need to get the base address of the FS selector.
Fortunately, each debugger module provides a special callback in its debugger_t structure:
Code:

// Get information about the base of a segment register
// tid - thread id
// sreg_value - value of the segment register
// answer - pointer to the answer. can't be NULL.
// 1-ok, 0-failed, -1-network error
int (idaapi *thread_get_sreg_base)(
thid_t tid,
int sreg_value,
ea_t *answer);
To use this callback, we will pass the FS selector value:
Code:

def GetFsBase(tid):
idc.SelectThread(tid)
return idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
or in C:
Code:

ea_t fs_base;
dbg->thread_get_sreg_base(tid, fs_sel_value, &fs_base);
Now that we have the base, we can compute the linear address of the exception registration record list head by adding the base (fs_base) to the offset (which happens to be zero), thus: fs_base + 0
With this knowledge, we can write a small loop to walk this list and extract the handlers:
Code:

def GetExceptionChain(tid):
fs_base = GetFsBase(tid)
exc_rr = Dword(fs_base)
result = []
while exc_rr != 0xffffffff:
prev = Dword(exc_rr)
handler = Dword(exc_rr + 4)
exc_rr = prev
result.append(handler)
return result
We do that for each thread:
Code:

# Iterate through all function instructions and take only call instructions
result = {}
for tid in idautils.Threads():
result[tid] = GetExceptionChain(tid)
Building the graph

Building the graph is even simpler and can be done by subclassing the GraphViewer class and implementing the OnRefresh() and OnGetText() events.
Here's the simplified version of the graph building loop:
Code:

def OnRefresh(self):
self.Clear() # clear previous nodes
addr_id = {}

for (tid, chain) in self.result.items():
# Add the thread node
id_parent = self.AddNode("Thread %X" % tid)

# Add each handler
for handler in chain:
# Get the node id given the handler address
# We use an addr -> id dictionary
# so that similar addresses get similar node id
if not addr_id.has_key(handler):
id = self.AddNode( hex(handler) )
addr_id[handler] = id # add this ID
else:
id = addr_id[handler]

# Link handlers to each other
self.AddEdge(id_parent, id)
# Now the parent node is this handler
id_parent = id

return True
Putting it all together


The script will display the thread nodes and the handlers in different colors. Double clicking on a handler node will jump to it in an IDA-View and double clicking on a thread node will display the exception handlers in the message window. Here are some SEH graphs:

IDA/Graphical version (idag.exe):
http://hexblog.com/ida_pro/pix/sehgraph_idag-thumb.png ("http://hexblog.com/ida_pro/pix/sehgraph_idag1.html")

Visual Studio 2008 (devenv.exe):
http://hexblog.com/ida_pro/pix/sehgraph_devenv-thumb.png ("http://hexblog.com/ida_pro/pix/sehgraph_devenv.html")

Please download the script from here ("http://hexblog.com/ida_pro/files/SEHGraph.py") (you need IDAPython r242 ("http://code.google.com/p/idapython/updates/list") and above).
All comments and suggestions are welcome. You are also encouraged to share screenshots of interesting SEH graphs you run into.


http://hexblog.com/2009/10/seh_graph.html
Externalist
October 6th, 2009, 10:40
hawt stuff

evlncrn8
October 27th, 2009, 13:53
you could also process the LOAD_CONFIG directory in the pe file, as if it is compiled with /safeseh you could also obtain a nice list of seh addresses by processing it