def getDynamicLoaderInfo(filePath, outputPath): logger = utils.setLogger() desc = utils.getCommandInfos(filePath, "LC_DYLD_INFO") if desc is None: desc = utils.getCommandInfos(filePath, "LC_DYLD_INFO_ONLY") rebase_off = desc.get("rebase_off") rebase_size = desc.get("rebase_size") if rebase_off is not None and rebase_size is not None: utils.getPartOfFile(filePath, rebase_off, rebase_size) opcodes = DyldInfo.createRebaseNode(filePath, "temp", rebase_off) opcodes = collections.OrderedDict(sorted(opcodes.items())) desc["Rebase Info(opcodes)"] = opcodes bind_off = desc.get("bind_off") bind_size = desc.get("bind_size") if bind_off is not None and bind_size is not None: utils.getPartOfFile(filePath, bind_off, bind_size) opcodes = DyldInfo.createBindingNode(filePath, "temp", bind_off) opcodes = collections.OrderedDict(sorted(opcodes.items())) desc["Binding Info(opcodes)"] = opcodes weak_bind_off = desc.get("weak_bind_off") weak_bind_size = desc.get("weak_bind_size") if weak_bind_off is not None and weak_bind_size is not None: utils.getPartOfFile(filePath, weak_bind_off, weak_bind_size) opcodes = DyldInfo.createBindingNode(filePath, "temp", weak_bind_off) opcodes = collections.OrderedDict(sorted(opcodes.items())) desc["Weak Binding Info(opcodes)"] = opcodes lazy_bind_off = desc.get("lazy_bind_off") lazy_bind_size = desc.get("lazy_bind_size") if lazy_bind_off is not None and lazy_bind_size is not None: utils.getPartOfFile(filePath, lazy_bind_off, lazy_bind_size) opcodes = DyldInfo.createBindingNode(filePath, "temp", lazy_bind_off) opcodes = collections.OrderedDict(sorted(opcodes.items())) desc["Lazy Binding Info(opcodes)"] = opcodes export_off = desc.get("export_off") export_size = desc.get("export_size") if export_off is not None and export_size is not None: utils.getPartOfFile(filePath, export_off, export_size) opcodes = DyldInfo.printSymbols(filePath, "temp", export_off) opcodes = collections.OrderedDict(sorted(opcodes.items())) desc["Export Info(opcodes)"] = opcodes if os.path.exists("temp"): os.remove("temp") outFinal = json.dumps(desc, encoding='latin1') with open(outputPath + "/" + "dynamicLoaderInfo", "w") as f: f.write(outFinal) logger.info("It has got all infos of dynamic loader info sucessfully")
def getSymbolsList(sample, strs): endian = utils.getEndianFormat(sample) count = 0 symbols = {} symbolsList = [] step = 0 desc = utils.getCommandInfos(sample, "LC_SYMTAB") baseStrAddr = desc.get("stroff") symAddress = desc.get("symoff") nsym = desc.get("nsyms") if utils.is64Bit(sample): step = 16 utils.getPartOfFile(sample, symAddress, nsym * 16) else: step = 12 utils.getPartOfFile(sample, symAddress, nsym * 12) os.rename("temp", "tmp") offset = 0 while count < nsym: count += 1 byte, data = ReadWrite.readInt32("tmp", endian, offset) offset += step value = strs.get(hex(baseStrAddr + data).rstrip("L")) if value is None: value = "" symbolsList.append(value) os.remove("tmp") return symbolsList
def getSymbolTables(filePath, outputPath): logger = utils.setLogger() strs = utils.getSymbolStrs(filePath) desc = utils.getCommandInfos(filePath, "LC_SYMTAB") strAddress = desc.get("stroff") symAddress = desc.get("symoff") if utils.is64Bit(filePath): utils.getPartOfFile(filePath, desc.get("symoff"), desc.get("nsyms") * 16) os.rename("temp", "tmp") symbolStrs = SymbolContents.createSymbols64Node( filePath, strs, "tmp", symAddress, strAddress, desc.get("nsyms")) else: utils.getPartOfFile(filePath, desc.get("symoff"), desc.get("nsyms") * 12) os.rename("temp", "tmp") symbolStrs = SymbolContents.createSymbolsNode(filePath, strs, "tmp", symAddress, strAddress, desc.get("nsyms")) desc["symbols"] = symbolStrs os.remove("tmp") outFinal = json.dumps(desc, encoding='latin1') with open(outputPath + "/" + "symbolTables", "w") as f: f.write(outFinal) logger.info("It has got all infos of symbol tables sucessfully")
def getISymbols(sample): endian = utils.getEndianFormat(sample) symbols = utils.getSymbolStrs(sample) symbolsList = getSymbolsList(sample, symbols) sections = utils.getSections(sample) is64 = utils.is64Bit(sample) count = 0 inSymbols = {} offset = 0 desc = utils.getCommandInfos(sample, "LC_DYSYMTAB") inSymAddress = desc.get("indirectsymoff") nSymbol = desc.get("nindirectsyms") utils.getPartOfFile(sample, inSymAddress, nSymbol * 4) os.rename("temp", "tmp") while count < nSymbol: nsect = len(sections) while nsect > 0: nsect -= 1 section = sections[nsect] flag = section.flags # print(section.reserved1) if (flag & SECTION_TYPE != S_SYMBOL_STUBS \ and flag & SECTION_TYPE != S_LAZY_SYMBOL_POINTERS \ and flag & SECTION_TYPE != S_LAZY_DYLIB_SYMBOL_POINTERS \ and flag & SECTION_TYPE != S_NON_LAZY_SYMBOL_POINTERS) \ or section.reserved1 > count: #section type or indirect symbol index mismatch continue nsect = 0 #calculate stub or pointer length if section.reserved2 > 0: length = section.reserved2 else: if is64: length = 8 else: length = 4 #calculate indirect value location indirectOffset = section.offset + (count - section.reserved1) * length #read indirect symbol index byte, indirectIndex = ReadWrite.readInt32("tmp", endian, offset) offset += byte if indirectIndex & (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS) == 0: if indirectIndex >= len(symbolsList): raise Exception("index is out of range " + str(indirectIndex)) symbolName = utils.getSymbolByIndex(symbolsList, indirectIndex) inSymbols[hex(indirectOffset).rstrip("L")] = symbolName count += 1 os.remove("tmp") return inSymbols
def createTextNode(sample, section, outputPath): #prepare disassembler params header = utils.getHeader(sample) strs = utils.getSymbolStrs(sample) inSymbols = SymbolContents.getISymbols(sample) names = SymbolContents.getFunctionNames(sample, strs) #open capstone target_arch = 0 target_mode = 0 if header.header.cputype == CPU_TYPE_ARM: target_arch = CS_ARCH_ARM target_mode = CS_MODE_ARM elif header.header.cputype == CPU_TYPE_ARM64: target_arch = CS_ARCH_ARM64 target_mode = CS_MODE_ARM else: print("NO CPU FOUND!") md = Cs(target_arch, target_mode) md.skipdata = True md.detail = True #set or not thumb mode for 32 bits ARM targets if header.header.cputype == CPU_TYPE_ARM: if header.header.cpusubtype == CPU_SUBTYPE_ARM_V7 \ or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7F \ or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7S \ or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7K \ or header.header.cpusubtype == CPU_SUBTYPE_ARM_V8 : md.mode = CS_MODE_THUMB else: md.mode = CS_MODE_ARM code = Codes(md) utils.getPartOfFile(sample, section.offset, section.size) os.rename("temp", "codes") if section.sectname.rstrip('\x00') == "__text": desc = utils.getCommandInfos(sample, "LC_FUNCTION_STARTS") utils.getPartOfFile(sample, desc.get("dataoff"), desc.get("datasize")) if utils.is64Bit(sample): getFunctions(code, inSymbols, names, "temp", section.offset, outputPath) else: getFunctions(code, inSymbols, names, "temp", section.offset, outputPath) os.remove("temp") else: fcode = open("codes", "rb") CODE = fcode.read() code.disAssembly(md, inSymbols, CODE, section.offset, outputPath) fcode.close() os.remove("codes")
def getDynamicSymbolTables(filePath, outputPath): logger = utils.setLogger() strs = utils.getSymbolStrs(filePath) symbolsList = SymbolContents.getSymbolsList(filePath, strs) desc = utils.getCommandInfos(filePath, "LC_DYSYMTAB") inSymAddress = desc.get("indirectsymoff") nSymbol = desc.get("nindirectsyms") utils.getPartOfFile(filePath, inSymAddress, nSymbol * 4) os.rename("temp", "tmp") desc["inSymbols"] = SymbolContents.createISymbolsNode( filePath, symbolsList, "tmp", inSymAddress, nSymbol) os.remove("tmp") outFinal = json.dumps(desc, encoding='latin1') with open(outputPath + "/" + "dynamicSymbolTables", "w") as f: f.write(outFinal) logger.info("It has get all infos of dynamic symbol tables sucessfully")
def getFunctionNames(sample, strs): endian = utils.getEndianFormat(sample) sectionInfos = utils.getSectionInfoMaps(sample) desc = utils.getCommandInfos(sample, "LC_SYMTAB") baseStrAddr = desc.get("stroff") symAddress = desc.get("symoff") nsym = desc.get("nsyms") if utils.is64Bit(sample): step = 16 utils.getPartOfFile(sample, symAddress, nsym * 16) else: step = 12 utils.getPartOfFile(sample, symAddress, nsym * 12) os.rename("temp", "tmp") count = 0 names = {} offset = 0 is64 = utils.is64Bit(sample) while count < nsym: count += 1 byte, data = ReadWrite.readInt32("tmp", endian, offset) offset += 8 value = strs.get(hex(baseStrAddr + data).rstrip("L")) if value is None: continue if is64: byte, n_value = ReadWrite.readInt64("tmp", endian, offset) else: byte, n_value = ReadWrite.readInt32("tmp", endian, offset) offset += byte key = utils.addressToFileOffset(sample, sectionInfos, n_value) names[hex(key)] = value os.remove("tmp") return names
def getClassSymbols(sample): endian = utils.getEndianFormat(sample) strs = utils.getSymbolStrs(sample) desc = utils.getCommandInfos(sample, "LC_SYMTAB") baseStrAddr = desc.get("stroff") symAddress = desc.get("symoff") nsym = desc.get("nsyms") is64 = utils.is64Bit(sample) if is64: utils.getPartOfFile(sample, symAddress, nsym * 16) else: utils.getPartOfFile(sample, symAddress, nsym * 12) count = 0 classSymbols = {} offset = 0 while count < nsym: count += 1 byte, data = ReadWrite.readInt32("temp", endian, offset) offset += byte description = "String Table Index" value = strs.get(hex(baseStrAddr + data).rstrip("L")) if value is None: value = "" offset += 4 if is64: byte, n_value = ReadWrite.readInt64("temp", endian, offset) else: byte, n_value = ReadWrite.readInt32("temp", endian, offset) offset += byte classSymbols[hex(n_value).rstrip("L")] = value classSymbols = collections.OrderedDict(sorted(classSymbols.items())) return classSymbols