* Script for generating syscall tables * Add generated syscall table * Reintroduce tracing script * Add configuration options needed by verify.py * Clean up verify; remove dependency on experimental after_hook * trace experiments * reorg verify.py * Update after merge * Remove Manticore param * Remove unused vars * Use regfile api; redo last_instr check * Fix gdb->mcore name descrepancy * Move kwargs to explicit args for Linux/SLinux * Maintain options in makeLinux to not overcomplicate the Manticore class * Address merge issues * remove debug stmt * Reintroduce options * Revert linux.py/manticore.py from master * Use the qemu -s and -R flags * Import syscalls table from master * And import extract_syscalls.py script * Fix verify reference * Move syscall to arg * Update register references * Simplify last instruction check * Add logging filter to TRACE logger as well * Be consistent with state synchronization * Be explicit about gdb types * Improve mmap debug output * Return error if ioctl is not implemented * Fix syscall sync * Make logging more self-contained * Use errno const in ioctl impl
129 lines
3.7 KiB
Python
129 lines
3.7 KiB
Python
import copy
|
|
import traceback
|
|
import os
|
|
import sys
|
|
import time
|
|
import subprocess
|
|
|
|
count = 0
|
|
|
|
prompt = ''
|
|
subproc = None
|
|
_arch = None
|
|
|
|
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, argv, port=1234, _prompt='(gdb) '):
|
|
global prompt, subproc
|
|
prompt = _prompt
|
|
gdb = 'gdb-multiarch'
|
|
try:
|
|
subproc = subprocess.Popen([gdb, argv[0]],
|
|
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(argv[0]))
|
|
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 getInstruction():
|
|
return correspond('x/i $pc\n').split('\n')[0]
|
|
|
|
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 long(val.split("0x")[-1],16)
|
|
else:
|
|
return long(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] = long(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(), long(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).strip().split('\t')[-1], 0)
|
|
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 long(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
|