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:
In Win32, a new SEH is installed by filling an EXCEPTION_REGISTRATION_RECORD entry and linking it to the SEH chain (at FS:[0]).

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:
Walking the exception registration records
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:Display 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)
In Win32, a new SEH is installed by filling an EXCEPTION_REGISTRATION_RECORD entry and linking it to the SEH chain (at FS:[0]).
Before walking the exception registration records, we need to get the base address of the FS selector.Code:
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION_RECORD *Prev;
PEXCEPTION_HANDLER Handler;
} EXCEPTION_REGISTRATION_RECORD;
Fortunately, each debugger module provides a special callback in its debugger_t structure:To use this callback, we will pass the FS selector value: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);
or in C:Code:
def GetFsBase(tid):
idc.SelectThread(tid)
return idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
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 + 0Code:
ea_t fs_base;
dbg->thread_get_sreg_base(tid, fs_sel_value, &fs_base);
With this knowledge, we can write a small loop to walk this list and extract the handlers:We do that for each thread: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
Building the graphCode:
# Iterate through all function instructions and take only call instructions
result = {}
for tid in idautils.Threads():
result[tid] = GetExceptionChain(tid)
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:Putting it all togetherCode:
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
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