def licensestring(lic): """ decode a license blob """ if not lic: return if len(lic) != 127: print("unknown license format: %s" % hexdump(lic)) return if struct.unpack_from("<L", lic, 106)[0]: print("unknown license format: %s" % hexdump(lic)) return # note: first 2 bytes probably a checksum licver, = struct.unpack_from("<H", lic, 2) if licver == 0: # todo: new 'Evaluation version' has licver == 0 as well, but is new format anyway # up to ida v5.2 time, = struct.unpack_from("<L", lic, 4) # then 8 zero bytes licflags, = struct.unpack_from("<L", lic, 16) licensee = strz(lic, 20) return "%s [%08x] %s" % (timestring(time), licflags, licensee) else: # since ida v5.3 # licflags from 8 .. 16 time1, = struct.unpack_from("<L", lic, 16) time2, = struct.unpack_from("<L", lic, 16 + 8) licid = "%02X-%02X%02X-%02X%02X-%02X" % struct.unpack_from( "6B", lic, 28) licensee = strz(lic, 34) return "v%04d %s .. %s %s %s" % (licver, timestring(time1), timestring(time2), licid, licensee)
def processidb(args, idb): if args.verbose > 1: print("magic=%s, filever=%d" % (idb.magic, idb.fileversion)) for i in range(6): comp, ofs, size, checksum = idb.getsectioninfo(i) if ofs: part = idb.getpart(i) print("%2d: %02x, %08x %8x [%08x]: %s" % (i, comp, ofs, size, checksum, hexdump(part.read(256)))) nam = idb.getsection(idblib.NAMFile) id0 = idb.getsection(idblib.ID0File) processid0(args, id0) processid1(args, idb.getsection(idblib.ID1File)) processid2(args, idb.getsection(idblib.ID2File)) processnam(args, nam) processtil(args, idb.getsection(idblib.TILFile)) processseg(args, idb.getsection(idblib.SEGFile)) if args.names: dumpnames(args, id0, nam) if args.scripts: dumplist(id0, '$ scriptsnippets', dumpscript) if args.structs: dumplist(id0, '$ structs', dumpstruct) if args.enums: dumplist(id0, '$ enums', dumpenum) if args.imports: dumplist(id0, '$ imports', dumpimport)
def dumpstructmember(id0, spec): def i64(a, b): return a + (b << 32) if id0.wordsize == 8: f = i64(spec[0], spec[1]), i64(spec[2], spec[3]), i64(spec[4], spec[5]), spec[6], spec[7] else: f = spec print(" %02x %02x %08x %02x: " % tuple(f[1:]), end="") nodeid = f[0] + id0.nodebase name = id0.name(nodeid) enumid = id0.int(nodeid, 'A', 11) struct = id0.int(nodeid, 'A', 3) # TODO 'A', 16 - stringtype # TODO 'S', 0 - member comment # TODO 'S', 1 - repeatable member comment ptrseg = hexdump(id0.bytes(nodeid, 'S', 9)) eltype = hexdump(id0.bytes(nodeid, 'S', 0x3000)) print("%-40s" % name, end="") if enumid: print(" enum %08x" % enumid, end="") if struct: print(" struct %08x" % struct, end="") if ptrseg: # packed # note: 64bit nrs are stored low32, high32 # flags1, target, base, delta, flags2 # flags1: # 0=off8 1=off16 2=off32 3=low8 4=low16 5=high8 6=high16 9=off64 # 0x10 = targetaddr, 0x20 = baseaddr, 0x40 = delta, 0x80 = base is plainnum # flags2: # 1=image is off, 0x10 = subtract, 0x20 = signed operand print(" ptr %s" % ptrseg, end="") if eltype: print(" type %s" % eltype, end="") print()
def dumpinfo(id0): """ print various infos on the idb file """ def ftstring(ft): if 0 < ft < len(filetypelist): return "%02x:%s" % (ft, filetypelist[ft]) return "%02x:unknown" % ft def decodebitmask(fl, bitnames): l = [] knownbits = 0 for bit, name in enumerate(bitnames): if fl & (1 << bit) and name is not None: l.append(name) knownbits |= 1 << bit if fl & ~knownbits: l.append("unknown_%x" % (fl & ~knownbits)) return ",".join(l) def osstring(fl): return decodebitmask(fl, ['msdos', 'win', 'os2', 'netw', 'unix', 'other']) def appstring(fl): return decodebitmask(fl, [ 'console', 'graphics', 'exe', 'dll', 'driver', '1thread', 'mthread', '16bit', '32bit', '64bit' ]) ldr = id0.nodeByName("$ loader name") if ldr: print("loader: %s %s" % (id0.string(ldr, 'S', 0), id0.string(ldr, 'S', 1))) if not id0.root: print("database has no RootNode") return if id0.idbparams: params = idblib.IDBParams(id0, id0.idbparams) print( "cpu: %s, version=%d, filetype=%s, ostype=%s, apptype=%s, core:%x, size:%x" % (params.cpu, params.version, ftstring(params.filetype), osstring(params.ostype), appstring( params.apptype), params.corestart, params.coresize)) print("idaver=%s: %s" % (nonefmt("%04d", id0.idaver), id0.idaverstr)) srcmd5 = id0.originmd5 print("nopens=%s, ctime=%s, crc=%s, md5=%s" % (nonefmt("%d", id0.nropens), nonefmt("%08x", id0.creationtime), nonefmt("%08x", id0.somecrc), hexdump(srcmd5) if srcmd5 else "-")) dumpuser(id0)
def processfile(args, filetypehint, fh): class DummyIDB: def __init__(idb, args): if args.i64: idb.magic = 'IDA2' elif args.i32: idb.magic = 'IDA1' else: idb.magic = None try: magic = fh.read(64) fh.seek(-64, 1) if magic.startswith(b"Va") or magic.startswith(b"VA"): idb = DummyIDB(args) if filetypehint == 'id1': processid1(args, idblib.ID1File(idb, fh)) elif filetypehint == 'nam': processnam(args, idblib.NAMFile(idb, fh)) elif filetypehint == 'seg': processseg(args, idblib.SEGFile(idb, fh)) else: print("unknown VA type file: %s" % hexdump(magic)) elif magic.startswith(b"IDAS"): processid2(args, idblib.ID2File(DummyIDB(args), fh)) elif magic.startswith(b"IDATIL"): processtil(args, idblib.ID2File(DummyIDB(args), fh)) elif magic.startswith(b"IDA"): processidb(args, idblib.IDBFile(fh)) elif magic.find(b'B-tree v') > 0: processid0(args, idblib.ID0File(DummyIDB(args), fh)) except Exception as e: print("ERROR %s" % e) if args.debug: raise
def printent(args, id0, c): if args.verbose: print("%s = %s" % (id0.prettykey(c.getkey()), id0.prettyval(c.getval()))) else: print("%s = %s" % (hexdump(c.getkey()), hexdump(c.getval())))
def dumpinfo(id0): """ print various infos on the idb file """ def nonefmt(fmt, num): if num is None: return "-" return fmt % num def ftstring(ft): if 0 < ft < len(filetypelist): return "%02x:%s" % (ft, filetypelist[ft]) return "%02x:unknown" % ft def decodebitmask(fl, bitnames): l = [] knownbits = 0 for bit, name in enumerate(bitnames): if fl & (1 << bit) and name is not None: l.append(name) knownbits |= 1 << bit if fl & ~knownbits: l.append("unknown_%x" % (fl & ~knownbits)) return ",".join(l) def osstring(fl): return decodebitmask(fl, ['msdos', 'win', 'os2', 'netw', 'unix', 'other']) def appstring(fl): return decodebitmask(fl, [ 'console', 'graphics', 'exe', 'dll', 'driver', '1thread', 'mthread', '16bit', '32bit', '64bit' ]) ldr = id0.nodeByName("$ loader name") if ldr: print("loader: %s %s" % (id0.string(ldr, 'S', 0), id0.string(ldr, 'S', 1))) root = id0.nodeByName("Root Node") if not root: print("database has no RootNode") return params = id0.bytes(root, 'S', 0x41b994) if params: magic, version, cpu, idpflags, demnames, filetype, coresize, corestart, ostype, apptype = struct.unpack_from( "<3sH8sBBH" + (id0.fmt * 2) + "HH", params, 0) cpu = strz(cpu, 0) print( "cpu: %s, version=%d, filetype=%s, ostype=%s, apptype=%s, core:%x, size:%x" % (cpu, version, ftstring(filetype), osstring(ostype), appstring(apptype), corestart, coresize)) idaver = id0.int(root, 'A', -1) # note: versions before 4.7 used a short instead of a long # and stored the versions with one minor digit ( 43 ) , instead of two ( 480 ) idaver2 = id0.string(root, 'S', 1303) print("idaver=%s: %s" % (nonefmt("%04d", idaver), idaver2)) nopens = id0.int(root, 'A', -4) ctime = id0.int(root, 'A', -2) crc = id0.int(root, 'A', -5) srcmd5 = id0.bytes(root, 'S', 1302) print("nopens=%s, ctime=%s, crc=%s, md5=%s" % (nonefmt("%d", nopens), nonefmt("%08x", ctime), nonefmt( "%08x", crc), hexdump(srcmd5) if srcmd5 else "-")) dumpuser(id0)