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