Finding All Paths Between Two Functions in IDA

A common need that I have when reversing code is to find all possible code paths between two functions. Say for example that I’m looking for calls to dangerous functions, like sprintf, and I want to find all possible code paths that lead from my current function to sprintf. Manually going through the call graph from my starting function can often be, well, tedious:

websReadEvent call graph

Unfortunately I couldn’t find an easy way to make IDA display all code paths between two functions, and only the paths between those two functions. Normal call graphs show everything going to or from a single function, and while proximity view can be told to find a path between two nodes, it only displays the first path that it finds.

So I wrote idapathfinder, a plugin to find all code paths between two functions. This can significantly narrow down the number of paths that require investigation:

All paths between websReadEvent and sprintf

Note that the graphs generated by idapathfinder are solely dependent on IDA’s knowledge of function cross-references, so if for example you have a function that iterates over function pointers in a function table, those relationships will not be identified.

You can download idapathfinder here.

Binwalk v1.0, Now With Python!

Binwalk 1.0 has just been released and has been completely re-written as a Python module. This means that not only does it feature smarter scanning and signature processing features that were much, much easier to implement in Python, but it is now fully scriptable.

Aside from a few new options (and the removal of a few depreciated ones), the command line usage is pretty much the same. My personal favorite options to pass to binwalk are ‘-re’, which besides being a reference to reverse engineering, will attempt to extract data from the target file and clean up after itself (very handy for when there are a lot of false positive LZMA files extracted!):

$ binwalk -re firmware.bin

Scripting with binwalk is pretty straight forward. To perform a simple scan (equivalent to running binwalk with no command line options):

import pprint
from binwalk import Binwalk

binwalk = Binwalk()
pprint.PrettyPrinter().pprint(binwalk.scan('firmware.bin'))
binwalk.cleanup()

Check out the wiki for more command line usage and API examples.

Binwalk 0.5 Release

In celebration of the world not ending, a new version of Binwalk has been released. Notable changes:

  • Much improved signatures for several common file types, particularly JFFS2
  • Smart signature” keyword support, for more reliable and faster scans
  • Ability to invoke external applications to process extracted files

The latter feature is probably of most interest, and is implemented as an extension of the pre-existing –dd option:

$ binwalk --dd='gzip:gz:gunzip %e' firmware.bin

The above command instructs Binwalk to extract any file whose description contains the text ‘gzip’, save it to disk with a ‘gz’ file extension, and to then run the ‘gunzip %e’ command (the %e is a placeholder that will be replaced with the actual name of the extracted file). This allows for auto extraction and decompression of gzipped files.

Although multiple –dd options may be specified, there are probably several common file types that you always want to be extracted whenever they are encountered. Binwalk 0.5 allows you to place multiple –dd arguments into the $HOME/.binwalk/extract.conf file:

# Extract and decompress gzip and lzma files
gzip:gz:gunzip %e
lzma:7z:7zip -d %e

# Extract private keys, but don't run anything
private key:key

The extract rules from this file are applied whenever the –extract option is specified:

$ binwalk --extract firmware.bin

There are several default extract rules that come with Binwalk by default. These are stored in /usr/local/etc/binwalk/extract.conf, and will be updated whenever the –update option is specified. Note that many of these extract rules expect the firmware-mod-kit to be installed to /opt/firmware-mod-kit, but these rules can be overridden by those in the $HOME/.binwalk/extract.conf file.

This means that a Binwalk scan can now not only identify embedded files, but also extract and decompress them for you automatically:

$ binwalk --extract firmware.bin 

DECIMAL   	HEX       	DESCRIPTION
-------------------------------------------------------------------------------------------------------
0         	0x0       	TRX firmware header, little endian, header size: 28 bytes,  image size: 13533184 bytes, CRC32: 0x15289B44 flags/version: 0x10000
28        	0x1C      	gzip compressed data, was "piggy", from Unix, last modified: Mon Dec  3 13:09:06 2012, max compression
2005108   	0x1E9874  	Squashfs filesystem, little endian, non-standard signature,  version 3.1, size: 11525877 bytes, 2743 inodes, blocksize: 131072 bytes, created: Mon Dec  3 13:49:31 2012 

$ ls
1C  1E9874.squashfs  firmware.bin  squashfs-root/
$ ls squashfs-root
bin  dev  etc  home  JNAP  lib  libexec  linuxrc  mnt  opt  proc  root  sbin  sys  tmp  usr  var  www

Binwalk 0.4.5 Release

Binwalk 0.4.5 is now available. This release includes a couple of bug fixes, including a (small) memory leak, and a signature parsing bug which prevented certain signatures from loading properly.

A new command line option has been added as well: –dd. This feature instructs Binwalk to extract embedded files that it finds automatically. For example, to extract all ‘gzip’ files and save them with the extension ‘gz’:

$ binwalk firmware.bin --dd=gzip:gz

To extract all gzip files but only the first JFFS2 entry:

$ binwalk firmware.bin --dd=gzip:gz --dd=jffs2:jffs2:1

To extract every file that Binwalk identifies, use the ‘all’ keyword:

$ binwalk firmware.bin --dd=all:dat

All string matches are case insensitive. Extracted files are named by their respective hexadecimal offsets in the original file. The extracted files will contain all data from the offset where the signature was found to EOF.

Get Binwalk 0.4.5 here.