#!/usr/bin/env python from os import popen from sys import argv dll = argv[1] objdump = "~/xda/wince-cross/usr/local/wince/cross-tools/bin/arm-wince-pe-objdump" section_name = [] section_size = [] section_vma = [] section_offset = [] imagebase = 0 # # is this an executable with headers? # ftype = popen("file %s" % dll).readlines()[0].split(' ')[1].replace("\n","") if ftype != "data": # # parse section headers # for l in popen("%s -h %s | grep ' t '" % (objdump, dll)).readlines(): t = l.split() section_name = section_name + [t[1]] section_size = section_size + [int(t[2],16)] section_vma = section_vma + [int(t[3],16)] section_offset = section_offset + [int(t[5],16)] else: section_name = ["none"] section_size = [256*1024] section_vma = [0] section_offset = [0] # # virtual memory address <--> file offset translation # def vma_to_offset(vma): i=0 while i < len(section_size): if (vma >= section_vma[i]) and (vma < section_vma[i]+section_size[i]): return vma-section_vma[i]+section_offset[i] i=i+1 def offset_to_vma(offset): i=0 while i < len(section_size): if (offset >= section_offset[i]) and (offset < section_offset[i]+section_size[i]): return offset-section_offset[i]+section_vma[i] i=i+1 def vma_in_section(vma): i=0 while i < len(section_size): if (vma >= section_vma[i]) and (vma < section_vma[i]+section_size[i]): return True i=i+1 return False # # parse strings into a dictionary (0xADDR : "string") # strings = {} strlen = {} for l in popen("strings -tx %s" % dll).readlines(): l = l.split(None,1) if len(l) != 2: continue addr = offset_to_vma(int(l[0],16)) text = l[1].replace("\n","") strings[addr] = text strlen[addr] = (len(text)-1)/4+1 # unicode strings for l in popen("strings -tx -el %s" % dll).readlines(): l = l.split(None,1) if len(l) != 2: continue addr = offset_to_vma(int(l[0],16)) text = l[1].replace("\n","") if not strings.has_key(addr): strings[addr] = text strlen[addr] = len(text)/2+1 # # parse function table into a dictionary (0xADDR : "name") # pipe = popen("%s -p %s | grep '^ImageBase\|\s*\[[0-9 ]*\]'" % (objdump, dll)) ll=pipe.readlines() pipe.close() addr = [] ftable = {} if len(ll) > 1: imagebase = int(ll[0].split()[1],16) print "%x" % imagebase i=1 l=ll[i].split() addr={} while len(l) == 7: n=int(l[1][0:-1]) addr[n] = int(l[4],16) i=i+1 l=ll[i].split() while i+1 < len(ll): i=i+1 l=ll[i].split() n=int(l[1][0:-1]) ftable[imagebase+addr[n]] = l[2] # # disassemble # if ftype == "data": pipe = popen("%s -b binary -m arm -D %s" % (objdump, dll)) else: pipe = popen("%s -D %s" % (objdump, dll)) ll=pipe.readlines() pipe.close() datadict = {} referenced = {} jumped_to = {} print "Finding references..." i = 0 while i+1 < len(ll): i=i+1 l=ll[i] if (l == '\t...') or (l == '\n'): continue t = l.split('\t') if (len(t[0]) == 0) or (t[0][-1] != ':') or (len(t) < 3): continue addr = int(t[0][0:-1].strip(),16) data = int(t[1],16) datadict[addr] = data # only evaluate references inst = t[2][0:3] if (inst == "ldr") or (inst == "str"): if t[len(t)-1][0:4] == '; 0x': ref = int(t[len(t)-1][4:],16) if vma_in_section(ref): referenced[ref] = 0 if (inst[0:2] == 'bl'): if (len(inst) == 2) or (inst[2] != 's'): target = int(t[3][2:],16) if vma_in_section(target): if target in jumped_to.keys(): jumped_to[target].append("0x%08x" % addr) else: jumped_to[target] = ["0x%08x" % addr] print "Resolving references..." for ref in referenced.keys(): if datadict.has_key(ref): referenced[ref] = datadict[ref] if datadict.has_key(referenced[ref]): referenced[referenced[ref]] = datadict[referenced[ref]] else: referenced[ref] = 0 print "Generating disassembled output..." i = 0 while i+1 < len(ll): i=i+1 l=ll[i].strip('\n') if (l == '\t...') or (l == '\n'): print l continue t = l.split('\t') if (len(t[0]) == 0) or (t[0][-1] != ':') or (len(t) < 3): print l continue addr = int(t[0][0:-1].strip(),16) data = int(t[1],16) inst = t[2] if referenced.has_key(addr): if strings.has_key(addr): print "%8x:\t\"%s\"" % (addr, strings[addr]) if(strlen[addr]>1): i=i+strlen[addr]-1 elif strings.has_key(data-0x90030000): print "%8x:\t%08x \"%s\"" % (addr, data, strings[data-0x90030000]) else: if referenced.has_key(data): if datadict.has_key(referenced[data]): if strings.has_key(referenced[data]): print "%8x:\t%08x --> \"%s\"" % (addr, data, strings[referenced[data]]) elif strings.has_key(referenced[data]-0x90030000): print "%8x:\t%08x --> \"%s\"" % (addr, data, strings[referenced[data]]) else: print "%8x:\t%08x --> %08x" % (addr, data, datadict[referenced[data]]) else: print "%8x:\t%08x --> ? (at %08x)" % (addr, data, referenced[data]) else: print "%s\t; (referenced somewhere)" % l elif strings.has_key(addr): print "%8x:\t\"%s\" (no direct reference)" % (addr, strings[addr]) if(strlen[addr]>1): i=i+strlen[addr]-1 elif t[len(t)-1][0:4] == '; 0x': ref = int(t[len(t)-1][4:],16) if referenced.has_key(ref): if datadict.has_key(referenced[ref]): if strings.has_key(referenced[ref]): print "%s = 0x%08x --> \"%s\"" % (l, referenced[ref], strings[referenced[ref]]) else: print "%s = 0x%08x --> %08x" % (l, referenced[ref], datadict[referenced[ref]]) else: if strings.has_key(referenced[ref]-0x90030000): print "%s --> 0x%08x\"%s\"" % (l, referenced[ref], strings[referenced[ref]-0x90030000]) else: print "%s --> 0x%08x" % (l, referenced[ref]) else: print l elif addr in ftable.keys(): print "\n/*\n * %s\n */\n%s\n" % (ftable[addr], l), if addr in jumped_to.keys(): print "\n/*\n *", print jumped_to[addr], print "\n */\n%s" % l elif addr in jumped_to.keys(): print "\n/*\n *", print jumped_to[addr], print "\n */\n%s" % l else: print l continue