Skip to content

Commit

Permalink
fixes and enhances function recover plugin
Browse files Browse the repository at this point in the history
The function recovery plugin was broken for some amount of time, as we
passed symbol file to bap, effectively disabling BAP own function
finding capabilities, so bap always returned the same amount of function
starts.

This commit also enhances the recovery plugin, by lowering the recovery
threshold. Although it will lead to more false positives it is
acceptable since IDA will ignore function starts that occur in a body of
an discovered function, that was already discovered and
disassembled. Since most of the functions have their bodies after
starts, we added sorting of the addresses, so that function starts are
added to the system in the ascending order.

This commit also adds two new attributes to the BapIda class. The first
one is called [args] and is a list of default arguments, shared by all
instances. It is useful to adapt the behavior of the plugins to your
needs, and to perform fast prototyping and debugging.

The second attribute is called [plugins] and it contains a list of
available BAP plugins. This is useful, when an IDA plugin needs to adapt
its behavior based on the presence of particular BAP plugins. For
example, the function start identification plugin, is allowed to tackle
with the byteweight parameters only if it is installed.
  • Loading branch information
ivg committed Jun 29, 2017
1 parent d0d7bf8 commit 289fd86
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
26 changes: 17 additions & 9 deletions plugins/bap/plugins/bap_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,32 @@
import idaapi
import idc

from heapq import heappush, heappop
from bap.utils.run import BapIda


class FunctionFinder(BapIda):
def __init__(self):
super(FunctionFinder, self).__init__()
super(FunctionFinder, self).__init__(symbols=False)
self.action = 'looking for function starts'
self.syms = self.tmpfile('syms', mode='r')
self.args += [
'--print-symbol-format', 'addr',
'--dump', 'symbols:{0}'.format(self.syms.name)
]

# we can be a little bit more promiscuous since IDA will ignore
# function starts that occur in the middle of a function
if 'byteweight' in self.plugins and not \
'--no-byteweight' in self.args:
self.args += [
'--byteweight-threshold', '0.5',
'--byteweight-length', '4',
]


class BAP_Functions(idaapi.plugin_t):
"""Plugin to get functions from BAP and mark them in IDA."""
"""Uses BAP to find missed functions"""

flags = idaapi.PLUGIN_FIX
comment = "BAP Functions Plugin"
Expand All @@ -40,15 +50,13 @@ def mark_functions(self):
analysis.run()

def add_starts(self, bap):
idaapi.refresh_idaview_anyway()
syms = []
for line in bap.syms:
line = line.strip()
if len(line) == 0:
continue
addr = int(line, 16)
end_addr = idaapi.BADADDR
idaapi.add_func(addr, end_addr)
heappush(syms, int(line, 16))
for i in range(len(syms)):
idaapi.add_func(heappop(syms), idaapi.BADADDR)
idc.Refresh()
idaapi.refresh_idaview_anyway()

def init(self):
"""Initialize Plugin."""
Expand Down
17 changes: 15 additions & 2 deletions plugins/bap/utils/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,24 @@ class Bap(object):
We will try to keep it clean from IDA
specifics, so that later we can lift it to the bap-python library
Attributes:
DEBUG print executed commands and keep temporary files
args default arguments, inserted after `bap <input>`
plugins a list of available plugins
"""

DEBUG = False

args = []

plugins = []

def __init__(self, bap, input_file):
"""Sandbox for the BAP process.
Each process is sandboxed, so that all intermediated data is
Each process is sandboxed, so that all intermediate data are
stored in a temporary directory.
instance variables:
Expand All @@ -50,7 +60,7 @@ def __init__(self, bap, input_file):
"""
self.tmpdir = tempfile.mkdtemp(prefix="bap")
self.args = [bap, input_file]
self.args = [bap, input_file] + self.args
self.proc = None
self.fds = []
self.out = self.tmpfile("out")
Expand All @@ -59,6 +69,9 @@ def __init__(self, bap, input_file):
self.env = {'BAP_LOG_DIR': self.tmpdir}
if self.DEBUG:
self.env['BAP_DEBUG'] = 'yes'
if not Bap.plugins:
with os.popen(bap + ' --list-plugins') as out:
Bap.plugins = [e.split()[1] for e in out]

def run(self):
"starts BAP process"
Expand Down

0 comments on commit 289fd86

Please sign in to comment.