Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 32 additions & 12 deletions smda/common/BinaryInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ def __init__(self, binary):
self.sha256 = hashlib.sha256(binary).hexdigest()
self.sha1 = hashlib.sha1(binary).hexdigest()
self.md5 = hashlib.md5(binary).hexdigest()
self._lief_binary = None

def _get_lief_binary(self):
if self._lief_binary is None:
self._lief_binary = lief.parse(self.raw_data)
return self._lief_binary

def getOep(self):
if self.oep is None:
lief_result = lief.parse(self.raw_data)
lief_result = self._get_lief_binary()
if isinstance(lief_result, lief.PE.Binary):
self.oep = lief_result.optional_header.addressof_entrypoint
elif isinstance(lief_result, lief.ELF.Binary):
Expand All @@ -49,7 +55,7 @@ def getOep(self):

def getExportedFunctions(self):
if self.exported_functions is None:
lief_result = lief.parse(self.raw_data)
lief_result = self._get_lief_binary()
if isinstance(lief_result, lief.PE.Binary):
self.exported_functions = PeSymbolProvider(None).parseExports(lief_result)
elif isinstance(lief_result, lief.ELF.Binary):
Expand All @@ -58,7 +64,7 @@ def getExportedFunctions(self):

def getImportedFunctions(self):
if self.imported_functions is None:
lief_result = lief.parse(self.raw_data)
lief_result = self._get_lief_binary()
if isinstance(lief_result, lief.PE.Binary):
PeSymbolProvider(None).parseSymbols(lief_result)
self.imported_functions = PeSymbolProvider(None).parseImports(lief_result)
Expand All @@ -68,26 +74,40 @@ def getImportedFunctions(self):

def getSymbols(self):
if self.symbols is None:
lief_result = lief.parse(self.raw_data)
lief_result = self._get_lief_binary()
if isinstance(lief_result, lief.PE.Binary):
self.symbols = PeSymbolProvider(None).parseSymbols(lief_result)
elif isinstance(lief_result, lief.ELF.Binary):
self.symbols = ElfSymbolProvider(None).parseSymbols(lief_result.dynamic_symbols)
return self.symbols

def getSections(self):
pefile = lief.parse(self.raw_data)
# TODO 20201030 might want to add ELF sections as well
if not isinstance(pefile, lief.PE.Binary):
"""
Generator that yields (name, start_addr, end_addr) for each section.
Supports PE and ELF binaries.
"""
parsed_binary = self._get_lief_binary()
if not parsed_binary:
return

is_pe = isinstance(parsed_binary, lief.PE.Binary)
is_elf = isinstance(parsed_binary, lief.ELF.Binary)

if not (is_pe or is_elf) or not parsed_binary.sections:
return
if pefile and pefile.sections:
for section in pefile.sections:

for section in parsed_binary.sections:
if is_pe:
section_start = self.base_addr + section.virtual_address
section_size = section.virtual_size
if section_size % 0x1000 != 0:
section_size += 0x1000 - (section_size % 0x1000)
section_end = section_start + section_size
yield section.name, section_start, section_end
elif is_elf:
section_start = section.virtual_address
section_size = section.size

section_end = section_start + section_size
yield section.name, section_start, section_end

def isInCodeAreas(self, address):
is_inside = False
Expand All @@ -101,7 +121,7 @@ def isInCodeAreas(self, address):

def getHeaderBytes(self):
if self.raw_data:
lief_result = lief.parse(self.raw_data)
lief_result = self._get_lief_binary()
if isinstance(lief_result, lief.PE.Binary):
return self.raw_data[:0x400]
elif isinstance(lief_result, lief.ELF.Binary):
Expand Down
4 changes: 4 additions & 0 deletions tests/testFileFormatParsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ def testElfParsingWithBashlite(self):
bashlite_unmapped_disassembly = disasm.disassembleUnmappedBuffer(bashlite_binary)
assert bashlite_unmapped_disassembly.num_functions == 177
assert len([f.function_name for f in bashlite_unmapped_disassembly.getFunctions() if f.function_name]) == 174
# test section extraction
sections = {name: (start, end) for name, start, end in binary_info.getSections()}
assert len(sections) > 0
assert ".text" in sections

def testDotnetParsingWithNjRAT(self):
disasm = Disassembler(config, backend="cil")
Expand Down