TippingPoint Digital Vaccine Laboratories
DID YOU KNOW... At the 2007 Black Hat Briefings in Las Vegas, TippingPoint DVLabs had five speakers presenting on a variety of topics.

MindshaRE: Extending IDA with Custom Viewers

Anyone who utilizes IDA Pro is very likely familiar with the concept of subviews, the window panes that give a reverser the ability to view and query many characteristics of a binary stored in IDA's database. The default views available in IDA are great for displaying generic characteristics of any disassembled object. However, as is quite often the case, one may wish to collect data about an application (or otherwise) that may be more specifically targeted.

For example, we often find ourselves reversing a file format parser for one reason or another. Many of them support various FourCC-based formats (like MOV, RealMedia, Shockwave, PNG, ICC, ...) and as such usually have code that resembles this:

These compares are useful to locate as they will usually be dealing with an input file and given some complementary runtime data, these locations can help us understand a bit about how the parser may work. So, as Elias Bachaalany demonstrated on the Hex-Rays blog (http://www.hexblog.com/?p=119) IDA supports custom viewer creations. I'll show how to implement a quick, clickable interface to FourCC compares within a binary.

First, we need code to find FourCC compares:

import string

fourccs = []

# loop functions

for func in Functions():

# loop instructions

for instr in FuncItems(func):

# only care about compares

disasm = GetDisasm(instr)

if "cmp" in disasm and "offset" not in disasm:

# ensure immediate compare

if GetOpType(instr, 1) == 5 and GetOpType(instr, 0) == 1:

# ensure at least 3 bytes of ASCII in the immediate

opval = GetOpnd(instr, 1)


opval = int(opval[:-1], 16)

opval = struct.pack('>L', opval)

except ValueError:


oplen = len(opval)

opstrlen = len("".join((x for x in opval if x in string.printable)))

if (opstrlen >= 3):

# change it to character representation in IDA

OpChr(instr, 1)

fourccs.append((instr, opval))

print "0x%08x: %s" % (instr, GetOpnd(instr, 1))

This should output something like the following:

Now, we can build a custom viewer and populate it with our data:

class FourCCViewer(idaapi.simplecustviewer_t):

def __init__(self, data):

self.fourccs = data


print "Launching FourCC subview..."


def Create(self):

title = "FourCCs"

idaapi.simplecustviewer_t.Create(self, title)

comment = idaapi.COLSTR("; Double-click to follow", idaapi.SCOLOR_BINPREF)


comment = idaapi.COLSTR("; Hover for preview", idaapi.SCOLOR_BINPREF)


for item in self.fourccs:

addy = item[0]

immvalue = item[1]

address_element = idaapi.COLSTR("0x%08x: " % addy, idaapi.SCOLOR_REG)

value_element = idaapi.COLSTR("%s" % immvalue, idaapi.SCOLOR_STRING)

line = address_element + value_element


return True

def OnDblClick(self, something):

line = self.GetCurrentLine()

if "0x" not in line: return False

# skip COLSTR formatting, find address

addy = int(line[2:line.find(":")], 16)


return True

def OnHint(self, lineno):

if lineno < 2: return False

else: lineno -= 2

line = self.GetCurrentLine()

if "0x" not in line: return False

# skip COLSTR formatting, find address

addy = int(line[2:line.find(":")], 16)

disasm = idaapi.COLSTR(GetDisasm(addy) + "\n", idaapi.SCOLOR_DREF)

return (1, disasm)

Now we just need to instantiate an instance of FourCCViewer and it should pop up a new subview that looks like so (assuming you've already run the fourCC finding code above):

foo = FourCCViewer(fourccs)

Pretty simple stuff, but it can come in handy when you've got an arsenal of extra analysis runs you perform prior to reversing a complex binary. A slightly more interesting use case for this was when displaying data scraped from a run time histogram of Shockwave's memory manager as Logan and I spoke about at CanSecWest this year:

That's all for now, hopefully we can get some more MindshaRE posts in the pipeline.


Published On: 2011-05-11 01:24:00

Comments post a comment

No comments.