Last active
April 27, 2016 13:41
-
-
Save joshwatson/fa3808f8e665d9785a197c720816dffc to your computer and use it in GitHub Desktop.
Binary Ninja script to identify virtual functions missed by auto-analysis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python | |
import sys | |
import platform | |
import time | |
import os | |
try: | |
import binaryninja as binja | |
except ImportError: | |
if platform.mac_ver()[0]: | |
sys.path.append('/Applications/Binary Ninja.app/Contents/Resources/python') | |
if platform.dist()[0]: | |
# I don't know where your linux install is. Here's mine | |
sys.path.append('/data/binaryninja/python') | |
if platform.win32_ver()[0]: | |
sys.path.append(r'C:\Program Files\Vector35\BinaryNinja\python') | |
import binaryninja as binja | |
if len(sys.argv) < 3: | |
print 'usage: find_virtual_functions.py <input_db> [output_db]' | |
raise SystemExit(-1) | |
input_db = sys.argv[1] | |
# if no output_db, save over input_db | |
if len(sys.argv) < 4: | |
output_db = input_db | |
fm = binja.FileMetadata() | |
db = fm.open_existing_database(input_db) | |
if db is None: | |
print 'Could not open database!' | |
raise SystemExit(-1) | |
bv = db.get_view_of_type('PE') | |
reader = binja.BinaryReader(bv) | |
bv.update_analysis() | |
time.sleep(1) | |
# Start looking for read only pages after the PE header | |
# Every page and its page permissions have to be checked, | |
# because segment information isn't yet reachable in the API. | |
for page in range(bv.start+0x1000, bv.end, 0x1000): | |
if (bv.is_offset_readable(page) and | |
not bv.is_offset_executable(page) and | |
not bv.is_offset_writable(page)): | |
reader.seek(page) | |
# assume that function pointers are aligned | |
for offset in range(page, page+0x1000, bv.address_size): | |
if bv.address_size == 4: | |
addr = reader.read32le() | |
elif bv.address_size == 8: | |
addr = reader.read64le() | |
else: | |
print 'Uh, what arch is this?!' | |
raise SystemExit(-1) | |
if addr is None: | |
continue | |
# If we find a pointer to executable memory, | |
# it is probably a virtual function. Go ahead and add it. | |
if bv.is_offset_executable(addr): | |
# print 'Found virtual function at {:x}'.format(addr) | |
bv.add_function(bv.platform, addr) | |
fm.create_database(output_db) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment