You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bddisasm/bindings/pybddisasm/pybddisasm/helpers.py

157 lines
4.4 KiB

#
# Copyright (c) 2020 Bitdefender
# SPDX-License-Identifier: Apache-2.0
#
import os
import sys
from pybddisasm.bddisasm import *
try:
from termcolor import colored
except:
colored = None
_SPACES = [
'',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
]
def print_internal(string, foreground=None, highlight=True):
no_colors = (foreground is None) or (not highlight)
if not colored or no_colors:
sys.stdout.write(string)
else:
text = colored(string, foreground)
sys.stdout.write(text)
def print_instruction(instruction, rip, highlight=False, ext_info=False):
k = 0
print_internal('%016x ' % rip)
# prefixes
for ibyte in range(0, instruction.PrefLength):
print_internal('%02x' % instruction.InstructionBytes[ibyte])
# opcodes
k += instruction.PrefLength
for ibyte in range(k, k + instruction.OpLength):
print_internal('%02x' % instruction.InstructionBytes[ibyte], 'green', highlight)
# modrm and sib
k += instruction.OpLength
for ibyte in range(k, k + instruction.HasModRm + instruction.HasSib):
print_internal('%02x' % instruction.InstructionBytes[ibyte], 'yellow', highlight)
# displacement
k += instruction.HasModRm + instruction.HasSib
for ibyte in range(k, k + instruction.DispLength):
print_internal('%02x' % instruction.InstructionBytes[ibyte], 'blue', highlight)
# relative offset/moffset/immediates
rest = instruction.Imm1Length + instruction.Imm2Length + instruction.RelOffsLength + \
instruction.MoffsetLength + instruction.HasSseImm + instruction.AddrLength
k += instruction.DispLength
for ibyte in range(k, k + rest):
print_internal('%02x' % instruction.InstructionBytes[ibyte], 'red', highlight)
# the rest of the bytes
k += rest
for ibyte in range(k, instruction.Length):
print_internal('%02x' % instruction.InstructionBytes[ibyte])
print_internal('%s' % _SPACES[16 - instruction.Length])
print_internal('%s' % instruction.Text)
if ext_info:
print_internal('\n')
print_internal('%r' % instruction)
print_internal('\n')
def disassemble_file(filepath, offset=0, size=0, rip=0, arch=64,
highlight=True, vendor='any', ext_info=False):
if not filepath:
return
with open(filepath, 'rb') as f:
total = 0
file_size = os.path.getsize(filepath)
if not size:
size = file_size
while offset < file_size and total < size:
to_read = file_size - offset
if to_read > 15:
to_read = 15
f.seek(offset, 0)
buff = f.read(to_read)
current_rip = rip + total
instr = nd_decode_ex2(buff, arch, arch, arch, vendor, current_rip)
if instr:
print_instruction(instr, current_rip, highlight, ext_info)
offset += instr['Length']
total += instr['Length']
else:
sys.stdout.write('%016x %02x %s db 0x%02x' % (current_rip, buff[0],
_SPACES[15], buff[0]))
if str.isalpha(chr(buff[0])):
sys.stdout.write(str(buff[0]))
sys.stdout.write('\n')
offset += 1
total += 1
def disassemble_hexstring(hexstring, offset=0, size=0, rip=0, arch=64,
highlight=True, vendor='any', ext_info=False):
if not hexstring:
return
buff = bytes.fromhex(''.join(hexstring))
total = 0
if not size:
size = len(buff)
while total < size:
current_rip = rip + total
instr = nd_decode_ex2(buff[total:total+16], arch, arch, arch, vendor, current_rip)
if instr:
print_instruction(instr, current_rip, highlight, ext_info)
offset += instr['Length']
total += instr['Length']
else:
sys.stdout.write('%016x %02x %s db 0x%02x\n' % (current_rip, buff[offset],
_SPACES[15], buff[offset]))
offset += 1
total += 1