def map(F, **kwargs): """Execute the callback `F` on all functions in the database. Synonymous to `map(F, database.functions())` but with some extra logging to display the current progress. The `F` parameter is defined as a function taking either an `(address, **kwargs)` or a `(index, address, **kwargs)`. Any keyword arguments are passed to `F` unmodified. """ f1 = lambda (idx, ea), **kwargs: F(ea, **kwargs) f2 = lambda (idx, ea), **kwargs: F(idx, ea, **kwargs) f = f1 if F.func_code.co_argcount == 1 else f2 result, all = [], database.functions() total = len(all) if len(all): ea = next(iter(all)) try: for i, ea in enumerate(all): ui.navigation.set(ea) print("{:#x}: processing # {:d} of {:d} : {:s}".format( ea, i + 1, total, func.name(ea))) result.append(f((i, ea), **kwargs)) except KeyboardInterrupt: print("{:#x}: terminated at # {:d} of {:d} : {:s}".format( ea, i + 1, total, func.name(ea))) return result
def map(F, **kwargs): """Execute the callback `F` on all functions in the database. Synonymous to `map(F, database.functions())` but with some extra logging to display the current progress. The `F` parameter is defined as a function taking either an `(address, **kwargs)` or a `(index, address, **kwargs)`. Any keyword arguments are passed to `F` unmodified. """ f1 = lambda idx, ea, **kwargs: F(ea, **kwargs) f2 = lambda idx, ea, **kwargs: F(idx, ea, **kwargs) Ff = internal.utils.pycompat.method.function(F) if isinstance( F, types.MethodType) else F Fc = internal.utils.pycompat.function.code(Ff) f = f1 if internal.utils.pycompat.code.argcount(Fc) == 1 else f2 result, all = [], database.functions() total = len(all) if len(all): ea = next(item for item in all) try: for i, ea in enumerate(all): ui.navigation.set(ea) six.print_("{:#x}: processing # {:d} of {:d} : {:s}".format( ea, 1 + i, total, func.name(ea))) result.append(f(i, ea, **kwargs)) except KeyboardInterrupt: six.print_("{:#x}: terminated at # {:d} of {:d} : {:s}".format( ea, 1 + i, total, func.name(ea))) return result
def below(ea, includeSegment=False): '''Return all of the function names and their offset that are called by the function at `ea`.''' tryhard = lambda ea: "{:s}{:+x}".format(func.name(func.top( ea)), ea - func.top(ea)) if func.within(ea) else "{:+x}".format( ea) if func.name(ea) is None else func.name(ea) return '\n'.join(':'.join( [segment.name(ea), tryhard(ea)] if includeSegment else [tryhard(ea)]) for ea in func.down(ea))
def above(ea, includeSegment=False): '''Return all of the function names and their offset that calls the function at `ea`.''' tryhard = lambda ea: "{:s}{:+x}".format(func.name(func.top( ea)), ea - func.top(ea)) if func.within(ea) else "{:+x}".format( ea) if func.name(ea) is None else func.name(ea) return '\n'.join( ':'.join((segment.name(ea), tryhard(ea)) if includeSegment else (tryhard(ea), )) for ea in func.up(ea))
def checkmarks(): '''Output all functions (sys.stdout) containing more than 1 mark.''' res = [] for a, m in database.marks(): try: res.append((function.top(a), a, m)) except ValueError: pass continue d = list(res) d.sort(lambda a, b: cmp(a[0], b[0])) flookup = {} for fn, a, m in d: try: flookup[fn].append((a, m)) except: flookup[fn] = [(a, m)] continue functions = [(k, v) for k, v in flookup.items() if len(v) > 1] if not functions: logging.warning( 'There are no functions available containing multiple marks.') return for k, v in functions: print >> sys.stdout, "{:x} : in function {:s}".format( k, function.name(function.byAddress(k))) print >> sys.stdout, '\n'.join( ("- {:x} : {:s}".format(a, m) for a, m in sorted(v))) return
def makecall(ea): if not function.contains(ea, ea): return None # scan down until we find a call that references something chunk, = ((l,r) for l,r in function.chunks(ea) if l <= ea <= r) result = [] while (len(result) < 1) and ea < chunk[1]: # FIXME: it's probably not good to just scan for a call if not instruction(ea).startswith('call '): ea = next(ea) continue result = cxdown(ea) if len(result) != 1: raise ValueError('Invalid code reference: %x %s'% (ea,repr(result))) fn, = result result = [] for offset,name,size in function.getArguments(fn): left,_ = function.stackwindow(ea, offset+config.bits()/8) # FIXME: if left is not an assignment or a push, find last assignment result.append((name,left)) result = ['%s=%s'%(name,_instruction.op_repr(ea,0)) for name,ea in result] return '%s(%s)'%(internal.declaration.demangle(function.name(function.byAddress(fn))), ','.join(result))
def dump_labels(func, statement="g"): Escape = lambda s: s.replace('"', '\\"') for ea, t in fn.select(func, 'name'): print 'bp {:s} ".printf \\"label {:s}:{:s}\\\\n\\";{:s}"'.format( eaToReference(ea), fn.name(func), Escape(t['name']), Escape(statement)) return
def checkmarks(): '''Output all functions (sys.stdout) containing more than 1 mark.''' res = [] for a,m in database.marks(): try: res.append((function.top(a), a, m)) except ValueError: pass continue d = list(res) d.sort( lambda a,b: cmp(a[0], b[0]) ) flookup = {} for fn,a,m in d: try: flookup[fn].append((a,m)) except: flookup[fn] = [(a,m)] continue functions = [ (k,v) for k,v in flookup.items() if len(v) > 1 ] if not functions: logging.warning('There are no functions available containing multiple marks.') return for k,v in functions: print >>sys.stdout, '%x : in function %s'% (k,function.name(function.byAddress(k))) print >>sys.stdout, '\n'.join( ('- %x : %s'%(a,m) for a,m in sorted(v)) ) return
def checkmarks(): """Emit all functions that contain more than 1 mark within them. As an example, if marks are used to keep track of backtraces then this tool will emit where those backtraces intersect. """ res = [] for a, m in database.marks(): try: res.append((func.top(a), a, m)) except internal.exceptions.FunctionNotFoundError: pass continue d = list(res) d.sort( lambda a, b: cmp(a[0], b[0]) ) flookup = {} for fn, a, m in d: try: flookup[fn].append((a, m)) except: flookup[fn] = [(a, m)] continue functions = [ (k, v) for k, v in flookup.items() if len(v) > 1 ] if not functions: logging.warning('There are no functions available containing multiple marks.') return for k, v in functions: print >>sys.stdout, "{:#x} : in function {:s}".format(k, func.name(func.byAddress(k))) print >>sys.stdout, '\n'.join( ("- {:#x} : {:s}".format(a, m) for a, m in sorted(v)) ) return
def checkmarks(): """Emit all functions that contain more than 1 mark within them. As an example, if marks are used to keep track of backtraces then this tool will emit where those backtraces intersect. """ listable = [] for a, m in database.marks(): try: listable.append((func.top(a), a, m)) except internal.exceptions.FunctionNotFoundError: pass continue d = listable[:] d.sort(key=lambda item: item[0]) flookup = {} for fn, a, m in d: try: flookup[fn].append((a, m)) except: flookup[fn] = [(a, m)] continue functions = [ (k, v) for k, v in flookup.items() if len(v) > 1 ] if not functions: logging.warning('There are no functions available containing multiple marks.') return for k, v in functions: six.print_("{:#x} : in function {:s}".format(k, func.name(func.by_address(k))), file=sys.stdout) six.print_('\n'.join(("- {:#x} : {:s}".format(a, m) for a, m in sorted(v))), file=sys.stdout) return
def makecall(ea): if not function.contains(ea, ea): return None # scan down until we find a call that references something chunk, = ((l, r) for l, r in function.chunks(ea) if l <= ea <= r) result = [] while (len(result) < 1) and ea < chunk[1]: # FIXME: it's probably not good to just scan for a call if not instruction(ea).startswith('call '): ea = next(ea) continue result = cxdown(ea) if len(result) != 1: raise ValueError('Invalid code reference: %x %s' % (ea, repr(result))) fn, = result result = [] for offset, name, size in function.getArguments(fn): left, _ = function.stackwindow(ea, offset + config.bits() / 8) # FIXME: if left is not an assignment or a push, find last assignment result.append((name, left)) result = [ '%s=%s' % (name, _instruction.op_repr(ea, 0)) for name, ea in result ] return '%s(%s)' % (_declaration.demangle( function.name(function.byAddress(fn))), ','.join(result))
def change_key_to_standard(dic1, dic2): dic3 = {} for key in dic2: if dic1.has_key(key): if not dic3.has_key(key): dic3[key] = dic2[key] elif dic3.has_key(key): dic3[key] += dic2[key] elif not dic1.has_key(key): A = [] A = name(key) #if 'OXT' in A[0]: # A[0] = A[0].replace('OXT','O') #if 'OXT' in A[1]: # A[1] = A[1].replace('OXT','O') ind0 = A[0].index('-') ind1 = A[1].index('-') if 'HIE' in A[0]: A[0] = A[0].replace('HIE', 'HID') elif 'HIP' in A[0]: A[0] = A[0].replace('HIP', 'HID') elif 'HIS' in A[0]: A[0] = A[0].replace('HIS', 'HID') if 'HIE' in A[1]: A[1] = A[1].replace('HIE', 'HID') elif 'HIP' in A[1]: A[1] = A[1].replace('HIP', 'HID') elif 'HIS' in A[1]: A[1] = A[1].replace('HIS', 'HID') if len(A[0][ind0 + 1:]) == 3: resi1 = A[0][ind0 + 1:] elif len(A[0][ind0 + 1:]) == 4: resi1 = A[0][ind0 + 2:] if len(A[1][ind1 + 1:]) == 3: resi2 = A[1][ind1 + 1:] elif len(A[1][ind1 + 1:]) == 4: resi2 = A[1][ind1 + 2:] key_old = A[0].replace(A[0][ind0 + 1:], resi1) + '__' + A[1].replace( A[1][ind1 + 1:], resi2) key_new = A[1].replace(A[1][ind1 + 1:], resi2) + '__' + A[0].replace( A[0][ind0 + 1:], resi1) if dic1.has_key(key_old): if not dic3.has_key(key_old): dic3[key_old] = dic2[key] elif dic3.has_key(key_old): dic3[key_old] += dic2[key] elif dic1.has_key(key_new): if not dic3.has_key(key_new): dic3[key_new] = dic2[key] elif dic3.has_key(key_new): dic3[key_new] += dic2[key] elif not dic1.has_key(key_new) and not dic1.has_key(key_old): print('undefined atom pair!', key, key_new, key_old, A, resi1, resi2) return dic3
def makecall(ea=None, target=None): """Output the function call at `ea` and its arguments with the address they originated from. If `target` is specified, then assume that the instruction is calling `target` instead of the target address that the call is referencing. """ ea = current.address() if ea is None else ea if not func.contains(ea, ea): return None if database.config.bits() != 32: raise RuntimeError("{:s}.makecall({!r}, {!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention.".format(__name__, ea, target, database.disasm(ea), database.config.bits())) if target is None: # scan down until we find a call that references something chunk, = ((l, r) for l, r in func.chunks(ea) if l <= ea <= r) result = [] while (len(result) < 1) and ea < chunk[1]: # FIXME: it's probably not good to just scan for a call if not database.instruction(ea).startswith('call '): ea = database.next(ea) continue result = database.cxdown(ea) if len(result) == 0: raise TypeError("{:s}.makecall({!r}, {!r}) : Unable to determine number of arguments.".format(__name__, ea, target)) if len(result) != 1: raise ValueError("{:s}.makecall({!r}, {!r}) : An invalid number of targets was returned for the call at {:#x}. The call targets that were returned are {!r}.".format(__name__, ea, result)) fn, = result else: fn = target try: result = [] for offset, name, size in func.arguments(fn): left = database.address.prevstack(ea, offset+database.config.bits()/8) # FIXME: if left is not an assignment or a push, find last assignment result.append((name, left)) except internal.exceptions.OutOfBoundsError: raise internal.exceptions.OutOfBoundserror("{:s}.makecall({!r}, {!r}) : Unable to get arguments for target function.".format(__name__, ea, target)) # FIXME: replace these crazy list comprehensions with something more comprehensible. # result = ["{:s}={:s}".format(name, instruction.op_repr(ea, 0)) for name, ea in result] result = ["({:#x}){:s}={:s}".format(ea, name, ':'.join(instruction.op_repr(database.address.prevreg(ea, instruction.op_value(ea, 0), write=1), n) for n in instruction.ops_read(database.address.prevreg(ea, instruction.op_value(ea, 0), write=1))) if instruction.op_type(ea, 0) == 'reg' else instruction.op_repr(ea, 0)) for name, ea in result] try: return "{:s}({:s})".format(internal.declaration.demangle(func.name(func.by_address(fn))), ','.join(result)) except: pass return "{:s}({:s})".format(internal.declaration.demangle(database.name(fn)), ','.join(result))
def makecall(ea=None, target=None): """Output the function call at `ea` and its arguments with the address they originated from. If `target` is specified, then assume that the instruction is calling `target` instead of the target address that the call is referencing. """ ea = current.address() if ea is None else ea if not func.contains(ea, ea): return None if database.config.bits() != 32: raise RuntimeError("{:s}.makecall({!r}, {!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention.".format(__name__, ea, target, database.disasm(ea), database.config.bits())) if target is None: # scan down until we find a call that references something chunk, = ((l, r) for l, r in func.chunks(ea) if l <= ea <= r) result = [] while (len(result) < 1) and ea < chunk[1]: # FIXME: it's probably not good to just scan for a call if not database.instruction(ea).startswith('call '): ea = database.next(ea) continue result = database.cxdown(ea) if len(result) == 0: raise TypeError("{:s}.makecall({!r}, {!r}) : Unable to determine number of arguments.".format(__name__, ea, target)) if len(result) != 1: raise ValueError("{:s}.makecall({!r}, {!r}) : An invalid number of targets was returned for the call at {:#x}. The call targets that were returned are {!r}.".format(__name__, ea, result)) fn, = result else: fn = target try: result = [] for offset, name, size in func.arguments(fn): left = database.address.prevstack(ea, offset + database.config.bits() // 8) # FIXME: if left is not an assignment or a push, find last assignment result.append((name, left)) except internal.exceptions.OutOfBoundsError: raise internal.exceptions.OutOfBoundserror("{:s}.makecall({!r}, {!r}) : Unable to get arguments for target function.".format(__name__, ea, target)) # FIXME: replace these crazy list comprehensions with something more comprehensible. # result = ["{:s}={:s}".format(name, instruction.op_repr(ea, 0)) for name, ea in result] result = ["({:#x}){:s}={:s}".format(ea, name, ':'.join(instruction.op_repr(database.address.prevreg(ea, instruction.op_value(ea, 0), write=True), n) for n in instruction.opsi_read(database.address.prevreg(ea, instruction.op_value(ea, 0), write=True))) if instruction.op_type(ea, 0) == 'reg' else instruction.op_repr(ea, 0)) for name, ea in result] try: return "{:s}({:s})".format(internal.declaration.demangle(func.name(func.by_address(fn))), ','.join(result)) except: pass return "{:s}({:s})".format(internal.declaration.demangle(database.name(fn)), ','.join(result))
def dump_breaks(func=None, tagname='break', stdout=True): if func is None: for func, _ in db.selectcontents(tagname): dump_breaks(func, tagname=tagname) return Escape = lambda s: s.replace('"', '\\"') entry, exit = fn.top(func), fn.bottom(func) funcname = fn.name(func) #[(entry,{tagname:'.printf "Entering {:s} %x,%x\\n",poi(@esp),@esp'.format(funcname)})], [(x,{tagname:'.printf "Exiting {:s} %x,%x\\n",poi(@esp),@esp'.format(funcname)}) for x in exit], select = itertools.chain(fn.select(func, And=(tagname, ), Or=('', ))) res = {} for ea, t in select: h = res.setdefault(ea, {}) for k in t.keys(): if k == tagname: h.setdefault(k, []).extend(t[k].split(';')) else: assert k not in h h[k] = t[k] continue output = [] for ea, t in res.iteritems(): ofs = db.offset(ea) commands = [] label = Template('.printf "$label -- $note\\n"' if t. has_key('') else '.printf "$label\\n"') commands.append( label.safe_substitute(label=eaToLabel(ea), note=t.get('', ''))) commands.extend(t.get(tagname, ['g'])) commands = map(windbgescape, commands) breakpoint = 'bp {:s} "{:s}"'.format(eaToReference(ea), Escape(';'.join(commands))) if stdout: print(breakpoint) output.append(breakpoint) if len(output) == 1: return output[0] + '\n' return '\n'.join(output)
for i,ea in enumerate(database.functions()): result = [] for l,r in function.chunks(ea): for x in database.iterate(l,r): address,size,insn = x,idc.ItemSize(x),idc.GetDisasm(x) insn = re.sub(" +", " ", insn) insn = insn.replace("short", "") insn = insn.replace("dword", "") insn = insn.replace("offset", "") insn = insn.replace("large", "") insn = insn.replace("ptr", "") insn = insn.replace("[", "") insn = insn.replace("]", "") if " " in insn: insn = insn.replace(" ", "|", 1) insn = insn.replace(",", "|") insn = insn.replace(" ", "") fn = insn.split("|") name = fn.pop(0) expr = pyml.function(name)(*(pyml.cache.cons(x) for x in fn)) # print len(result),instruction(address,size,expr) result.append(pyml.function("instruction")(address,size,expr)) name = pyml.symbol(function.name(ea)) rules.append(Rule(call(name), List(*result))) print '%x : %d of %d : %s'%(ea, i, max, call(name)) x = List(*rules) z.send(SetDelayed(pyml.symbol('module'), x)) print 'done'
def below(ea, includeSegment=False): '''Return all of the function names and their offset that are called by the function at `ea`.''' tryhard = lambda ea: "{:s}{:+x}".format(func.name(func.top(ea)), ea - func.top(ea)) if func.within(ea) else "{:+x}".format(ea) if func.name(ea) is None else func.name(ea) return '\n'.join(':'.join((segment.name(ea), tryhard(ea)) if includeSegment else (tryhard(ea),)) for ea in func.down(ea))
def makecall(ea=None, target=None): ea = current.address() if ea is None else ea if not function.contains(ea, ea): return None if database.config.bits() != 32: raise RuntimeError( "{:s}.makecall({!r},{!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention." .format(__name__, ea, target, database.disasm(ea), database.config.bits())) if target is None: # scan down until we find a call that references something chunk, = ((l, r) for l, r in function.chunks(ea) if l <= ea <= r) result = [] while (len(result) < 1) and ea < chunk[1]: # FIXME: it's probably not good to just scan for a call if not database.instruction(ea).startswith('call '): ea = database.next(ea) continue result = database.cxdown(ea) if len(result) == 0: raise TypeError( "{:s}.makecall({!r},{!r}) : Unable to determine number of arguments" .format(__name__, ea, target)) if len(result) != 1: raise ValueError( "{:s}.makecall({!r},{!r}) : Too many targets for call at {:x} : {!r}" .format(__name__, ea, result)) fn, = result else: fn = target try: result = [] for offset, name, size in function.arguments(fn): left, _ = function.stack_window( ea, offset + database.config.bits() / 8) # FIXME: if left is not an assignment or a push, find last assignment result.append((name, left)) except LookupError: raise LookupError( "{:s}.makecall({!r},{!r}) : Unable to get arguments for target function" .format(__name__, ea, target)) # FIXME: replace these crazy list comprehensions with something more comprehensible. # result = ["{:s}={:s}".format(name,ins.op_repr(ea, 0)) for name,ea in result] result = [ "({:x}){:s}={:s}".format( ea, name, ':'.join( ins.op_repr( database.address.prevreg(ea, ins.op_value(ea, 0), write=1), n) for n in ins.ops_read( database.address.prevreg(ea, ins.op_value(ea, 0), write=1)) ) if ins.op_type(ea, 0) == 'reg' else ins.op_repr(ea, 0)) for name, ea in result ] try: return "{:s}({:s})".format( internal.declaration.demangle( function.name(function.by_address(fn))), ','.join(result)) except: pass return "{:s}({:s})".format( internal.declaration.demangle(database.name(fn)), ','.join(result))
def label(ea): '''Return a label for the given address `ea`.''' try: res = '{:s}{{+{:x}}}'.format(func.name(ea), db.offset(ea)) except: res = '+{:x}'.format(db.offset(ea)) return '{:s}!{:s}'.format(db.module(), res)
def map(F, **kwargs): """Execute the callback `F` on all functions in the database. Synonymous to `map(F, database.functions())` but with some extra logging to display the current progress. The `F` parameter is defined as a function taking either an `(address, **kwargs)` or a `(index, address, **kwargs)`. Any keyword arguments are passed to `F` unmodified. """ f1 = lambda (idx, ea), **kwargs: F(ea, **kwargs) f2 = lambda (idx, ea), **kwargs: F(idx, ea, **kwargs) f = f1 if F.func_code.co_argcount == 1 else f2 result, all = [], database.functions() total = len(all) if len(all): ea = next(iter(all)) try: for i, ea in enumerate(all): ui.navigation.set(ea) print("{:#x}: processing # {:d} of {:d} : {:s}".format(ea, i+1, total, func.name(ea))) result.append( f((i, ea), **kwargs) ) except KeyboardInterrupt: print("{:#x}: terminated at # {:d} of {:d} : {:s}".format(ea, i+1, total, func.name(ea))) return result
def eaToLabel(ea): try: res = '{:s}{{+{:x}}}'.format(fn.name(ea), db.offset(ea)) except: res = '+{:x}'.format(db.offset(ea)) return '{:s}!{:s}'.format(db.module(), res)
import function import random import urllib.request #modules function.name() for i in range(5): x = random.randrange(1, 1000) print(x)