Commit 35538acb by devttys0

Improved --disasm efficiency

parent 366a4faa
......@@ -31,7 +31,7 @@ $ sudo apt-get install libqt4-opengl python-opengl python-qt4 python-qt4-gl pyth
$ sudo pip install pyqtgraph
```
Binwalk's "Fuzzy Hashing" options requires the libfuzzy library:
Binwalk's "Fuzzy Hashing" options require the libfuzzy library:
```bash
$ sudo apt-get install libfuzzy2
......@@ -60,7 +60,7 @@ $ (cd sasquatch && make && sudo make install)
Bundled Software
================
For convenience, the following libraries are bundled with binwalk and will not conflict with system-wide libraries:
For convenience, the following libraries are bundled with binwalk and installed so as not to conflict with system-wide libraries:
libmagic
......
import capstone
import binwalk.core.common
import binwalk.core.compat
from binwalk.core.module import Module, Option, Kwarg
class Architecture(object):
......@@ -18,17 +19,17 @@ class CodeID(Module):
Option(short='Y',
long='disasm',
kwargs={'enabled' : True},
description='Identify executable code using the capstone disassembler'),
description='Identify the architecture of files containing executable code'),
Option(short='T',
long='minsn',
type=int,
kwargs={'min_insn_count' : 0},
description='Minimum number of instructions to be considered valid'),
description='Minimum number of consecutive instructions to be considered valid (default: %d)' % DEFAULT_MIN_INSN_COUNT),
]
KWARGS = [
Kwarg(name='enabled', default=False),
Kwarg(name='min_insn_count', default=0),
Kwarg(name='min_insn_count', default=DEFAULT_MIN_INSN_COUNT),
]
ARCHITECTURES = [
......@@ -89,9 +90,16 @@ class CodeID(Module):
]
def init(self):
self.disassemblers = []
if not self.min_insn_count:
self.min_insn_count = self.DEFAULT_MIN_INSN_COUNT
self.disasm_data_size = self.min_insn_count * 10
for arch in self.ARCHITECTURES:
self.disassemblers.append((capstone.Cs(arch.type, (arch.mode + arch.endianess)), arch.description))
def scan_file(self, fp):
total_read = 0
......@@ -100,20 +108,28 @@ class CodeID(Module):
if not data:
break
offset = 0
while offset < dlen:
for arch in self.ARCHITECTURES:
md = capstone.Cs(arch.type, (arch.mode + arch.endianess))
ninsn = len([insn for insn in md.disasm_lite(data[offset:offset+(self.min_insn_count*10)], 0)])
binwalk.core.common.debug("0x%.8X %s, at least %d valid instructions" % ((total_read+offset), arch.description, ninsn))
if ninsn >= self.min_insn_count:
description = arch.description + ", at least %d valid instructions" % ninsn
r = self.result(offset=total_read+offset, file=fp, description=description)
if r.valid and r.display and not self.config.verbose:
return
offset += 1
# If this data block doesn't contain at least two different bytes, skip it
# to prevent false positives (e.g., "\x00\x00\x00x\00" is a nop in MIPS).
if len(set(data)) >= 2:
block_offset = 0
while block_offset < dlen:
# Don't pass the entire data block into disasm_lite, it's horribly inefficient
# to pass large strings around in Python. Break it up into smaller code blocks instead.
code_block = binwalk.core.compat.str2bytes(data[block_offset:block_offset+self.disasm_data_size])
# If this code block doesn't contain at least two different bytes, skip it
# to prevent false positives (e.g., "\x00\x00\x00x\00" is a nop in MIPS).
if len(set(code_block)) >= 2:
for (md, description) in self.disassemblers:
ninsn = len([insn for insn in md.disasm_lite(code_block, 0)])
binwalk.core.common.debug("0x%.8X %s, at least %d valid instructions" % ((total_read+block_offset), description, ninsn))
if ninsn >= self.min_insn_count:
r = self.result(offset=total_read+block_offset, file=fp, description=(description + ", at least %d valid instructions" % ninsn))
if r.valid and r.display and not self.config.verbose:
return
block_offset += 1
total_read += dlen
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment