def is_line_exists(line_address): """ Check if a given address corresponds to a real line. """ # Use a hack of trying to check if the line is code. # If we get an exception, this is probably not a real line: try: idaapi.isCode(line_address) except TypeError: return False return True
def GetInstructions(start_ea, end_ea): ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(Instruction(head, GetDisasm(head))) return ins
def is_code_ea(ea): if idaapi.cvar.inf.procname == "ARM": # In case of ARM code in THUMB mode we sometimes get pointers with thumb bit set flags = idaapi.getFlags(ea & -2) # flags_t else: flags = idaapi.getFlags(ea) return idaapi.isCode(flags)
def findUnidentifiedFunctions(): # just get all not-function code and convert it to functions next = idaapi.cvar.inf.minEA while next != idaapi.BADADDR: next = idaapi.find_not_func(next, SEARCH_DOWN) flags = idaapi.getFlags(next) if idaapi.isCode(flags): idc.MakeFunction(next)
def highlight(self, color=COLOR): for ea in idautils.Heads(): if idaapi.isCode(idaapi.getFlags(ea)) and idaapi.is_call_insn(ea): current_color = idaapi.get_item_color(ea) if current_color == self.COLOR: idaapi.set_item_color(ea, idc.DEFCOLOR) elif current_color == idc.DEFCOLOR: idaapi.set_item_color(ea, self.COLOR)
def findUnidentifiedFunctions(): # just get all not-function code and convert it to functions next = idaapi.cvar.inf.minEA while next != idaapi.BADADDR: next = idaapi.find_not_func(next, 1) flags = idaapi.getFlags(next) if idaapi.isCode(flags): idc.MakeFunction(next)
def Run(self): for function_ea in idautils.Functions(): for inst_ea in idautils.FuncItems(function_ea): if idaapi.isCode(idaapi.getFlags(inst_ea)): mnemonic = idc.GetMnem(inst_ea) if (mnemonic == 'rdmsr' or mnemonic == 'wrmsr'): msr_code = self.GetMsrCodeFromOperand(inst_ea) self.PrintMsrTable(msr_code, function_ea, inst_ea)
def GetInstructions(self, start_ea, end_ea): # #Returns a List of all instructions in the Range start_ea, end_ea # ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(GetDisasm(head)) return ins
def GetInstructions(start_ea, end_ea): """ Return a list of all the instructions in the range [start_ea, end_ea]. """ ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(Instruction(head, GetDisasm(head))) return ins
def get_code_heads(): """Returns a set with all the recognized code heads from all the code sections.""" global code_heads if len(code_heads) == 0: for begin, end, name in code_segments_iter(): code_heads |= set(filter(lambda x: idaapi.isCode(idc.GetFlags(x)), idautils.Heads(begin, end))) return code_heads
def __init__(self, ea, info, cs): """Initialization function.""" # Init the node structure node_t.__init__(self) # Check if it's a code instruction try: is_c = is_code(get_flags(ea)) except: is_c = isCode(GetFlags(ea)) if not is_c: raise CodeException # # fill node_t struct # # NodeInfo self.info = NodeInfo() inst_elements = [] try: size = create_insn(ea) bytes = get_bytes(ea, size) except: size = MakeCode(ea) bytes = GetManyBytes(ea, size) (address, size, mnemonic, op_str) = cs.disasm_lite(bytes, ea, count=1).next() self.info.opcode = mnemonic.encode("ascii", "ignore") op_str_ascci = op_str.encode("ascii", "ignore") self.info.inst_str = self.info.opcode + " " + op_str_ascci splitted = op_str_ascci.split(", ") self.info.nargs = 0 if len(splitted) >= 1: self.info.arg1 = splitted[0] self.info.nargs += 1 if len(splitted) >= 2: self.info.arg2 = splitted[1] self.info.nargs += 1 if len(splitted) >= 3: self.info.arg3 = splitted[2] self.info.nargs += 1 # No node will be root but this is acceptable for CFGs self.info.is_root = False self.info.address = ea self.info.has_address = True # node_t self.node_id = self._genid()
def get_code_heads(): """Returns a set with all the recognized code heads from all the code sections.""" global code_heads if len(code_heads) == 0: for begin, end, name in code_segments_iter(): code_heads |= set( filter(lambda x: idaapi.isCode(idc.GetFlags(x)), idautils.Heads(begin, end))) return code_heads
def populate(self): address = self.address while True: if Const.EA64: func_address = idaapi.get_64bit(address) else: func_address = idaapi.get_32bit(address) flags = idaapi.getFlags(func_address) # flags_t if idaapi.isCode(flags): self.virtual_functions.append(VirtualFunction(func_address, address - self.address)) address += Const.EA_SIZE else: break
def run(self, arg): idaapi.msg("[i2q Plugin] Syncing ...\n") self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): #idaapi.msg("[i2q Plugin] update instrunction address\n") update_address("iaddr", self.addr) else: # Data Address #idaapi.msg("[i2q Plugin] update data address\n") update_address("daddr", self.addr) self.old_addr = self.addr
def OnViewCurpos(self): self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): # don't update the address if it's already the qira address or None if (self.addr is not None) and (self.addr != qira_address): #idaapi.msg("[QIRA Plugin] Qira Address %x \n" % (self.addr)) # Instruction Address set_qira_address(self.addr) update_address("iaddr", self.addr) else: # Data Address update_address("daddr", self.addr) self.old_addr = self.addr
def run(self, arg): idaapi.msg("[QIRA Plugin] Syncing with Qira\n") self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): # don't update the address if it's already the qira address if (self.addr != qira_address): # Instruction Address set_qira_address(self.addr) update_address("iaddr", self.addr) else: # Data Address update_address("daddr", self.addr) self.old_addr = self.addr
def process_func(func, start_ea, end_ea): for head in idautils.Heads(start_ea, end_ea): flags = idaapi.getFlags(head) if idaapi.isCode(flags): mnem = idc.GetMnem(head) if mnem == 'call' or mnem == 'jmp': op_ea = idc.GetOperandValue(head, 0) fn = ida_funcs.get_func(op_ea) if fn: fn_info = postprocess_func(fn) if fn_info: func['calls'][get_func_name(op_ea)] = fn_info
def getInvariantsBytes(InstructionAddress, Size, ida_instruction_bytes_cache): # while no instruction currentEa = InstructionAddress while not idaapi.isCode(idaapi.get_flags_novalue(currentEa)): currentEa += idc.ItemSize(currentEa) if currentEa >= (InstructionAddress + Size): return (('', ''), currentEa - InstructionAddress) FirstInstructionOffset = currentEa - InstructionAddress (hashes, instruction_size) = decodeInstruction(InstructionAddress + FirstInstructionOffset, ida_instruction_bytes_cache[FirstInstructionOffset:]) # concac hash of code and instruction id return (hashes, instruction_size + FirstInstructionOffset)
def check_new_code_area(ea): """ Check if the current ea is a part of an un-analyzed code segment @return: If new code segment was located return a tuple of (new_code_seg_start, new_code_seg_end), otherwise return None """ if ea is idaapi.BADADDR: raise RuntimeError("check_new_code_segment failed. Bad Address: %s" % hex(ea)) # If ea is defined as code, this is not a new code segment. if idaapi.isCode(idc.GetFlags(ea)): return None # If ea is not defined as code return the entire segment borders # TODO: this should be refined to return a more specific area return (idc.SegStart(ea), idc.SegEnd(ea))
def find_unmapped_funcs(): funcs = {} i = 0 ea = 0 max_ea = 0xFFFFFFFF while True: ea = NextHead(ea, max_ea) if ea == BADADDR: break flags = idaapi.getFlags(ea) if idaapi.isCode(flags): if not idaapi.get_func(ea): s = util.scan_insn_for_debug_ref(ea) if s != None: if not s in funcs: funcs[s] = ea return funcs
def run(self, arg): idaapi.msg("[%s] Syncing with WS Server\n" % (self.wanted_name,)) self.addr = idaapi.get_screen_ea() if self.old_addr != self.addr: # check against idc.BADADDR and None before going if (self.addr is not None) and (self.addr != idc.BADADDR): # Code Address if idaapi.isCode(idaapi.getFlags(self.addr)): # don't set the address if it's already the qira_address if self.addr != self.qira_address: # debugging if DEBUG: idaapi.msg( "[%s] Qira Address 0x%x \n" % (self.wanted_name, self.addr,)) # Instruction Address self.set_qira_address(self.addr) self.update_address("iaddr", self.addr) # Data Address elif idaapi.isData(idaapi.getFlags(self.addr)): self.update_address("daddr", self.addr) # Tail Address elif idaapi.isTail(idaapi.getFlags(self.addr)): self.update_address("taddr", self.addr) # Unknown Address elif idaapi.isUnknown(idaapi.getFlags(self.addr)): self.update_address("uaddr", self.addr) # Head Address elif idaapi.isHead(idaapi.getFlags(self.addr)): self.update_address("haddr", self.addr) # Flow Address elif idaapi.isFlow(idaapi.getFlags(self.addr)): self.update_address("faddr", self.addr) # Var Address elif idaapi.isVar(idaapi.getFlags(self.addr)): self.update_address("vaddr", self.addr) # Data Address else: self.update_address("daddr", self.addr) self.old_addr = self.addr
def NonFuncs(*args): """ Enumerate code which is not in a function @param ea: where to start @param endea: BADADDR, or end address @return: list of addresses containing code, but not in a function Example:: for ea in NonFuncs(FirstSeg(), BADADDR): if not MakeFunction(ea): Jump(ea) break Wait() Will try to change non-function code to function until MakeFunction fails """ (first, last)= getrange(args) ea = first while ea!=idaapi.BADADDR and ea<last: nextcode= idaapi.find_code(ea, idaapi.SEARCH_NEXT|idaapi.SEARCH_DOWN) thischunk= idaapi.get_fchunk(ea) nextchunk= idaapi.get_next_fchunk(ea) if thischunk: ea= thischunk.endEA elif idaapi.isCode(idaapi.getFlags(ea)): yield ea ea= idaapi.next_head(ea, last) elif nextchunk is None: return elif nextcode<nextchunk.startEA: yield nextcode ea= nextcode else: ea= nextchunk.endEA
def NonFuncs(*args): """ Enumerate code which is not in a function @param <range>: see getrange @return: list of addresses containing code, but not in a function Example:: for ea in NonFuncs(FirstSeg(), BADADDR): if not MakeFunction(ea): Jump(ea) break Wait() Will try to change non-function code to function until MakeFunction fails """ (first, last) = getrange(args) ea = first while ea != idaapi.BADADDR and ea < last: nextcode = idaapi.find_code(ea, idaapi.SEARCH_NEXT | idaapi.SEARCH_DOWN) thischunk = idaapi.get_fchunk(ea) nextchunk = idaapi.get_next_fchunk(ea) if thischunk: ea = thischunk.endEA elif idaapi.isCode(idaapi.getFlags(ea)): yield ea ea = idaapi.next_head(ea, last) elif nextchunk is None: return elif nextcode < nextchunk.startEA: yield nextcode ea = nextcode else: ea = nextchunk.endEA
def check_address(address): # Checks if given address contains virtual table. Returns True if more than 2 function pointers found # Also if table's addresses point to code in executable section, than tries to make functions at that addresses functions_count = 0 while True: func_address = idaapi.get_64bit(address) if Const.EA64 else idaapi.get_32bit(address) flags = idaapi.getFlags(func_address) # flags_t # print "[INFO] Address 0x{0:08X}".format(func_address) if idaapi.isCode(flags): functions_count += 1 address += Const.EA_SIZE else: segment = idaapi.getseg(func_address) if segment and segment.perm & idaapi.SEGPERM_EXEC: idc.MakeUnknown(func_address, 1, idaapi.DOUNK_SIMPLE) if idc.MakeFunction(func_address): functions_count += 1 address += Const.EA_SIZE continue break idaapi.autoWait() return functions_count
def is_code(self): """Is the line code.""" return idaapi.isCode(self.flags)
def is_code(self): """Is the location code.""" return idaapi.isCode(self.flags)
def is_code_ea(ea): flags = idaapi.getFlags(ea) # flags_t return idaapi.isCode(flags)
def __init__(self, ea, cs, IDA_inst, IDA_inst_size, IDA_inst_string): """Initialization function, to disassemble with Capstone""" # Init the node structure node_t.__init__(self) # Check if it's a code instruction try: is_c = is_code(get_flags(ea)) except: is_c = isCode(GetFlags(ea)) if not is_c: raise CodeException # # fill node_t struct # # NodeInfo self.info = NodeInfo() inst_elements = [] if cs is not None: try: size = create_insn(ea) bytes = get_bytes(ea, size) except: size = MakeCode(ea) bytes = GetManyBytes(ea, size) (address, size, mnemonic, op_str) = next(cs.disasm_lite(bytes, ea, count=1)) else: address = ea size = IDA_inst_size splitted = IDA_inst_string.split(" ") mnemonic = splitted[0] op_str = " ".join(splitted[1:]) self.info.opcode = mnemonic self.info.inst_str = self.info.opcode + " " + op_str splitted = op_str.split(", ") self.info.nargs = 0 if len(splitted) >= 1: self.info.arg1 = splitted[0] self.info.nargs += 1 if len(splitted) >= 2: self.info.arg2 = splitted[1] self.info.nargs += 1 if len(splitted) >= 3: self.info.arg3 = splitted[2] self.info.nargs += 1 # No node will be root but this is acceptable for CFGs self.info.is_root = False self.info.address = ea self.info.has_address = True # node_t self.node_id = self._genid()
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs #old ver compat nextHeadArgCount = len(inspect.getargspec(idc.NextHead).args) cnt = 0 while True: cnt += 1 if nextHeadArgCount == 1: ea = idc.NextHead(ea) else: ea = idc.NextHead(ea, idc.BADADDR) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode( idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr, target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0 ) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range(1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1
def AnalyzeRange( self, startEA, endEA ): CurrentAddress = startEA CurrentBlockAddress = CurrentAddress NewBlockStart = True last_op_code = '' while CurrentAddress < endEA: if idaapi.isCode( idaapi.get_flags_novalue( CurrentAddress ) ): idaapi.decode_insn( CurrentAddress ) op_code = idaapi.ua_mnem( CurrentAddress ) operands=[] disasm_line = op_code + ' ' for i in range(0, 6, 1): operand = idaapi.ua_outop2( CurrentAddress, i ) if not operand: break; operand = idaapi.tag_remove( operand ) operands.append( operand ) if i != 0: disasm_line += ',' disasm_line += operand #disasm_line = idaapi.tag_remove( idaapi.generate_disasm_line( CurrentAddress ) ) xref = idaapi.xrefblk_t() ret = xref.first_to( CurrentAddress, idaapi.XREF_FAR ) while ret: ret = xref.next_to() NewBlockStart = True if NewBlockStart and last_op_code[0:3] != 'ret' and last_op_code != 'new block': self.AddToMap( CurrentBlockAddress, CurrentAddress, None, 'link') if NewBlockStart: CurrentBlockAddress = CurrentAddress self.BlockData[CurrentBlockAddress]=[] if self.DebugLevel > 2: print '='*80 if self.DebugLevel > 2: print hex(CurrentAddress), disasm_line self.BlockData[CurrentBlockAddress].append( ( CurrentAddress, disasm_line ) ) NewBlockStart = False CallIsResolved = False ret = xref.first_from( CurrentAddress, idaapi.XREF_FAR ) while ret: if xref.iscode: if op_code == 'jmp' and xref.to == CurrentAddress + idaapi.cvar.cmd.size: NewBlockStart = True elif op_code == 'call': CallIsResolved = True self.AddToMap( CurrentBlockAddress,xref.to, operands[0], 'call') else: if len(operands) > 0 : self.AddToMap( CurrentBlockAddress,xref.to, operands[0], 'from') NewBlockStart = True ret = xref.next_from() if ( op_code == 'call' or op_code =='' ) and not CallIsResolved: self.AddToMap( CurrentBlockAddress, operands[0], operands[0], 'call') if NewBlockStart and op_code != 'jmp': self.AddToMap( CurrentBlockAddress, CurrentAddress + idaapi.cvar.cmd.size, '', 'link') if op_code[0:3] == 'ret': NewBlockStart = True last_op_code = op_code CurrentAddress += idaapi.cvar.cmd.size else: CurrentAddress += 1
def AnalyzeRange(self, startEA, endEA): CurrentAddress = startEA CurrentBlockAddress = CurrentAddress NewBlockStart = True last_op_code = '' while CurrentAddress < endEA: if idaapi.isCode(idaapi.get_flags_novalue(CurrentAddress)): idaapi.decode_insn(CurrentAddress) op_code = idaapi.ua_mnem(CurrentAddress) operands = [] disasm_line = op_code + ' ' for i in range(0, 6, 1): operand = idaapi.ua_outop2(CurrentAddress, i) if not operand: break operand = idaapi.tag_remove(operand) operands.append(operand) if i != 0: disasm_line += ',' disasm_line += operand #disasm_line = idaapi.tag_remove( idaapi.generate_disasm_line( CurrentAddress ) ) xref = idaapi.xrefblk_t() ret = xref.first_to(CurrentAddress, idaapi.XREF_FAR) while ret: ret = xref.next_to() NewBlockStart = True if NewBlockStart and last_op_code[ 0:3] != 'ret' and last_op_code != 'new block': self.AddToMap(CurrentBlockAddress, CurrentAddress, None, 'link') if NewBlockStart: CurrentBlockAddress = CurrentAddress self.BlockData[CurrentBlockAddress] = [] if self.DebugLevel > 2: print '=' * 80 if self.DebugLevel > 2: print hex(CurrentAddress), disasm_line self.BlockData[CurrentBlockAddress].append( (CurrentAddress, disasm_line)) NewBlockStart = False CallIsResolved = False ret = xref.first_from(CurrentAddress, idaapi.XREF_FAR) while ret: if xref.iscode: if op_code == 'jmp' and xref.to == CurrentAddress + idaapi.cvar.cmd.size: NewBlockStart = True elif op_code == 'call': CallIsResolved = True self.AddToMap(CurrentBlockAddress, xref.to, operands[0], 'call') else: if len(operands) > 0: self.AddToMap(CurrentBlockAddress, xref.to, operands[0], 'from') NewBlockStart = True ret = xref.next_from() if (op_code == 'call' or op_code == '') and not CallIsResolved: self.AddToMap(CurrentBlockAddress, operands[0], operands[0], 'call') if NewBlockStart and op_code != 'jmp': self.AddToMap(CurrentBlockAddress, CurrentAddress + idaapi.cvar.cmd.size, '', 'link') if op_code[0:3] == 'ret': NewBlockStart = True last_op_code = op_code CurrentAddress += idaapi.cvar.cmd.size else: CurrentAddress += 1
"%s = unk_689FA0[%s*0x7f + byte_686090[ %s*0x7f+%s[%s] ]]" ] ea = ScreenEA() result = [] for i in xrange(len(template)): result.append([]) begin = [0]*len(template) template_index = [0]*len(template) last_template_addr = ea not_in_template = [] while True: if idaapi.isCode(idaapi.getFlags(ea)): flag = True cmd = idc.GetDisasm(ea) opcode = cmd.split(' ')[0] for i in xrange(len(template)): if opcode == template[i][ template_index[i] ]: flag = False if template_index[i] == 0: begin[i] = ea if template_index[i] < len(template[i])-1: template_index[i] += 1 else: # if match a template result[i].append( (begin[i],ea) ) tmp = idc.NextHead(last_template_addr) if tmp >= begin[i]: pass
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs cnt = 0 while True: cnt += 1 ea = idc.NextHead(ea) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode(idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr,target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range (1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1