Commit 96761662 by devttys0

Updated disasm for reliability, updated vxworks symbol table signature

parent 76ff729a
......@@ -7,4 +7,7 @@ from binwalk.modules.extractor import Extractor
from binwalk.modules.entropy import Entropy
from binwalk.modules.heuristics import HeuristicCompressionAnalyzer
from binwalk.modules.compression import RawCompression
#from binwalk.modules.codeid import CodeID
try:
from binwalk.modules.disasm import Disasm
except ImportError:
pass
......@@ -3,13 +3,19 @@ import binwalk.core.common
import binwalk.core.compat
from binwalk.core.module import Module, Option, Kwarg
class ArchResult(object):
def __init__(self, **kwargs):
for (k,v) in kwargs.iteritems():
setattr(self, k, v)
class Architecture(object):
def __init__(self, **kwargs):
for (k, v) in kwargs.iteritems():
setattr(self, k, v)
class CodeID(Module):
class Disasm(Module):
THRESHOLD = 10
DEFAULT_MIN_INSN_COUNT = 500
TITLE = "Disassembly Scan"
......@@ -17,35 +23,22 @@ class CodeID(Module):
CLI = [
Option(short='Y',
long='code',
long='disasm',
kwargs={'enabled' : True},
description='Attempts to identify the CPU architecture of a file using the capstone disassembler'),
description='Identify the CPU architecture of a file using the capstone disassembler'),
Option(short='T',
long='minsn',
type=int,
kwargs={'min_insn_count' : 0},
description='Minimum number of consecutive instructions to be considered valid (default: %d)' % DEFAULT_MIN_INSN_COUNT),
Option(short='V',
long='disasm',
kwargs={'show_disasm' : True},
description='Display the disassembled instructions'),
]
KWARGS = [
Kwarg(name='enabled', default=False),
Kwarg(name='show_disasm', default=False),
Kwarg(name='min_insn_count', default=DEFAULT_MIN_INSN_COUNT),
]
ARCHITECTURES = [
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_32,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="MIPS executable code, 32-bit, big endian"),
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_32,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="MIPS executable code, 32-bit, little endian"),
Architecture(type=capstone.CS_ARCH_ARM,
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_BIG_ENDIAN,
......@@ -54,19 +47,29 @@ class CodeID(Module):
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="ARM executable code, 32-bit, little endian"),
Architecture(type=capstone.CS_ARCH_ARM64,
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="ARM executable code, 64-bit, big endian"),
Architecture(type=capstone.CS_ARCH_ARM64,
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="ARM executable code, 64-bit, little endian"),
Architecture(type=capstone.CS_ARCH_PPC,
mode=capstone.CS_MODE_BIG_ENDIAN,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="PPC executable code, 32/64-bit, big endian"),
#Architecture(type=capstone.CS_ARCH_MIPS,
# mode=capstone.CS_MODE_16,
# endianess=capstone.CS_MODE_BIG_ENDIAN,
# description="MIPS executable code, 16-bit, big endian"),
#Architecture(type=capstone.CS_ARCH_MIPS,
# mode=capstone.CS_MODE_16,
# endianess=capstone.CS_MODE_LITTLE_ENDIAN,
# description="MIPSEL executable code, 16-bit, little endian"),
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_64,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="MIPS executable code, 32/64-bit, big endian"),
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_64,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="MIPS executable code, 32/64-bit, little endian"),
Architecture(type=capstone.CS_ARCH_ARM,
mode=capstone.CS_MODE_THUMB,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
......@@ -75,23 +78,6 @@ class CodeID(Module):
mode=capstone.CS_MODE_THUMB,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="ARM executable code, 16-bit (Thumb), big endian"),
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_64,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="MIPS executable code, 64-bit, big endian"),
Architecture(type=capstone.CS_ARCH_MIPS,
mode=capstone.CS_MODE_64,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="MIPS executable code, 64-bit, little endian"),
Architecture(type=capstone.CS_ARCH_ARM64,
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_BIG_ENDIAN,
description="ARM executable code, 64-bit, big endian"),
Architecture(type=capstone.CS_ARCH_ARM64,
mode=capstone.CS_MODE_ARM,
endianess=capstone.CS_MODE_LITTLE_ENDIAN,
description="ARM executable code, 64-bit, little endian"),
]
def init(self):
......@@ -109,39 +95,62 @@ class CodeID(Module):
total_read = 0
while True:
result = None
(data, dlen) = fp.read_block()
if not data:
break
# 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).
# to prevent false positives (e.g., "\x00\x00\x00\x00" is a nop in MIPS).
if len(set(data)) >= 2:
block_offset = 0
while block_offset < dlen:
# Loop through the entire block, or until we're pretty sure we've found some valid code in this block
while (block_offset < dlen) and (result is None or result.count < self.THRESHOLD):
# 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).
# to prevent false positives (e.g., "\x00\x00\x00\x00" is a nop in MIPS).
if len(set(code_block)) >= 2:
for (md, description) in self.disassemblers:
insns = [insn for insn in md.disasm_lite(code_block, (total_read+block_offset))]
binwalk.core.common.debug("0x%.8X %s, at least %d valid instructions" % ((total_read+block_offset), description, len(insns)))
binwalk.core.common.debug("0x%.8X %s, at least %d valid instructions" % ((total_read+block_offset),
description,
len(insns)))
# Did we disassemble at least self.min_insn_count instructions?
if len(insns) >= self.min_insn_count:
r = self.result(offset=total_read+block_offset, file=fp, description=(description + ", at least %d valid instructions" % len(insns)))
if r.valid and r.display:
if self.show_disasm:
for (position, size, mnem, opnds) in insns:
self.result(offset=position, file=fp, description="\t%s %s" % (mnem, opnds))
if not self.config.verbose:
return
# If we've already found the same type of code in this block, simply update the result counter
if result and result.description == description:
result.count += 1
if result.count >= self.THRESHOLD:
break
else:
result = ArchResult(offset=total_read+block_offset+fp.offset,
description=description,
insns=insns,
count=1)
block_offset += 1
if result is not None:
r = self.result(offset=result.offset,
file=fp,
description=(result.description + ", at least %d valid instructions" % len(result.insns)))
if r.valid and r.display:
if self.config.verbose:
for (position, size, mnem, opnds) in result.insns:
self.result(offset=position, file=fp, description="\t\t%s %s" % (mnem, opnds))
if not self.config.keep_going:
return
total_read += dlen
self.status.completed = total_read
def run(self):
for fp in iter(self.next_file, None):
......
......@@ -37,7 +37,7 @@ class General(Module):
Option(long='continue',
short='k',
kwargs={'keep_going' : True},
description='Show all matches for every offset, not just the first'),
description="Don't stop at the first match"),
Option(long='swap',
short='g',
type=int,
......
......@@ -584,7 +584,9 @@
# Signatures to identify the start of a VxWorks symbol table
8 string \x00\x00\x05\x00\x00\x00\x00\x00 VxWorks symbol table, big endian,
>4 belong 0 invalid
>4 belong x first entry: [type: function, code address: 0x%X,
>0 belong 0 invalid
>0 belong x symbol address: 0x%X]{display-once}
>24 belong !0x500
>>24 belong !0x700
......@@ -600,7 +602,9 @@
>>>72 belong !0x900 \b, invalid
8 string \x00\x00\x07\x00\x00\x00\x00\x00 VxWorks symbol table, big endian,
>4 belong 0 invalid
>4 belong x first entry: [type: initialized data, code address: 0x%X,
>0 belong 0 invalid
>0 belong x symbol address: 0x%X]{display-once}
>24 belong !0x500
>>24 belong !0x700
......@@ -616,7 +620,9 @@
>>>72 belong !0x900 \b, invalid
8 string \x00\x00\x09\x00\x00\x00\x00\x00 VxWorks symbol table, big endian,
>4 belong 0 invalid
>4 belong x first entry: [type: uninitialized data, code address: 0x%X,
>0 belong 0 invalid
>0 belong x symbol address: 0x%X]{display-once}
>24 belong !0x500
>>24 belong !0x700
......@@ -632,7 +638,9 @@
>>>72 belong !0x900 \b, invalid
8 string \x00\x05\x00\x00\x00\x00\x00\x00 VxWorks symbol table, little endian,
>4 lelong 0 invalid
>4 lelong x first entry: [type: function, code address: 0x%X,
>0 lelong 0 invalid
>0 lelong x symbol address: 0x%X]{display-once}
>24 lelong !0x500
>>24 lelong !0x700
......@@ -648,7 +656,9 @@
>>>72 lelong !0x900 \b, invalid
8 string \x00\x07\x00\x00\x00\x00\x00\x00 VxWorks symbol table, little endian,
>4 lelong 0 invalid
>4 lelong x first entry: [type: initialized data, code address: 0x%X,
>0 lelong 0 invalid
>0 lelong x symbol address: 0x%X]{display-once}
>24 lelong !0x500
>>24 lelong !0x700
......@@ -664,7 +674,9 @@
>>>72 lelong !0x900 \b, invalid
8 string \x00\x09\x00\x00\x00\x00\x00\x00 VxWorks symbol table, little endian,
>4 lelong 0 invalid
>4 lelong x first entry: [type: uninitialized data, code address: 0x%X,
>0 lelong 0 invalid
>0 lelong x symbol address: 0x%X]{display-once}
>24 lelong !0x500
>>24 lelong !0x700
......
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