Files
manticore/utils/gdb.py
T
2017-02-13 12:04:15 -05:00

131 lines
3.7 KiB
Python

import copy
import traceback
import os
import sys
import time
import subprocess
count = 0
prompt = ''
subproc = None
prog = ''
_arch = None
def set_program(_prog):
global prog
prog = _prog
def drain():
str_buffer = ''
while not str_buffer.endswith(prompt):
c = subproc.stdout.read(1)
str_buffer += c
return str_buffer[:-len(prompt)]
def start(arch, port=1234, _prompt='(gdb) '):
global prompt, subproc
prompt = _prompt
gdb = 'gdb-multiarch'
try:
subproc = subprocess.Popen([gdb, prog],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
except OSError:
msg = "'{}' binary not found in PATH (needed for tracing)".format(gdb)
raise RuntimeError(msg)
drain()
correspond('set architecture {}\n'.format(arch))
correspond('file {}\n'.format(prog))
correspond('target remote :{}\n'.format(port))
correspond('set pagination off\n')
def correspond(text):
"""Communicate with the child process without closing stdin."""
subproc.stdin.write(text)
subproc.stdin.flush()
return drain()
def getR(reg):
reg = "$"+reg
if "XMM" in reg:
reg = reg+".uint128"
val = correspond('p %s\n'%reg.lower()).split("=")[-1].split("\n")[0]
if "0x" in val:
return int(val.split("0x")[-1],16)
else:
return int(val)
if "FLAG" in reg:
reg = "(unsigned) "+reg
if reg in ['$R%dB'%i for i in range(16)] :
reg = reg[:-1] + "&0xff"
if reg in ['$R%dW'%i for i in range(16)] :
reg = reg[:-1] + "&0xffff"
val = correspond('p /x %s\n'%reg.lower())
val = val.split("0x")[-1]
return long(val.split("\n")[0],16)
def getCanonicalRegisters():
reg_output = correspond('info reg\n')
registers = {}
for line in reg_output.split("\n"):
line = line.strip()
if not line:
continue
name, hex_val = line.split()[:2]
if name != 'cpsr':
registers[name] = int(hex_val, 0)
else:
# We just want the NZCV flags
registers[name] = int(hex_val, 0) & 0xF0000000
return registers
def setR(reg, value):
correspond('set $%s = %s\n'%(reg.lower(), int(value)))
def stepi():
#print subproc.correspond("x/i $pc\n")
correspond("stepi\n")
def getM(m):
try:
return long(correspond('x/xg %s\n'%m).split("\t")[-1].split("0x")[-1].split("\n")[0],16)
except Exception,e:
raise e
return 0
def getPid():
return int(correspond('info proc\n').split("\n")[0].split(" ")[-1])
def getStack():
maps = file("/proc/%s/maps"%correspond('info proc\n').split("\n")[0].split(" ")[-1]).read().split("\n")
i,o = [ int(x,16) for x in maps[-3].split(" ")[0].split('-')]
def setByte(addr, val):
cmdstr = 'set {{char}}{} = {}'.format(addr, ord(val))
correspond(cmdstr + '\n')
def getByte(m):
arch = get_arch()
mask = {'i386': 0xffffffff,
'armv7': 0xffffffff,
'amd64': 0xffffffffffffffff}[arch]
return int(correspond("x/1bx %d\n"%(m&mask)).split("\t")[-1].split("\n")[0][2:],16)
def get_entry():
a=correspond('info target\n')
return int(a[a.find("Entry point:"):].split('\n')[0].split(' ')[-1][2:],16)
def get_arch():
global _arch
if _arch is not None:
return _arch
infotarget = correspond('info target\n')
if 'elf32-i386' in infotarget:
_arch = 'i386'
elif 'elf64-x86-64' in infotarget:
_arch = 'amd64'
elif 'elf32-littlearm' in infotarget:
_arch = 'armv7'
else:
print infotarget
raise NotImplemented
return _arch