Esempio n. 1
0
    def readFunction(self, f, discard=True):
        name = idc.GetFunctionName(f)
        func = idaapi.get_func(f)
        flow = idaapi.FlowChart(func)
        size = func.endEA - func.startEA

        if discard:
            # Unnamed function, ignore it...
            if name.startswith("sub_") or name.startswith(
                    "j_") or name.startswith("unknown"):
                return False

            # Already recognized runtime's function
            flags = idc.GetFunctionFlags(f)
            if flags & idc.FUNC_LIB or flags == -1:
                return False

        nodes = 0
        edges = 0
        points = 0
        instructions = 0
        mnems = []
        dones = {}

        for block in flow:
            nodes += 1
            indegree = 0
            outdegree = 0
            for succ_block in block.succs():
                edges += 1
                indegree += 1
                if not dones.has_key(succ_block.id):
                    dones[succ_block] = 1
                    for x in list(
                            idautils.Heads(succ_block.startEA,
                                           succ_block.endEA)):
                        instructions += 1
                        mnems.append(idc.GetMnem(x))

            for pred_block in block.preds():
                edges += 1
                outdegree += 1
                if not dones.has_key(succ_block.id):
                    dones[succ_block] = 1
                    for x in list(
                            idautils.Heads(succ_block.startEA,
                                           succ_block.endEA)):
                        instructions += 1
                        mnems.append(idc.GetMnem(x))

            if indegree > 0:
                points += indegree
            if outdegree > 0:
                points += outdegree

        if nodes > 1 and instructions > 5 and edges > 1:
            #myexport_print("Exporter: Current function 0x%08x %s" % (f, name))
            return (name, nodes, edges, points, size, instructions, mnems)

        return False
def find_all_ioctls():
    """
    From the currently selected address attempts to traverse all blocks inside the current function to find all immediate values which
    are used for a comparison/sub immediately before a jz. Returns a list of address, second operand pairs.
    """

    ioctls = []
    # Find the currently selected function and get a list of all of it's basic blocks
    addr = idc.ScreenEA()
    f = idaapi.get_func(addr)
    fc = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
    for block in fc:
        # grab the last two instructions in the block
        last_inst = idc.PrevHead(block.endEA)
        penultimate_inst = idc.PrevHead(last_inst)
        # If the penultimate instruction is cmp or sub against an immediate value immediatly preceding a 'jz'
        # then it's a decent guess that it's an IOCTL code (if this is a disptach function)
        if idc.GetMnem(penultimate_inst) in ['cmp', 'sub'] and idc.GetOpType(
                penultimate_inst, 1) == 5:
            if idc.GetMnem(last_inst) == 'jz':
                ioctl_tracker.add_ioctl(penultimate_inst)
    for inst in ioctl_tracker.ioctl_locs:
        value = get_operand_value(inst)
        ioctls.append((inst, value))
    return ioctls
Esempio n. 3
0
def TraceApiCall(code):
    print "operand 0 is "+idc.GetOpnd(code,0)
    print "operand 1 is "+idc.GetOpnd(code,1)
    print "operand 2 is "+idc.GetOpnd(code,2)
    
    reg = idc.GetOpnd(code,0)
    
    ### search down to find caller  it cannt deal with such situation: 
    ###    addi r10, r10, VOS_sprintf@l
    ###    b addr
    ###     in the above code, the trace should follow addr to find the right call
    ###    
    
    func_end = idc.GetFunctionAttr(code, idc.FUNCATTR_END)
    
    instruct = "mtlr "+reg

    while(code < func_end):
        code = idc.FindCode(code, SEARCH_DOWN|SEARCH_NEXT)
        ### search "mtlr r10"
        if(("mtlr"==idc.GetMnem(code)) and (idc.GetOpnd(code,1) == reg)):
            print idc.GetOpnd(code,1)
            print "Get the instruct! "+ idc.GetDisasm(code)
            
            while(code < func_end):
                code = idc.FindCode(code, SEARCH_DOWN|SEARCH_NEXT)
                
                if("blrl" in idc.GetDisasm(code)):
                    print "api call " + idc.GetDisasm(code)+" from ",hex(code)
                    print "mnem "+idc.GetMnem(code)
                    return code
Esempio n. 4
0
def calBasicBlockFeature_gemini(block):
    numericNum = 0
    stringNum = 0
    transferNum = 0
    callNum = 0
    InstrNum = 0
    arithNum = 0
    logicNum = 0
    curEA = block.startEA
    while curEA <= block.endEA:
        #	数值常量 , 字符常量的数量
        numer, stri = calConstantNumber(curEA)
        numericNum = numericNum + numer
        stringNum = stringNum + stri
        #	转移指令的数量
        if idc.GetMnem(curEA) in config_for_feature.Gemini_allTransferInstr:
            transferNum = transferNum + 1
        # 调用的数量
        if idc.GetMnem(curEA) == 'call':
            callNum = callNum + 1
        # 指令的数量
        InstrNum = InstrNum + 1
        #	算术指令的数量
        if idc.GetMnem(curEA) in config_for_feature.Gemini_arithmeticInstr:
            arithNum = arithNum + 1
        #  逻辑指令
        if idc.GetMnem(curEA) in config_for_feature.Gemini_logicInstr:
            logicNum = logicNum + 1

        curEA = idc.NextHead(curEA, block.endEA)

    fea_str = str(numericNum) + "," + str(stringNum) + "," + str(
        transferNum) + "," + str(callNum) + "," + str(InstrNum) + "," + str(
            arithNum) + "," + str(logicNum) + ","
    return fea_str
Esempio n. 5
0
    def jumps_to(f, t):
        f_ea = idc.LocByName(f)
        t_ea = idc.LocByName(t)

        for start, end in idautils.Chunks(f_ea):
            ea = start
            while (ea < end):
                i = idautils.DecodeInstruction(ea)

                #Functions have data chunks in them, these are offsets and dwords. skipping 4 ahead seems like a safe choice.
                if type(i) == type(None):
                    ea += 4
                    continue

                #detect if instruction is a jump to t_ea
                m = idc.GetMnem(ea)
                if idc.GetMnem(ea) == "LDR" and idc.GetOpnd(
                        ea, 0) == "PC" and t in idc.GetOpnd(ea, 1):
                    return True
                elif idc.GetMnem(ea) == "BX" and idc.GetOpnd(ea, 0) == t:
                    return True

                try:
                    ea += i.size
                except:
                    print "0x%08x" % ea
                    print "DecodeInstruction failed!"
                    print i.size

        return False
Esempio n. 6
0
def check_operand(opnd, call_arguments, heads):
    if is_argument(opnd, call_arguments):
        return True

    for head in heads:
        if is_jump(head):
            return False

        if is_return_value(opnd) and idc.GetMnem(
                head) == 'call' and ida_funcs.func_does_return(head):
            return check_eax(head, call_arguments)

        if idc.GetMnem(head) == 'call' and is_used(head, opnd):
            return False

        if opnd != idc.GetOpnd(head, 0):
            continue

        if should_check_second_opnd(head):
            if is_number(idc.GetOpnd(head, 1)):
                return is_argument(idc.GetOpnd(head, 1), call_arguments)
            opnd = idc.GetOpnd(head, 1)

        elif (not is_number(idc.GetOpnd(head, 1))) and check_next_opnd(
                head, call_arguments):
            return True

        if is_argument(opnd, call_arguments):
            return True

    return False
Esempio n. 7
0
def get_args(addr):
    """ Retreives the passed arguments to the decryption function. We are only interested in the key
        and offset to the encrypted string.

        addr: (int) Address at which the decryption function was called.

        Returns:
        key: (int) The key used to decrypt the string.
        enc_str: (list) Byte array of encrypted string.
        ins_addr: (int) Address at which the encrypted byte array is referenced.

    """
    found = False
    foundstr = False
    foundkey = False
    while not found:
        addr = idc.PrevHead(addr)
        if idc.GetMnem(addr) == "mov" and "r8d" in idc.GetOpnd(addr,0):
            #print "[+] Found key: 0x%08x at 0x%016x" % (idc.GetOperandValue(addr,1)& 0xffffffff, addr)
            key = idc.GetOperandValue(addr,1) & 0xffffffff
            foundkey = True

        if idc.GetMnem(addr) == "lea" and "rdx" in idc.GetOpnd(addr,0):
            #print "[+] Found str: 0x%016x at 0x%016x" % (idc.GetOperandValue(addr,1), addr)
            enc_str_addr = idc.GetOperandValue(addr,1)
            enc_str = get_encoded_string(enc_str_addr)
            ins_addr = addr
            foundstr = True
        
        if foundkey and foundstr:
            found = True
    
    return key, enc_str, ins_addr
Esempio n. 8
0
    def revise_syscall(rename=False):
        if not rename:
            print(
                'Change the function name with `CGCHeler.revise_syscall(True)`.'
            )

        # visit all instructions
        start_ea, end_ea = utils.get_seg_range('.text')
        eax = -1
        ip = start_ea
        while ip < end_ea and ip != idaapi.BADADDR:
            if 'int' in idc.GetMnem(ip) and '80h' == idc.GetOpnd(ip, 0):
                if eax != -1:
                    # fix comment and function name
                    print('{}: {}'.format(hex(ip), syscall_table[eax]))
                    idc.MakeComm(ip,
                                 'CGC syscall: {}'.format(syscall_table[eax]))
                    if rename:
                        print('Change {} to {}'.format(idc.GetFunctionName(ip),
                                                       syscall_table[eax]))
                        idc.MakeName(
                            idc.GetFunctionAttr(ip, idc.FUNCATTR_START),
                            syscall_table[eax])
            elif 'mov' in idc.GetMnem(ip) and 'eax' == idc.GetOpnd(
                    ip, 0) and 5 == idc.GetOpType(ip, 1):
                value = idc.GetOpnd(ip, 1)
                if re.search('^[0-9]+$', value) != None:
                    eax = int(value)
                if eax > 7 or eax < 1:
                    eax = -1

            ip = idc.NextHead(ip)
Esempio n. 9
0
def find_vm_codes(dispatcher_ea):
    mnem = idc.GetMnem(dispatcher_ea)

    if mnem != "pusha":
        print "dispatcher_ea: 0x%08x, bad mnem: %s" (dispatcher_ea, mnem)
        assert (False)

    refs = idautils.CodeRefsTo(dispatcher_ea, 1)
    refs = list(x for x in refs)

    print "vms found:", len(refs)

    for ref in refs:
        print hex(ref)

    vms = []
    for ref in refs:
        #push offset
        #jmp dispatcher
        push_ea = prev_head(ref)
        mnem = idc.GetMnem(push_ea)
        if mnem != "push":
            print "push_ea:", hex(push_ea)
            print "unexpected mnem:", mnem
            assert (False)
        op = idc.GetOpnd(push_ea, 0)

        op = str2int(op)

        vms.append((push_ea, op))

    return vms
Esempio n. 10
0
def add_bp_to_virtual_calls(cur_addr, end):
    while cur_addr < end:
        if cur_addr == idc.BADADDR:
            break
        elif idc.GetMnem(cur_addr) == 'call' or idc.GetMnem(cur_addr) == 'BLR':
            if True in [idc.GetOpnd(cur_addr, 0).find(reg) != -1 for reg in REGISTERS]:  # idc.GetOpnd(cur_addr, 0) in REGISTERS:
                cond, bp_address = vtableAddress.write_vtable2file(cur_addr)
                if cond != '':
                    bp_vtable = AddBP.add(bp_address, cond)
        cur_addr = idc.NextHead(cur_addr)
Esempio n. 11
0
def add_xrefs(addr, end=idc.BADADDR):
    """
        https://github.com/xyzz/vita-ida-physdump/blob/master/vita_phys_dump.py
        Searches for MOV / MOVT pair, probably separated by few instructions,
        and adds xrefs to things that look like addresses
    """
    while addr < end and addr != BADADDR:
        addr = idc.NextHead(addr)
        if idc.GetMnem(addr) in ["MOV", "MOVW"]:
            reg = idc.GetOpnd(addr, 0)
            if idc.GetOpnd(addr, 1)[0] != "#":
                continue
            val = idc.GetOperandValue(addr, 1)
            found = False
            next_addr = addr
            for x in range(16):
                next_addr = idc.NextHead(next_addr)
                if idc.GetMnem(next_addr) in ["B", "BX"]:
                    break
                # TODO: we could handle a lot more situations if we follow branches, but it's getting complicated
                # if there's a function call and our register is scratch, it will probably get corrupted, bail out
                if idc.GetMnem(next_addr) in ["BL", "BLX"] and reg in [
                        "R0", "R1", "R2", "R3"
                ]:
                    break
                # if we see a MOVT, do the match!
                if idc.GetMnem(next_addr) in ["MOVT",
                                              "MOVT.W"] and idc.GetOpnd(
                                                  next_addr, 0) == reg:
                    if idc.GetOpnd(next_addr, 1)[0] == "#":
                        found = True
                        val += idc.GetOperandValue(next_addr, 1) * (2**16)
                    break
                # if we see something other than MOVT doing something to the register, bail out
                if idc.GetOpnd(next_addr, 0) == reg or idc.GetOpnd(
                        next_addr, 1) == reg:
                    break
            if val & 0xFFFF0000 == 0:
                continue
            if found:
                # pair of MOV/MOVT
                try:
                    idc.OpOffEx(addr, 1, idc.REF_LOW16, val, 0, 0)
                    idc.OpOffEx(next_addr, 1, idc.REF_HIGH16, val, 0, 0)
                except:
                    print "Failed xref @ %x next_addr %x val %x" % (
                        addr, next_addr, val)
            else:
                # a single MOV instruction
                try:
                    idc.OpOff(addr, 1, 0)
                except:
                    print "Failed xref at addr %x" % (addr)
Esempio n. 12
0
 def as_ret_or_arg(self):
     """
     as ret value
     :return:
     """
     for xref in idautils.XrefsTo(self.class_ref):
         if idc.SegName(xref.frm) == '__text':
             if idc.GetMnem(xref.frm) == 'ADRP':
                 pass
             elif 'LDR' in idc.GetMnem(xref.frm):
                 # ctx = CTX(xref.frm, PT(idc.GetOpnd(xref.frm, 0), xref.frm))
                 # if ctx.find_call(rec='x8', sel='alloc'):
                 self.add_occurrences(xref.frm, 'ret_or_arg')
Esempio n. 13
0
 def as_ivar(self):
     """
     When object was referenced as ivar, whether get or set, load or store, the object must exist in this context.
     :return:
     """
     if self.class_name in self.bin_data['ivars2']:
         for ivar in self.bin_data['ivars2'][self.class_name]:
             for xref in idautils.XrefsTo(ivar):
                 if idc.SegName(xref.frm) == '__text':
                     if idc.GetMnem(xref.frm) == 'ADRP':
                         pass
                     elif 'LDR' in idc.GetMnem(xref.frm):
                         # PT(idc.GetOpnd(xref.frm, 0), xref.frm)
                         # ctx = CTX(xref.frm, PT(idc.GetOpnd(xref.frm, 0), xref.frm))
                         self.add_occurrences(xref.frm, 'ivar')
Esempio n. 14
0
def get_con2_var_or_num(i_cnt, cur_addr):
    """
    :param i_cnt: the register of the virtual call
    :param cur_addr: the current address in the memory
    :return: "success" string and the address of the vtable's location. if it fails it sends the reason and -1
    """
    start_addr = idc.GetFunctionAttr(cur_addr, idc.FUNCATTR_START)
    virt_call_addr = cur_addr
    cur_addr = idc.PrevHead(cur_addr)
    dct_arch = get_arch_dct()
    if dct_arch == -1:
        return 'Wrong Architechture', "-1", cur_addr

    while cur_addr >= start_addr:
        if idc.GetMnem(cur_addr)[:3] == dct_arch["opcode"] and idc.GetOpnd(
                cur_addr, 0) == i_cnt:  # TODO lea ?
            opnd2 = idc.GetOpnd(cur_addr, 1)
            place = opnd2.find(dct_arch["separator"])
            if place != -1:  # if the function is not the first in the vtable
                register = opnd2[opnd2.find('[') + 1:place]
                if opnd2.find('*') == -1:
                    offset = opnd2[place +
                                   dct_arch["val_offset"]:opnd2.find(']')]
                else:
                    offset = "*"
                return register, offset, cur_addr
            else:
                offset = "0"
                if opnd2.find(']') != -1:
                    register = opnd2[opnd2.find('[') + 1:opnd2.find(']')]
                else:
                    register = opnd2
                return register, offset, cur_addr
        elif idc.GetMnem(cur_addr)[:4] == "call":
            intr_func_name = idc.GetOpnd(cur_addr, 0)
            # In case the code has CFG -> ignores the function call before the virtual calls
            if "guard_check_icall_fptr" not in intr_func_name:
                if "nullsub" not in intr_func_name:
                    # intr_func_name = idc.Demangle(intr_func_name, idc.GetLongPrm(idc.INF_SHORT_DN))
                    print(
                        "Warning! At address 0x%08x: The vtable assignment might be in another function (Maybe %s),"
                        " could not place BP." %
                        (virt_call_addr, intr_func_name))
                cur_addr = start_addr
        cur_addr = idc.PrevHead(cur_addr)
    return "out of the function", "-1", cur_addr

    return '', 0, cur_addr
Esempio n. 15
0
def get_first_function(ea):
    """ see above, but returns the first pushed value """
    maybe_start = idc.get_func_attr(ea, idc.FUNCATTR_START)
    limit = 0
    if maybe_start == idc.BADADDR:
        limit = 10

    cur_ea = ea
    limit_count = 0
    while cur_ea != idc.BADADDR:
        # are we over limit or up to the func start?
        limit_count += 1
        limit_exceeded = (limit > 0 and limit_count > limit)
        too_far = (maybe_start != idc.BADADDR and cur_ea < maybe_start)
        if limit_exceeded or too_far:
            LOG.error(
                "Failed to find string walking backwards from {:08X}".format(
                    ea))
            return None

        prev_ins = idautils.DecodePreviousInstruction(cur_ea)
        prev_ea = prev_ins.ea

        # did we find it?
        if idc.GetMnem(prev_ea) == 'push':
            if idc.get_operand_type(prev_ea, 0) in [idc.o_mem, idc.o_imm]:
                # push offset found!
                pushed_addr = idc.GetOperandValue(prev_ea, 0)
                # it's not data, then probably good
                if idc.isCode(idc.GetFlags(pushed_addr)):
                    return pushed_addr

        cur_ea = prev_ea
Esempio n. 16
0
    def _does_instruction_match(self, ea, instruction, regex=False):
        i = 0
        op_cnt = 0
        op_ok_cnt = 0
        match = False
        ins_size = idaapi.decode_insn(ea)
        mnem = idc.GetMnem(ea)

        if (not instruction.mnem) or (instruction.mnem == mnem) or (
                regex and re.match(instruction.mnem, mnem)):
            for operand in instruction.operands:
                if operand:
                    op_cnt += 1
                    op = idc.GetOpnd(ea, i)

                    if regex:
                        if re.match(operand, op):
                            op_ok_cnt += 1
                    elif operand == op:
                        op_ok_cnt += 1
                i += 1

            if op_cnt == op_ok_cnt:
                match = True

        return match
Esempio n. 17
0
def DelAllConditionBpt():
    ea = 0x2C13000
    while ea < 0x357D000:
        mnem = idc.GetMnem(ea)
        if mnem == 'jmp' or mnem == 'retn':
            idc.DelBpt(ea)
        ea = idc.NextHead(ea)
Esempio n. 18
0
    def PrintMsrTable(self, msr_code, function_ea, inst_ea):
        mnemonic = idc.GetMnem(inst_ea)
        call_addr = self.GetJumpAddr(inst_ea, function_ea)
        function_name = idc.GetFunctionName(function_ea) + '+' + call_addr
        dwSize = 30 - len(function_name)
        delimeter = " " * dwSize

        if (msr_code == None):
            msr_code_hex = 'Not imm value'
        else:
            msr_code_hex = self.NormalizeHexValue(msr_code)

        if (msr_code == None):
            msr_name = msr_code_hex
        else:
            msr_name = msr_list.get(int(msr_code_hex, 16))

        idc.MakeComm(inst_ea, '{}({})'.format(mnemonic, msr_name))
        idc.SetColor(inst_ea, idc.CIC_ITEM, 0xf8abef)

        msr_name_delimeter = (" " * (15 - len(msr_code_hex)))

        print '{}{}| {} | {} {} | {}'.format(function_name, delimeter,
                                             mnemonic, msr_code_hex,
                                             msr_name_delimeter, msr_name)
Esempio n. 19
0
def parse_register_value(register, start_addr, end_addr):
    print "start find register: %s from 0x%x to 0x%x" % (register, start_addr,
                                                         end_addr)
    _addr = start_addr
    while _addr > end_addr:
        _addr = idc.PrevHead(_addr)
        _opnd_first = idc.GetOpnd(_addr, 0)
        if _opnd_first == register:
            _op_code = idc.GetMnem(_addr)
            second_opnd_type = idc.GetOpType(_addr, 1)
            print 'find register( 0x%x ) -> %s,  type1: %d,  type2: %d' % (
                _addr, idc.GetDisasm(_addr), second_opnd_type,
                idc.GetOpType(_addr, 2))
            if _op_code.startswith('LDR'):
                return parse_opnd_value(_addr, end_addr, 1)
            elif _op_code.startswith('ADD'):
                if (idc.GetOpType(_addr, 2) == 0):
                    if idc.GetOpnd(_addr, 1) == 'PC':
                        # todo: check last _op  =>  LDR             R6, =(_GLOBAL_OFFSET_TABLE_ - 0xAEB6)
                        return 0x00021DB4
                    else:
                        return parse_register_value(
                            register, _addr, end_addr) + parse_opnd_value(
                                _addr, end_addr, 1)
                else:
                    return parse_opnd_value(_addr, end_addr,
                                            1) + parse_opnd_value(
                                                _addr, end_addr, 2)
            elif _op_code.startswith('MOV'):
                return parse_register_value(idc.GetOpnd(_addr, 1), _addr,
                                            end_addr)
Esempio n. 20
0
    def _find_system_calls(self, start_ea, end_ea):
        system_calls = []
        system_load = MIPSInstruction("la", "$t9", "system")
        stack_arg_zero = MIPSInstruction("addiu", "$a0", "$sp")

        for xref in idautils.XrefsTo(idc.LocByName('system')):
            ea = xref.frm
            if ea >= start_ea and ea <= end_ea and idc.GetMnem(ea)[0] in [
                    'j', 'b'
            ]:
                a0_ea = self._find_next_instruction_ea(ea + self.INSIZE,
                                                       stack_arg_zero,
                                                       ea + self.INSIZE)
                if a0_ea == idc.BADADDR:
                    a0_ea = self._find_prev_instruction_ea(
                        ea, stack_arg_zero,
                        ea - (self.SEARCH_DEPTH * self.INSIZE))

                if a0_ea != idc.BADADDR:
                    control_ea = self._find_prev_instruction_ea(
                        ea - self.INSIZE, system_load,
                        ea - (self.SEARCH_DEPTH * self.INSIZE))
                    if control_ea != idc.BADADDR:
                        system_calls.append(
                            ROPGadget(self._get_instruction(control_ea),
                                      self._get_instruction(ea),
                                      self._get_instruction(a0_ea),
                                      description="System call",
                                      base=self.base))

                ea += self.INSIZE
            else:
                break

        return system_calls
Esempio n. 21
0
 def find_interesting_xors(self):
     next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT,
                             0, 0, "xor")
     while next_xor != idc.BADADDR:
         if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1):
             entry = {
                 "func": "",
                 "addr": next_xor,
                 "loop": False,
                 "disasm": idc.GetDisasm(next_xor)
             }
             func = idaapi.get_func(next_xor)
             if func:
                 entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA)
                 heads = idautils.Heads(next_xor, func.endEA)
                 lxors = []
                 for head in heads:
                     if idc.GetMnem(head).startswith('j'):
                         jmp_addr = idc.GetOperandValue(head, 0)
                         if jmp_addr < next_xor and jmp_addr > func.startEA:
                             entry["loop"] = True
                             break
             self._interesting_xors.append(entry)
         next_xor = idc.FindText(idc.NextHead(next_xor),
                                 idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0,
                                 "xor")
Esempio n. 22
0
    def find_value(self, func_addr, instr_addr, register):
        """
        Attempts to resolve the value of the given register at the given address.
        If the value cannot be resolved, None is returned.
        """
        reg_num = idaapi.ph_get_regnames().index(register)

        # go back from the current instruction to the start of the function
        for instr_addr in list(instructions(func_addr, instr_addr))[::-1]:
            # look for instrucations that move a value into the desired register
            mnemonic = idc.GetMnem(instr_addr)
            if mnemonic == 'mov':

                op1_type = idc.get_operand_type(instr_addr, 0)
                op1_value = idc.get_operand_value(instr_addr, 0)

                if op1_type == idc.o_reg and op1_value == reg_num:
                    op2_type = idc.get_operand_type(instr_addr, 1)
                    op2_value = idc.get_operand_value(instr_addr, 1)

                    # if this instruction sets the register to an immediate value
                    if op2_type == idc.o_imm:
                        # return that value
                        return op2_value
                    else:
                        # it is not an immediate value, so we say we cannot
                        # resolve the value
                        return None

        # we did not find an allocation of the register,
        # so we return None to indicate that
        return None
Esempio n. 23
0
    def decide(self, func_addr):
        for instr_addr in func_instructions(func_addr):
            mnemonic = idc.GetMnem(instr_addr)
            if self.is_x64_syscall(mnemonic) or self.is_x86_syscall(
                    mnemonic, instr_addr):
                self.log('0x{:x} has a syscall instruction at 0x{:x}'.format(
                    func_addr, instr_addr))
                num = self.find_value(func_addr, instr_addr, 'ax')
            elif self.is_libc_syscall(mnemonic, instr_addr):
                self.log('0x{:x} has a libc syscall call at 0x{:x}'.format(
                    func_addr, instr_addr))
                num = self.find_value(func_addr, instr_addr, 'di')
            else:
                continue

            # if the syscall number could not be determined or it is
            # one of those we are looking for, return True
            if num is None:
                self.log(
                    '0x{:x} has a syscall at 0x{:x} but we could not find the number so we include it'
                    .format(func_addr, instr_addr))
                return True
            elif num in self.syscalls:
                self.log(
                    '0x{:x} has a syscall at 0x{:x} that we are looking for ({})'
                    .format(func_addr, instr_addr, num))
                return True
            else:
                self.log(
                    '0x{:x} has a syscall at 0x{:x} but it is NOT what are looking for ({})'
                    .format(func_addr, instr_addr, num))

        return False
        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
Esempio n. 25
0
def SetAllConditionBpt():
    ea = 0x2C13000
    while ea < 0x357D000:
        mnem = idc.GetMnem(ea)
        if mnem == 'retn':
            idc.add_bpt(ea)
        ea = idc.NextHead(ea)
Esempio n. 26
0
def norm_func1(head):
    inst = '' + idc.GetMnem(head)
    num_operands = op_count(head)
    for i in range(num_operands):
        type_op = idc.GetOpType(head, i)
        if type_op == idc.o_void:
            break
        elif type_op == idc.o_mem:
            inst += ' [MEM]'
        elif type_op == idc.o_imm:
            val = idc.GetOperandValue(head, i)
            #if -int(5000) <= val <= int(5000):
            if -int(500) <= val <= int(500):
                inst += ' ' + str(hex(val))
            else:
                inst += ' HIMM'
        else:
            inst += ' ' + idc.GetOpnd(head, i)

        if num_operands > 1:
            inst += ','

    if ',' in inst:
        inst = inst[:-1]
    inst = inst.replace(' ', '_')
    return str(inst)
Esempio n. 27
0
    def jump_branches(self, ea):
        """ if this instruction is a jump, yield the destination(s)
            of the jump, of which there may be more than one.
            
            only literal destinations (i.e. addresses without dereferences)
            are yielded. """

        mnem = idc.GetMnem(ea)
        insn = idautils.DecodeInstruction(ea)

        if mnem in self.unconditional_jumps:

            if insn.Op1.type == idaapi.o_near:

                if insn.Op1.addr > self.signed_limit:
                    dest = -((self.max_int + 1) - op.addr)
                else:
                    dest = insn.Op1.addr

                yield dest

        elif mnem in self.conditional_jumps:
            dest = insn.Op1.addr
            yield dest
            dest = ea + insn.size
            yield dest

        return
Esempio n. 28
0
def _split_basic_block(start_ea, end_ea):
    """
    IDA Pro's ``idaapi.Flowchart`` does not consider function calls as basic
    block boundaries. This function takes an address range and splits the
    basic blocks found within that range so that function calls are considered
    basic block boundaries.
    """
    split_bbs = []
    func_name = idc.GetFunctionName(start_ea)
    demangled_name = idc.Demangle(func_name, idc.GetLongPrm(idc.INF_SHORT_DN))
    if demangled_name:
        func_name = demangled_name

    bb_start_addr = start_ea
    block = idautils.Heads(start_ea, end_ea)

    for inst in block:
        mnem = idc.GetMnem(inst)
        if mnem == 'call' and inst != end_ea:
            split_bbs.append(
                dict(start_addr=bb_start_addr,
                     end_addr=idc.NextHead(inst, end_ea + 1) - 1,
                     function=func_name))
            bb_start_addr = idc.NextHead(inst, end_ea + 1)

    if bb_start_addr < end_ea:
        split_bbs.append(
            dict(start_addr=bb_start_addr,
                 end_addr=end_ea - 1,
                 function=func_name))

    return split_bbs
Esempio n. 29
0
def ret_addr(ea):

    #we can't assume Thumb only, so we also keep ARM cases, just adjust addr in Thumb cases
    if (ea % 2) != 0:
        ea -= 1
    '''
	#calculating code segment ranges every time is wasteful
	code_segs = []
	for s in idautils.Segments():
		if idaapi.segtype(s) == idaapi.SEG_CODE:
			s_end = idc.GetSegmentAttr(s, SEGATTR_END)
			code_segs.append({"start" : s, "end" : s_end})

	if not reduce(lambda x, y: x or y, map(lambda x: (x["start"] <= ea) and (x["end"] > ea), code_segs)):
		return False
	'''

    #this is-in-function check is enough (segment check redundant) if we trust function ID'ing anyway.

    f_ea = idaapi.get_func(ea)
    if not f_ea:
        return False

    #Preceding or Previous?
    #	Not necessarily all preceding will be a call to a ret instruction,
    #	but "the" prev should be always the one.
    i = idautils.DecodePreviousInstruction(ea)
    if i and "BL" in idc.GetMnem(i.ea):
        return True

    return False
Esempio n. 30
0
    def run(self):
        self.logger.info('Starting up')
        try:
            here = idc.here()
            self.logger.info('Using ea: 0x%08x', here)

            if not idc.GetMnem(here).startswith('call'):
                self.logger.info(
                    'Not running at a call instruction. Bailing out now')
                return
            if idc.GetOpType(here, 0) == idc.o_near:
                self.logger.info(
                    "Cannot (or shouldn't) run when call optype is o_near")
                return

            dlg = ApplyCalleeTypeWidget()
            oldTo = idaapi.set_script_timeout(0)
            res = dlg.exec_()
            idaapi.set_script_timeout(oldTo)

            if res == QtWidgets.QDialog.Accepted:
                self.logger.debug('Dialog accepted. Input type: %d',
                                  dlg.inputType)
            else:
                self.logger.debug('Dialog rejected')
                return

            tinfo = None
            #check user input type
            if dlg.inputType == dlg.USER_TYPE:
                decl = self.convertUserType(str(dlg.getUserText()))
                tinfo = self.getUserDeclType(decl)
            elif dlg.inputType == dlg.STANDARD_TYPE:
                tinfo = self.getBuiltinGlobalType()
            elif dlg.inputType == dlg.LOCAL_TYPE:
                tinfo = self.getLocalType()
            else:
                self.logger.info('Bad user input type')
                return
            if tinfo is None:
                self.logger.debug('Bailing due to null tinfo')
                return
            #self.logger.info('Deserialize result: %r', ret)
            #not 100% sure if i need to explicitly convert from func to funcptr - seemed
            # to pretty much work without this, but doing it just to be sure
            if not tinfo.is_funcptr():
                self.logger.debug('Converting to func pointer')
                tinfo.create_ptr(tinfo)
            typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, tinfo,
                                          '', '')
            self.logger.info('Applying tinfo: "%s"', str(typename))
            #both applying callee type & setting op type -> not sure if both are needed?
            # set op type causes change in hexrays decompilation
            # apply callee type updates ida's stack analysis
            ret = idaapi.apply_callee_tinfo(here, tinfo)
            ret = idaapi.set_op_tinfo2(here, 0, tinfo)
            self.logger.debug('set_op_tinfo2 result: %r', ret)

        except Exception, err:
            self.logger.exception("Exception caught: %s", str(err))