manticore/tests/auto/trace.py
2018-04-03 16:47:47 -04:00

130 lines
4.5 KiB
Python

import copy
import sys
import sys
import time
import subprocess
from distorm3 import Decompose, Decode16Bits, Decode32Bits, Decode64Bits, Mnemonics, Registers
count = 0
class Gdb(subprocess.Popen):
def __init__(self, prg, prompt='(gdb) '):
"""Construct interactive Popen."""
self.prompt = prompt
subprocess.Popen.__init__(self, ['gdb', prg], stdin=subprocess.PIPE, stdout=subprocess.PIPE , stderr=subprocess.STDOUT)
def correspond(self, text):
"""Communicate with the child process without closing stdin."""
self.stdin.write(text)
self.stdin.flush()
str_buffer = ''
while not str_buffer.endswith(self.prompt):
str_buffer += self.stdout.read(1)
return str_buffer
def getR(self, reg):
reg = "$"+reg
if "XMM" in reg:
reg = reg+".uint128"
val = self.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 = self.correspond('p /x %s\n'%reg.lower()).split("0x")[-1]
return long(val.split("\n")[0],16)
def setR(self, reg, value):
self.correspond('set $%s = %s\n'%(reg.lower(), int(value)))
def setByte(self, m, value):
self.correspond('set *(char*)(%s) = %s\n'%(m,value))
def stepi(self):
#print self.correspond("x/i $pc\n")
self.correspond("stepi\n")
def getM(self, m):
try:
return long(self.correspond('x/xg %s\n'%m).split("\t")[-1].split("0x")[-1].split("\n")[0],16)
except Exception,e:
print 'x/xg %s\n'%m
print self.correspond('x/xg %s\n'%m)
raise e
return 0
def getPid(self):
return int(self.correspond('info proc\n').split("\n")[0].split(" ")[-1])
def getStack(self):
maps = file("/proc/%s/maps"%self.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('-')]
print self.correspond('dump mem lala 0x%x 0x%x\n'%(i,o))
def getByte(self, m):
arch = self.get_arch()
mask = {'i386': 0xffffffff, 'amd64': 0xffffffffffffffff}[arch]
return int(self.correspond("x/1bx %d\n"%(m&mask)).split("\t")[-1].split("\n")[0][2:],16)
def get_entry(self):
a=self.correspond('info target\n')
return int(a[a.find("Entry point:"):].split('\n')[0].split(' ')[-1][2:],16)
_arch = None
def get_arch(self):
if self._arch is not None:
return self._arch
infotarget = self.correspond('info target\n')
if 'elf32-i386' in infotarget:
self._arch = 'i386'
return 'i386'
elif 'elf64-x86-64' in infotarget:
self._arch = 'amd64'
return 'amd64'
else:
print infotarget
raise NotImplementedError()
gdb = Gdb(sys.argv[1])
arch = gdb.correspond('')
#guess arch
arch = gdb.get_arch()
#gues architecture from file
entry = gdb.get_entry()
gdb.correspond("b *0\n")
gdb.correspond("run arg1 arg2 arg3 < /dev/urandom > /dev/null\n")
gdb.correspond("d 1\n")
# Simulate no vdso (As when analized with symbemu)
found = 0
for i in range(75,120):
if gdb.getM('$sp+sizeof(void*)*%d'%i) ==0x19 and gdb.getM('$sp+%d'%(i+2))==0x1f:
found = i
if found !=0:
gdb.setByte('$sp+sizeof(void*)*%d'%found,1)
gdb.setByte('$sp+sizeof(void*)*%d'%(found+2),1)
vdso = gdb.getM('$sp+sizeof(void*)*%d'%(found+1))
for i in range(75,120):
val = gdb.getM('$sp+sizeof(void*)*%d'%i)
if val > vdso-0x10000 and val <= vdso+0x10000:
if (gdb.getM('$sp+sizeof(void*)*%d'%(i-1))) != 1:
gdb.setByte('$sp+sizeof(void*)*%d'%(i-1),1)
STACK_INSTRUCTIONS = ['BOUND', 'CALL', 'CALLF', 'ENTER', 'INT', 'INT1', 'INTO', 'IRET', 'IRETD', 'LEAVE', 'POP', 'POPA', 'POPAD', 'POPF', 'POPFD', 'PUSH', 'PUSHA', 'PUSHAD', 'PUSHF', 'PUSHFD', 'RETF', 'RETN', 'RET']
while True:
try:
stepped = False
pc = gdb.getR({'i386': 'EIP', 'amd64': 'RIP'}[arch])
print hex(pc)
gdb.stepi()
print gdb.correspond('info registers\n')
except Exception,e:
print e
print "# Processed %d instructions." % count