def xref_global(node, ctx): var = ctx.get_obj("written") print("%x at %x" % (var.addr, node.ea)) # Terrible check to see if we're in a function if idc.get_func_flags(var.addr) == -1: ida_xref.add_dref(node.ea, var.addr, ida_xref.XREF_USER) return False
def main(): global cfgTree cfgTree = CFGTree() seg = idaapi.get_segm_by_name("__text") # Loop from segment start to end func_ea = seg.startEA # Get a function at the start of the segment (if any) func = idaapi.get_func(func_ea) if func is None: # No function there, try to get the next one func = idaapi.get_next_func(func_ea) seg_start = seg.startEA seg_end = seg.end_ea while func is not None and func.start_ea < seg_end: funcea = func.start_ea fflags = idc.get_func_flags(funcea) if (fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK): continue # print("Function %s at 0x%x" % (idc.get_func_name(funcea), funcea)) flow = idaapi.FlowChart(idaapi.get_func(funcea), flags=idaapi.FC_PREDS) construct_cfg(flow, funcea, seg_start, seg_end) func = idaapi.get_next_func(funcea) cfgTree.print_deepest_path()
def find_dispatch_by_cfg(): """ Finds the functions in the binary which are not directly called anywhere and counts how many other functions they call, returing all functions which call > 0 other functions but are not called themselves. As a dispatch function is not normally directly called but will normally many other functions this is a fairly good way to guess which function it is. """ out = [] called = set() caller = dict() # Loop through all the functions in the binary for function_ea in idautils.Functions(): flags = idc.get_func_flags(function_ea) # skip library functions if flags & idc.FUNC_LIB: continue f_name = idc.get_func_name(function_ea) # For each of the incoming references for ref_ea in idautils.CodeRefsTo(function_ea, 0): called.add(f_name) # Get the name of the referring function caller_name = idc.get_func_name(ref_ea) if caller_name not in caller.keys(): caller[caller_name] = 1 else: caller[caller_name] += 1 while True: if len(caller.keys()) == 0: break potential = max(caller, key=caller.get) if potential not in called: out.append(potential) del caller[potential] return out
def ext_instruction(file_name, addr_start, addr_end): name_fun = GetFunctionName(addr_start) row = '' for addr in Heads(addr_start, addr_end): ins = '' thisOperand = idc.GetMnem(addr) oPtype1 = idc.GetOpType(addr, 0) oPtype2 = idc.GetOpType(addr, 1) # assemblydata = parametertype(oPtype1)+' '+parametertype(oPtype2) if (oPtype1 == 1 or oPtype1 == 4): oPtype1 = idc.GetOpnd(addr, 0) if (oPtype2 == 1 or oPtype2 == 4): oPtype2 = idc.GetOpnd(addr, 1) if thisOperand == "call": call_fun_name = GetOpnd(addr, 0) keyInstr = LocByName(call_fun_name) fflags = idc.get_func_flags(keyInstr) if (fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK): ins = thisOperand + '_' + idc.GetOpnd(addr, 0) + '_0' row = row + ' ' + ins continue ins = str(thisOperand)+'_'+tran(str(oPtype1)) + \ '_'+tran(str(oPtype2)) row = row + ' ' + ins return row
def getXRefsTo(self): """ Computes a list of the names of the xrefs to the function. This includes all functions that call this, but also data xrefs. :returns: a tuple of two lists: crefs and drefs """ # type: () -> (list[int], list[int]) crefs = [] drefs = [] # If the current address is function process it if idc.get_func_flags(self.func_ea) != -1: # Find all code references to func ref = idc.get_first_cref_to(self.func_ea) while ref != idaapi.BADADDR: # name = get_func_name(ref) # if not name: name = "ROM:%08X" % ref crefs.append(ref) ref = idaapi.get_next_cref_to(self.func_ea, ref) # Find all data references to func for ref in idautils.DataRefsTo(self.func_ea): drefs.append(ref) for ref in idautils.DataRefsTo(self.func_ea + 1): drefs.append(ref) return crefs, drefs
def analysis(): for ea in idautils.Functions(): flags = idc.get_func_flags(ea) # 筛选 THUNK (跳转) or 典型库函数 if flags & idc.FUNC_LIB or flags & idc.FUNC_THUNK: continue features['EA'].append(f"{ea:X}")
def query_all_callback(self, threshold=0.8, minsize=3): for ea in idautils.Functions(): pfn = idaapi.get_func(ea) func_name = idaapi.get_func_name(ea) if idaapi.FlowChart(pfn).size < minsize: print( "[BinaryAI] {} is skipped because basicblock size lower than minsize({})" .format(func_name, minsize)) continue funcs = self.query_function(ea) if funcs is None: print( "[BinaryAI] {} is skipped because get function feature error" .format(func_name, threshold)) continue func = funcs[0] if func['score'] < threshold: print( "[BinaryAI] {} is skipped because top1_score lower than threshold({})" .format(func_name, threshold)) continue idc.set_color(ea, idc.CIC_FUNC, 0xFFFFE1) idc.set_func_flags(ea, idc.get_func_flags(ea) | 0x10000) comment = SourceCodeViewer.source_code_comment(func_name, func) idaapi.set_func_cmt(pfn, comment, 0)
def __init__(self, func_ea): """ :raises: InvalidFunctionException if func_ea does not live within a function, or the function is not defined. :param func_ea: long: Effective Address of function to manipulate """ # If the current address is a function, process it if idc.get_func_flags(func_ea) != -1: self.func = idaapi.get_func(func_ea) self.func_ea = self.func.startEA if self.func.tails: raise (FunctionException( "%07X: Function Chunks are not supported" % func_ea)) else: raise (FunctionException( "Address %08x does not live within a function" % func_ea))
def find_dispatch_by_struct_index(): """Attempts to locate the dispatch function based off it being loaded in a structure at offset 70h, based off of https://github.com/kbandla/ImmunityDebugger/blob/master/1.73/Libs/driverlib.py """ out = set() for function_ea in idautils.Functions(): flags = idc.get_func_flags(function_ea) # skip library functions if flags & idc.FUNC_LIB: continue func = idaapi.get_func(function_ea) addr = func.start_ea while addr < func.end_ea: if idc.print_insn_mnem(addr) == 'mov': if '+70h' in idc.print_operand(addr, 0) and idc.get_operand_type(addr, 1) == 5: out.add(idc.print_operand(addr, 1)) addr = idc.next_head(addr) return out
def __init__(self, func_ea): """ :raises: InvalidFunctionException if func_ea does not live within a function, or the function is not defined. :param func_ea: long: Effective Address of function to manipulate """ # If the current address is a function process it if idc.get_func_flags(func_ea) != -1: self.func = idaapi.get_func(func_ea) self.func_ea = self.func.startEA # TODO: these shouldn't be unsupported. detect each chunk as its own function? fix func_ea # function chunks can give invalid behavior when definind functions! if self.func.tails: raise (FunctionException( "%07X: Function Chunks are not supported" % func_ea)) else: raise (FunctionException( "Address %08x does not live within a function" % func_ea))
def disassemble_func(address): func_dis = {} symbolic_calls = {} inst_num = 0 flags = idc.get_func_flags(address) last_addr = address asm = '' cnt = 0 for addr in FuncItems(address): cnt += 1 ins = idautils.DecodeInstruction(addr) # print('decoded') byte_instr = idc.get_bytes(addr, ins.size) asm = asm + str(binascii.hexlify(byte_instr)) inst_num = inst_num + 1 last_addr = addr if idc.print_insn_mnem(addr) in ["call"]: # print('Call:'+str(ins)) call_address = idc.get_operand_value(addr, 0) # print(call_address) start_addr = idc.first_func_chunk(call_address) symbolic_calls[start_addr] = idc.get_func_name(call_address) func_dis['bytecode'] = asm func_dis['symbolic_calls'] = symbolic_calls func_dis['start_address'] = idc.first_func_chunk(address) func_dis['end_address'] = last_addr func_dis['segment_address'] = idc.get_segm_start(address) func_dis['segment_name'] = idc.SegName(address) func_dis['name'] = idc.get_func_name(address) func_dis['inst_numbers'] = inst_num # attenzione sta cosa ci da la roba riconosciuta con flirt. func_dis['library_flag'] = flags & idc.FUNC_LIB print("Function contains {} instructions".format(cnt)) return func_dis
offset = -stack_size + var.get_stkoff() hexrays_types[idc.get_func_name(ea)][offset] = var.width, ownertype # print(dir(var)) # get global variables get_data_symbols() for ea in idautils.Functions(): if not str(idc.get_func_name(ea)) in functions: continue # print(dir(va)) # print(ida_hexrays.decompile(ea).arguments) # check if library function if not idc.get_segm_name(ea) == ".text": continue if idc.get_func_flags(ea) & FUNC_LIB: continue if decompiler: get_hexrays_vars(ea, idc.get_func_attr(ea, idc.FUNCATTR_FRSIZE)) # function name fun_name = idc.get_func_name(ea) # print(dir(idc)) # function stack size and boundaries stack_size = idc.get_func_attr(ea, idc.FUNCATTR_FRSIZE) fun_entry = format(idc.get_func_attr(ea, FUNCATTR_START), 'x') fun_exit = format(idc.get_func_attr(ea, FUNCATTR_END), 'x') # instructions instructions = {item:Instruction(item, ea) for item in idautils.FuncItems(ea)} # check if rbp or rsp relative addressing adjust_off = 0
def xex_load_imports(li): global directory_entry_headers li.seek(directory_entry_headers[XEX_HEADER_IMPORTS]) import_desc = read_struct(li, XEXImportDescriptor) # seperate the library names in the name table import_libnames = [] cur_lib = "" for i in range(0, import_desc.NameTableSize): name_char = li.read(1) if name_char == '\0' or name_char == '\xCD': if cur_lib != "": import_libnames.append(cur_lib) cur_lib = "" else: cur_lib += name_char # read each import library table for i in range(0, import_desc.ModuleCount): table_addr = li.tell() table_header = read_struct(li, XEXImportTable) libname = import_libnames[table_header.ModuleIndex] variables = {} for i in range(0, table_header.ImportCount): record_addr = read_dwordBE(li) record_value = ida_bytes.get_dword(record_addr) record_type = (record_value & 0xFF000000) >> 24 ordinal = record_value & 0xFFFF import_name = x360_imports.DoNameGen(libname, 0, ordinal) if record_type == 0: # variable idc.create_data(record_addr, idc.FF_WORD, 2, idc.BADADDR) idc.create_data(record_addr + 2, idc.FF_WORD, 2, idc.BADADDR) idc.make_array(record_addr, 2) idc.set_name(record_addr, "__imp__" + import_name) variables[ordinal] = record_addr elif record_type == 1: # thunk # have to rewrite code to set r3 & r4 like xorlosers loader does # r3 = module index afaik # r4 = ordinal # important to note that basefiles extracted via xextool have this rewrite done already, but raw basefile from XEX doesn't! # todo: find out how to add to imports window like xorloser loader... ida_bytes.put_dword(record_addr + 0, 0x38600000 | table_header.ModuleIndex) ida_bytes.put_dword(record_addr + 4, 0x38800000 | ordinal) idc.add_func(record_addr, record_addr + 0x10) idc.set_name(record_addr, import_name) # add comment to thunk like xorloser's loader idc.set_cmt( record_addr + 4, "%s :: %s" % (libname.rsplit('.', 1)[0], import_name), 1) # this should mark the func as a library function, but it doesn't do anything for some reason # tried a bunch of things like idaapi.autoWait() before running it, just crashes IDA with internal errors... idc.set_func_flags( record_addr, idc.get_func_flags(record_addr) | idc.FUNC_LIB) # thunk means it's not a variable, so remove from variables dict if ordinal in variables: variables.pop(ordinal) else: print( "[+] %s import %d (%s) (@ 0x%X) unknown type %d!" % (libname, ordinal, import_name, record_addr, record_type)) # remove "__imp__" part from variable import names for ordinal in variables: import_name = x360_imports.DoNameGen(libname, 0, ordinal) idc.set_name(variables[ordinal], import_name) # Seek to end of this import table li.seek(table_addr + table_header.TableSize) return
def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if list( map(lambda x: x if type(x) == int else ord(x), idc.get_bytes(ea, len( const["byte_array"])))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"], ida_name.SN_FORCE) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == idc.SEG_CODE: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] searching for crypto constants in immediate operand") funcs = idautils.Functions() for f in funcs: flags = idc.get_func_flags(f) if (not flags & (idc.FUNC_LIB | idc.FUNC_THUNK)): ea = f f_end = idc.get_func_attr(f, idc.FUNCATTR_END) while (ea < f_end): imm_operands = [] insn = ida_ua.insn_t() ida_ua.decode_insn(insn, ea) for i in range(len(insn.ops)): if insn.ops[i].type == ida_ua.o_void: break if insn.ops[i].type == ida_ua.o_imm: imm_operands.append(insn.ops[i].value) if len(imm_operands) == 0: ea = idc.find_code(ea, idc.SEARCH_DOWN) continue for const in operand_consts: if const["value"] in imm_operands: print(("0x%0" + str(digits) + "X: found immediate operand constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(ea, 0) if cmt: idc.set_cmt(ea, cmt + ' ' + const["name"], 0) else: idc.set_cmt(ea, const["name"], 0) break ea = idc.find_code(ea, idc.SEARCH_DOWN) print("[*] finished")
def isFunction(ea): return idc.get_func_flags(ea) != -1
def print_deepest_path(self): # CS_OP_INVALID = 0, ///< uninitialized/invalid operand. # CS_OP_REG, 1 ///< Register operand. # CS_OP_IMM, 2 ///< Immediate operand. # CS_OP_MEM, 3 ///< Memory operand. def ext_instruction(file_name, addr_start, addr_end): name_fun = GetFunctionName(addr_start) row = '' for addr in Heads(addr_start, addr_end): ins = '' thisOperand = idc.GetMnem(addr) oPtype1 = idc.GetOpType(addr, 0) oPtype2 = idc.GetOpType(addr, 1) # assemblydata = parametertype(oPtype1)+' '+parametertype(oPtype2) if (oPtype1 == 1 or oPtype1 == 4): oPtype1 = idc.GetOpnd(addr, 0) if (oPtype2 == 1 or oPtype2 == 4): oPtype2 = idc.GetOpnd(addr, 1) if thisOperand == "call": call_fun_name = GetOpnd(addr, 0) keyInstr = LocByName(call_fun_name) fflags = idc.get_func_flags(keyInstr) if (fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK): ins = thisOperand + '_' + idc.GetOpnd(addr, 0) + '_0' row = row + ' ' + ins continue ins = str(thisOperand)+'_'+tran(str(oPtype1)) + \ '_'+tran(str(oPtype2)) row = row + ' ' + ins return row # file_name.writerow([name_fun, hex(addr_start), hex(addr_end), row]) deepset = list() path = list() all_path = list() def print_path_deepest(head): global deepset global path global all_path # print(deepset) if head is None: return if head in all_path: return # print(path) all_path.append(head) path.append(head) # print("********\n",path) if len(deepset) < len(path): # print(len(deepset),len(path)) deepset = [i for i in path] # print(deepset) for elem in head.child: print_path_deepest(elem) path.remove(head) # print("#######\n",path) def print_path_all(head): global path # print(deepset) if head is None: return if head in path: return path.append(head) for elem in head.child: print_path_all(elem) f = open(file_store_path + '\\' + 'test' + '.csv', 'wb') saveFile = csv.writer(f) saveFile.writerow(["name", "start", "end", "Op"]) for fun_node in self.root: name_fun = GetFunctionName(fun_node.addr) fflags = idc.get_func_flags(fun_node.addr) if not ((fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK)): global path path = list() global deepset deepset = list() global all_path all_path = list() # print(deepset) # path.clear() print_path_deepest(fun_node) row_fun = '' fun_addr_end = idc.FindFuncEnd(fun_node.addr) for bb in deepset: ins_bb = ext_instruction(saveFile, bb.block.startEA, bb.block.end_ea) row_fun = row_fun + ' ' + ins_bb saveFile.writerow( [name_fun, hex(fun_node.addr), hex(fun_addr_end), row_fun])
def main(): eh = flare_emu.EmuHelper() # dictionary that stores data used across emulation runs, function emulation specific data is set below userData = { # found stackstrings in stack memory "stackstrings": [], # found stackstrings in global memory (globalstrings) "globalstrings": [] } cnt_functions = 0 cnt_analyzed = 0 cnt_found_ss = 0 cnt_commented_ss = 0 errors = [] start = time.time() print("Started ironstrings stackstring deobfuscation") print_header() if ANALYZE_SINGLE_FUNC: fvas = [idc.get_func_attr(idc.here(), idc.FUNCATTR_START)] else: fvas = idautils.Functions() for fva in fvas: logging.debug("running on 0x%X", fva) if JUMP_TO_FUNC: idc.jumpto(fva) if fva == idaapi.BADADDR: logging.debug("skipping invalid function address") continue if idc.get_func_flags(fva) & (idc.FUNC_LIB | idc.FUNC_THUNK): logging.debug("skipping library or thunk function 0x%X", fva) continue # function start address userData["funcStart"] = fva # list of addresses of last instruction for all basic blocks in function userData["bb_ends"] = get_bb_ends(fva) # memory writes in current function userData["mem_writes"] = {} # start and end addresses of all memory writes in function userData["writelog"] = set() # memory write count in current basic block userData["mem_write_count"] = 0 # cache previous address to count instructions that are executed multiple times, e.g. rep prefixed userData["prevAddress"] = 0 # number same instruction has been executed in a row userData["repCount"] = 0 cnt_functions += 1 try: # emulate various paths through function via flare-emu, use hooks to reconstruct strings eh.iterateAllPaths(fva, noop, hookData=userData, callHook=call_hook, instructionHook=instr_hook, memAccessHook=hook_mem_write, hookApis=False, maxPaths=MAX_CODE_PATHS) except unicorn.UcError as e: errors.append("Error analyzing function 0x{:X}: {}".format(fva, str(e))) else: cnt_analyzed += 1 # print stackstrings found in this function f_ss = filter(lambda s: s.fva == fva, userData["stackstrings"]) cnt_found_ss += len(f_ss) for ss in sorted(f_ss, key=lambda s: s.written_at): print_string(ss.fva, ss.written_at, ss.offset, ss.s) # IMPROVEMENT adjust stack frame member size in IDA view # print globalstrings found in this function f_gs = filter(lambda g: g.fva == fva, userData["globalstrings"]) cnt_found_ss += len(f_gs) for gs in sorted(f_gs, key=lambda g: g.written_at): print_string(gs.fva, gs.written_at, gs.offset, gs.s) if COMMENT_STACKSTRINGS: for ss in f_ss: if not ss.written_at: errors.append("Can't get location where '{}' was written in 0x{:X}.".format(ss.s, ss.fva)) continue ss_cmt = format_comment(ss.s) if append_comment(ss.written_at, ss_cmt): cnt_commented_ss += 1 else: errors.append("Failed to set comment at 0x{:X}: {}".format(ss.written_at, ss_cmt)) for gs in f_gs: if COMMENT_STACKSTRING_GLOBAL_REPEATABLE: repeatable = True cmt_va = gs.offset else: repeatable = False cmt_va = gs.written_at if not cmt_va: errors.append("Can't get location where '{}' was written in 0x{:X}.".format(gs.s, gs.fva)) continue gs_cmt = format_comment(gs.s) if append_comment(cmt_va, gs_cmt, repeatable): cnt_commented_ss += 1 else: errors.append("Failed to set comment at 0x{:X}: {}".format(cmt_va, gs_cmt)) # update IDA view idc.refresh_idaview_anyway() # clean up memory after each function eh.resetEmulatorHeapAndStack() print_summary(cnt_functions, cnt_analyzed, cnt_found_ss, cnt_commented_ss, errors) if PRINT_PLAIN_SUMMARY: print_plain_summary(userData["stackstrings"] + userData["globalstrings"]) print("\nFinished ironstrings stackstring deobfuscation after {:.2f} seconds".format(time.time() - start))
def main(): eh = flare_emu.EmuHelper() # dictionary that stores data used across emulation runs, function emulation specific data is set below userData = { # found stackstrings in stack memory "stackstrings": [], # found stackstrings in global memory (globalstrings) "globalstrings": [] } cnt_functions = 0 cnt_analyzed = 0 cnt_found_ss = 0 cnt_commented_ss = 0 errors = [] start = time.time() print("Started ironstrings stackstring deobfuscation") print_header() if ANALYZE_SINGLE_FUNC: fvas = [idc.get_func_attr(idc.here(), idc.FUNCATTR_START)] else: fvas = idautils.Functions() for fva in fvas: logging.debug("running on 0x%X", fva) if JUMP_TO_FUNC: idc.jumpto(fva) if fva == idaapi.BADADDR: logging.debug("skipping invalid function address") continue if idc.get_func_flags(fva) & (idc.FUNC_LIB | idc.FUNC_THUNK): logging.debug("skipping library or thunk function 0x%X", fva) continue # function start address userData["funcStart"] = fva # list of addresses of last instruction for all basic blocks in function userData["bb_ends"] = get_bb_ends(fva) # memory writes in current function userData["mem_writes"] = {} # start and end addresses of all memory writes in function userData["writelog"] = set() # memory write count in current basic block userData["mem_write_count"] = 0 # cache previous address to count instructions that are executed multiple times, e.g. rep prefixed userData["prevAddress"] = 0 # number same instruction has been executed in a row userData["repCount"] = 0 cnt_functions += 1 try: # emulate various paths through function via flare-emu, use hooks to reconstruct strings eh.iterateAllPaths(fva, noop, hookData=userData, callHook=call_hook, instructionHook=instr_hook, memAccessHook=hook_mem_write, hookApis=False, maxPaths=MAX_CODE_PATHS) except unicorn.UcError as e: errors.append("Error analyzing function 0x{:X}: {}".format( fva, str(e))) else: cnt_analyzed += 1 # print stackstrings found in this function f_ss = filter(lambda s: s.fva == fva, userData["stackstrings"]) cnt_found_ss += len(f_ss) for ss in sorted(f_ss, key=lambda s: s.written_at): print_string(ss.fva, ss.written_at, ss.offset, ss.s) # IMPROVEMENT adjust stack frame member size in IDA view # print globalstrings found in this function f_gs = filter(lambda g: g.fva == fva, userData["globalstrings"]) cnt_found_ss += len(f_gs) for gs in sorted(f_gs, key=lambda g: g.written_at): print_string(gs.fva, gs.written_at, gs.offset, gs.s) if COMMENT_STACKSTRINGS: for ss in f_ss: if not ss.written_at: errors.append( "Can't get location where '{}' was written in 0x{:X}." .format(ss.s, ss.fva)) continue ss_cmt = format_comment(ss.s) if append_comment(ss.written_at, ss_cmt): cnt_commented_ss += 1 else: errors.append( "Failed to set comment at 0x{:X}: {}".format( ss.written_at, ss_cmt)) for gs in f_gs: if COMMENT_STACKSTRING_GLOBAL_REPEATABLE: repeatable = True cmt_va = gs.offset else: repeatable = False cmt_va = gs.written_at if not cmt_va: errors.append( "Can't get location where '{}' was written in 0x{:X}." .format(gs.s, gs.fva)) continue gs_cmt = format_comment(gs.s) if append_comment(cmt_va, gs_cmt, repeatable): cnt_commented_ss += 1 else: errors.append( "Failed to set comment at 0x{:X}: {}".format( cmt_va, gs_cmt)) # update IDA view idc.refresh_idaview_anyway() # clean up memory after each function eh.resetEmulatorHeapAndStack() print_summary(cnt_functions, cnt_analyzed, cnt_found_ss, cnt_commented_ss, errors) if PRINT_PLAIN_SUMMARY: print_plain_summary(userData["stackstrings"] + userData["globalstrings"]) print( "\nFinished ironstrings stackstring deobfuscation after {:.2f} seconds" .format(time.time() - start))
def withinFunction(self): return idc.get_func_flags(self.ea) != -1
# # invoke with: # idat64 -c -A -S"ida-analysis.py $HOME/analysis.txt" <file.bin> # import sys import idc import idautils f = open(idc.ARGV[1], 'a') if len(idc.ARGV) > 1 else sys.stdout log = f.write # log current file path log(idc.get_input_file_path() + '\n') # wait for auto-analysis to complete idc.auto_wait() # count functions log( 'count %d\n' % len(list(idautils.Functions())) ) # print function name and addresses for ea in idautils.Functions(): if idc.get_func_flags(ea) & (idc.FUNC_LIB | idc.FUNC_THUNK): continue log( hex(ea) + ' ' + idc.get_func_name(ea) + '\n' ) # if logging to a file, close it and exit IDA Pro if f != sys.stdout: f.close() idc.qexit(0)