SEH Graph

It is said 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.


Writing the script

The steps needed to write the script:

  1. For each thread in the process:
    1. Retrieve the linear address of FS:[0]
    2. Walk the exception registration record list and save the handler
  2. Build the graph:
    1. Allocate one node for each unique exception handler address
    2. Add edges between the last exception handler and the current exception handler (so to create the chain visually)
  3. 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]).


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:

// 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:

def GetFsBase(tid):
    return idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)

or in C:

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:

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
    return result

We do that for each thread:

    # 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:

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
        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):

Visual Studio 2008 (devenv.exe):

Please download the script from here (you need IDAPython r242 and above).

All comments and suggestions are welcome. You are also encouraged to share screenshots of interesting SEH graphs you run into.

This entry was posted in IDA Pro. Bookmark the permalink.

3 Responses to SEH Graph

  1. Anonymous says:

    All cool stuff. But man, you really need to fix some of your semantic patterns. “Linear address of the FS segment selector” – wtf? Lol.

  2. hume says:

    A suggestion to IDA’s graph capability:
    It seems IDAPro’s graph can’t display block with different border width/color or shape, of course the owner draw can do this but lack of portablity and too complex for simple display task like this.

  3. Elias Bachaalany says:

    Thanks for the corrections Anon.
    Hume: We are aware of this limitation. This is one thing among many other things that are scheduled for improvement.