Ejemplo n.º 1
0
def decrypt_all_strings(decrypt_string_func_ea):
    global STRING_DICTIONARY
    for ref in idautils.CodeRefsTo(decrypt_string_func_ea, 1):
        # this function can be better. I hate it rn but oh well

        prev_instruction_ea = 0x472DAC if ref == translate_ea(
            0x1db3) else idc.prev_head(ref)

        if idc.print_insn_mnem(
                prev_instruction_ea) == 'push' or idc.print_insn_mnem(
                    prev_instruction_ea) == 'lea':
            encrypted_blob_ea = idc.get_operand_value(
                prev_instruction_ea,
                1) if ref == translate_ea(0x1db3) else idc.get_operand_value(
                    prev_instruction_ea, 0)
            length = int.from_bytes(idaapi.get_bytes(encrypted_blob_ea - 4, 4),
                                    'little')
            #print(hex(prev_instruction_ea) + " and " + hex(encrypted_blob_ea) + " and " + hex(length))
            encrypted_blob = [
                x for x in idaapi.get_bytes(encrypted_blob_ea, length)
            ]
            encrypted_blob = decrypt_config(encrypted_blob, length)
            string = ''
            for each in encrypted_blob:
                if each != 0:
                    string += chr(each)
            STRING_DICTIONARY[translate_ea_to_offset(
                encrypted_blob_ea)] = string
    return
def formbook_decrypt_c2c_uri():
    fb_decrypt = FormBookDecryption()

    encbuf6_addr = 0x0041AAA4  # fake prologue
    encbuf7_addr = 0x0041AE45  # fake prologue
    encbuf8_addr = 0x0041AF4C  # fake prologue
    encbuf9_addr = 0x00419A83  # fake prologue

    encbuf7_s0 = idaapi.get_bytes(encbuf7_addr, 0x14 * 2)
    encbuf6_s0 = idaapi.get_bytes(encbuf6_addr, 0x14 * 2)
    encbuf8_s0 = idaapi.get_bytes(encbuf8_addr, 0x139 * 2)
    encbuf9_s0 = idaapi.get_bytes(encbuf9_addr, 0x9d3 * 2)

    rc4_key_two = fb_decrypt.decrypt_func1(encbuf6_s0, 0x14)
    rc4_key_one = fb_decrypt.decrypt_func1(encbuf7_s0, 0x14)
    encbuf8_s1 = fb_decrypt.decrypt_func1(encbuf8_s0, 0x139)
    encbuf9_s1 = fb_decrypt.decrypt_func1(encbuf9_s0, 0x9d3)

    rc4_key = formbook_compute_sha1(encbuf9_s1)
    encbuf8_s2 = fb_decrypt.decrypt_func2(encbuf8_s1, rc4_key)

    encrypted_c2c_uri = encbuf8_s2[220:220+44]  # 44 is the length of the C&C URI
    encrypted_c2c_uri = fb_decrypt.decrypt_func2(encrypted_c2c_uri, rc4_key_two)
    c2c_uri = fb_decrypt.decrypt_func2(encrypted_c2c_uri, rc4_key_one)
    print('C&C URI: {:s}'.format(c2c_uri))
Ejemplo n.º 3
0
def get_FULL_CONFIG():
    global config_extract_ea, FULL_CONFIG

    # get FULL_CONFIG size
    curr_ea = config_extract_ea
    stop_bytes = 0  # this should be 0xDEADBEEF
    FULL_CONFIG_ea = 0

    while True:
        next_instruction_ea = idc.next_head(curr_ea)
        if idc.print_insn_mnem(next_instruction_ea) == 'cmp':
            stop_bytes = idc.get_operand_value(next_instruction_ea, 1)
            break
        elif idc.print_insn_mnem(next_instruction_ea) == 'lea':
            FULL_CONFIG_ea = idc.get_operand_value(next_instruction_ea, 1)
        curr_ea = next_instruction_ea

    config_length = 0

    while True:
        if int.from_bytes(idaapi.get_bytes(FULL_CONFIG_ea + config_length, 4),
                          'little') == stop_bytes:
            break
        config_length += 1

    FULL_CONFIG = [
        each_byte
        for each_byte in idaapi.get_bytes(FULL_CONFIG_ea, config_length)
    ]
    FULL_CONFIG = decrypt_config(FULL_CONFIG, config_length)
Ejemplo n.º 4
0
def formbook_decrypt_hashes_and_strings():
    fb_decrypt = FormBookDecryption()

    # PE base address: 0x00400000
    encbuf1_addr = 0x0041AF4C  # fake prologue
    encbuf2_addr = 0x0041B160  # fake prologue
    encbuf3_addr = 0x0041AAA4  # fake prologue
    encbuf4_addr = 0x00419A83  # fake prologue

    # decrypt_func1 input length buffer is unknown
    # but is always >= output length
    encbuf1_s0 = idaapi.get_bytes(encbuf1_addr, 0x139 * 2)
    encbuf2_s0 = idaapi.get_bytes(encbuf2_addr, 0x35C * 2)
    encbuf3_s0 = idaapi.get_bytes(encbuf3_addr, 0x14 * 2)
    encbuf4_s0 = idaapi.get_bytes(encbuf4_addr, 0x9d3 * 2)

    encbuf1_s1 = fb_decrypt.decrypt_func1(encbuf1_s0, 0x139)
    encbuf2_s1 = fb_decrypt.decrypt_func1(encbuf2_s0, 0x35c)
    encbuf3_s1 = fb_decrypt.decrypt_func1(encbuf3_s0, 0x14)
    encrypted_strings = fb_decrypt.decrypt_func1(encbuf4_s0, 0x9d3)

    rc4_key_one = formbook_compute_sha1(encbuf1_s1)
    rc4_key_two = formbook_compute_sha1(encbuf3_s1)

    encbuf2_s2 = fb_decrypt.decrypt_func2(encbuf2_s1, rc4_key_one)
    encrypted_hashes_array = fb_decrypt.decrypt_func2(encbuf2_s2, rc4_key_two)

    rc4_key_pre_final = formbook_compute_sha1(encrypted_hashes_array)
    rc4_key_final = fb_decrypt.decrypt_func2(encbuf3_s1, rc4_key_pre_final)

    formbook_decrypt_hashes(fb_decrypt, rc4_key_final, encrypted_hashes_array)
    formbook_decrypt_strings(fb_decrypt, rc4_key_final, encrypted_strings)
Ejemplo n.º 5
0
def getStructArg(struct_addr, arg, arg_size=8, size=32):

    print_bytes = idaapi.get_bytes(struct_addr+arg*arg_size, arg_size)
    arg_value = px_qw(struct_addr+arg*arg_size, False)    
    print("Struct Base: 0x%08x -> Arg[%d]: 0x%08x -> Value: 0x%08x" % (struct_addr, arg, 
        struct_addr+arg*arg_size, arg_value))

    print_bytes = idaapi.get_bytes(arg_value, size)
    dump = []
    for b in print_bytes:
        dump.append(ord(b))

    hexdump_raw(arg_value, dump)
Ejemplo n.º 6
0
def decode_callback(eh, address, argv, userData):
    encoded_str_ea = eh.getRegVal('edx')
    ENCRYPTED_STRING_BUFFER = argv[0]
    key_offset = argv[1]
    key_length = argv[2]
    data_length = argv[3]

    RC4_key = idaapi.get_bytes(ENCRYPTED_STRING_BUFFER + key_offset,
                               key_length)
    RC4_encrypted_buffer = idaapi.get_bytes(
        ENCRYPTED_STRING_BUFFER + key_offset + key_length, data_length)
    decrypted_str = RC4_crypt(RC4_key, RC4_encrypted_buffer)
    print(hex(address) + ' ' + decrypted_str)
    eh.analysisHelper.setComment(address, decrypted_str, False)
Ejemplo n.º 7
0
def get_encrypted_lib_table():
    LoadLibraryA_ea = idc.get_name_ea_simple("LoadLibraryA")
    LoadLibraryA_ref = None
    if LoadLibraryA_ea != idaapi.BADADDR:
        for ref in idautils.CodeRefsTo(LoadLibraryA_ea, 1):
            LoadLibraryA_ref = ref
            break
    ENCRYPTED_LIB_TABLE_instruction_ea = LoadLibraryA_ref - 22
    API_TABLE_start_instruction_ea = LoadLibraryA_ref - 16

    if 'lea' not in idc.GetDisasm(
            ENCRYPTED_LIB_TABLE_instruction_ea) or 'lea' not in idc.GetDisasm(
                API_TABLE_start_instruction_ea):
        print(hex(ENCRYPTED_LIB_TABLE_instruction_ea))
        print('Parsing fails...')
        return

    ENCRYPTED_LIB_TABLE_ea = idc.get_operand_value(
        ENCRYPTED_LIB_TABLE_instruction_ea, 1)
    ENCRYPTED_LIB_TABLE_ea -= 4

    global API_TABLE_start_ea
    API_TABLE_start_ea = idc.get_operand_value(API_TABLE_start_instruction_ea,
                                               1)

    global ENCRYPTED_LIB_TABLE
    # 3694 bytes
    ENCRYPTED_LIB_TABLE = idaapi.get_bytes(ENCRYPTED_LIB_TABLE_ea, 3694)
Ejemplo n.º 8
0
  def get_segments_memory(self):
    memory = b""
    step_size = self.entropy_cfg['step_size']
    segments  = OrderedDict()

    for ea in filter(self.segment_filter, idautils.Segments()):
      seg_name = idc.get_segm_name(ea)
      segm  = idaapi.get_segm_by_name(seg_name)
      data = idaapi.get_bytes(segm.start_ea, segm.size())
      assert len(data) == segm.size()

      start_offset = len(memory)
      end_offset   = (start_offset+len(data))

      seg_info = {
        'segm': segm,
        'entropy': entropy(data),
        'offsets': [
          start_offset ,
          end_offset
        ],
        'chart_offsets': [
          start_offset // step_size,
          end_offset // step_size
        ]
      }
      segments[seg_name] = seg_info
      memory += data

    self.data = memory
    self.data_size = len(memory)
    self.segments = segments
Ejemplo n.º 9
0
def formbook_patch_encrypted_bytecode():
    text_segm = ida_segment.get_segm_by_name('.text')
    if not text_segm:
        return idaapi.BADADDR

    seg_start = text_segm.startEA
    seg_end = text_segm.endEA
    fb_decrypt = FormBookDecryption()
    rc4_key = "faddefad156c45629c95d5f429363b0653ad5c1d".decode('hex')  # same as rc4_final from formbook_decrypt_hashes_and_strings()

    for i in [(0x40, 0x48), (0x41, 0x49), (0x42, 0x4a), (0x43, 0x4b), (0x44, 0x4c)]:
        egg_pattern = ''.join('{:02x} '.format(x) for x in [i[0], 0x90, 0x90, 0x90, i[1]])
        encrypted_start = idaapi.find_binary(seg_start, seg_end, egg_pattern, 16, idaapi.SEARCH_DOWN)
        if encrypted_start != idaapi.BADADDR:
            encrypted_end = idaapi.find_binary(encrypted_start + 5, seg_end, "90 90 90 90", 16, idaapi.SEARCH_DOWN)
            if encrypted_end != idaapi.BADADDR:
                encrypted_start += 5
                patch_length = encrypted_end - encrypted_start
                if idaapi.visit_patched_bytes(encrypted_start, encrypted_end, callback_on_patched_bytes) == 0:
                    encrypted_buff = idaapi.get_bytes(encrypted_start, patch_length)
                    decrypted_buff = fb_decrypt.decrypt_func2(encrypted_buff, rc4_key)
                    print('Patching encrypted bytecode at 0x{:x} ({:d} bytes)'.format(encrypted_start, patch_length))
                    idaapi.patch_many_bytes(encrypted_start, decrypted_buff)
                else:
                    print('Encrypted bytecode at 0x{:x} ({:d} bytes) is already patched'.format(encrypted_start, patch_length))
Ejemplo n.º 10
0
Archivo: ida.py Proyecto: w00kong/sdk
def parse_func(pfn):
    try:
        hf = idaapi.hexrays_failure_t()
        cfunc = idaapi.decompile(pfn.start_ea, hf)
        mbr = idaapi.mba_ranges_t(pfn)
        mba = idaapi.gen_microcode(
            mbr,
            hf,
            None,
            idaapi.DECOMP_NO_WAIT | idaapi.DECOMP_NO_CACHE,
            idaapi.MMAT_GLBOPT3
        )
    except Exception:
        return
    if mba is None:
        return

    G = Graph()
    ctree_state, ctree_expr, ctree_int, ctree_str, micro_int = [], [], [], [], []

    # node level
    for i in range(mba.qty):
        mb = mba.get_mblock(i)
        minsn = mb.head
        blk = []
        while minsn:
            ins = parse_minsn(minsn, micro_int)
            blk.append(ins)
            minsn = minsn.next

        vp = idaapi.qstring_printer_t(None, True)
        mb._print(vp)

        G.add_node(mb.serial, feat=blk, raw_data=vp.s)
        for succ in mb.succset:
            G.add_edge(mb.serial, succ)
    G.remove_featempty_nodes()

    if not G.have_nodes():
        return

    # add a fake edge if there is no edge
    if not G.have_edges():
        G.add_edge(G.graph['nodes'][0]['id'], G.graph['nodes'][0]['id'])

    # graph level
    ctree_fea = CtreeFeature(ctree_state, ctree_expr, ctree_int, ctree_str)
    ctree_fea.apply_to(cfunc.body, None)

    G.graph['graph']['c_state'], G.graph['graph']['c_expr'], G.graph['graph']['c_int'], G.graph['graph'][
        'c_str'], G.graph['graph']['m_int'] = ctree_state, ctree_expr, ctree_int, ctree_str, micro_int
    G.graph['graph']['arg_num'] = len(cfunc.argidx)

    func_bytes = b''
    for start, end in idautils.Chunks(pfn.start_ea):
        fb = idaapi.get_bytes(start, end-start)
        func_bytes += fb
    G.graph['graph']['hash'] = hashlib.md5(func_bytes).hexdigest()

    return G.graph
Ejemplo n.º 11
0
    def __init__(self, parent, display, location):
        """initialize item

        details section shows byte preview for match

        @param parent: parent node
        @param display: text to display in UI
        @param location: virtual address as seen by IDA
        """
        byte_snap = idaapi.get_bytes(location, 32)

        if byte_snap:
            byte_snap = codecs.encode(byte_snap, "hex").upper()
            if sys.version_info >= (3, 0):
                details = " ".join([
                    byte_snap[i:i + 2].decode()
                    for i in range(0, len(byte_snap), 2)
                ])
            else:
                details = " ".join(
                    [byte_snap[i:i + 2] for i in range(0, len(byte_snap), 2)])
        else:
            details = ""

        super(CapaExplorerByteViewItem, self).__init__(parent,
                                                       display,
                                                       location=location,
                                                       details=details)
        self.ida_highlight = idc.get_color(location, idc.CIC_ITEM)
Ejemplo n.º 12
0
def get_struct(address, struct_type):
    assert idaapi.is_loaded(
        address) == True, "Can't access memory at 0x%x" % address
    sbytes = idaapi.get_bytes(address, sizeof(struct_type))
    struct = struct_type.from_buffer_copy(sbytes)
    struct._addr = address
    return struct
Ejemplo n.º 13
0
    def __get_real_gp(rom_addr, rom_end):
        # li gp, 0xADDR; move $fp, $sp
        gp_set, _ = masked_search(rom_addr, rom_end, b'\x9C\x27\x21\xF0\xA0\x03', b'\xFF\xFF\xFF\xFF\xFF\xFF')

        if gp_set != idaapi.BADADDR:
            gp_set -= 6

            gp1 = idaapi.get_bytes(gp_set + 0, 2)
            gp2 = idaapi.get_bytes(gp_set + 4, 2)

            new_gp = ((gp1[1] & 0xFF) << 24) | ((gp1[0] & 0xFF) << 16) | ((gp2[1] & 0xFF) << 8) | ((gp2[0] & 0xFF) << 0)
            idaapi.msg("Real GP found at 0x%08X => 0x%08X!\n" % (gp_set, new_gp))

            return new_gp

        return 0
Ejemplo n.º 14
0
 def _sig_bytes(self, addr: int, count: int) -> str:
     """
     Get the bytes for a single instruction without wildcards
     :param addr: Byte start address
     :param count: Number of bytes to get
     :return: A signature
     """
     return ' '.join(f'{b:02X}' for b in idaapi.get_bytes(addr, count))
Ejemplo n.º 15
0
def iterate_vtable(vtable_addr):
    ea = vtable_addr
    while True:
        fn_ea = struct.unpack('<Q', idaapi.get_bytes(ea, 8))[0]
        if idaapi.get_name(fn_ea) != "__cxa_pure_virtual" and not idaapi.is_func(idaapi.get_flags(fn_ea)):
            return
        yield fn_ea
        ea += 8
Ejemplo n.º 16
0
 def get_data(self):
   data = None
   if self.config.use_disk_binary:
     data = get_disk_binary()
   else:
     data_size = self.config.end_addr - self.config.start_addr
     data = idaapi.get_bytes(self.config.start_addr, data_size)
   return data
Ejemplo n.º 17
0
def hexdump(addr, size):
    print_bytes = idaapi.get_bytes(addr, size)
    
    dump = []
    for b in print_bytes:
        dump.append(ord(b))

    hexdump_raw(addr, dump)
Ejemplo n.º 18
0
def handle_string_mov(ea, state):
    """Updates the stack based on a movs instruction.  Used by create_stack
        If a rep/repne prefix is used, takes the count from ecx.  If the count cannot be determined, will ignore
        the instruction.  Also assumes that esi points to memory within the executable, and edi points to the
        stack. On any errors, this will ignore the instruction.

        :param ea: instruction location
        :param state: the current TraceState

        :return: None - updates stack or regs
    """
    opcode = idaapi.get_bytes(ea, 1)
    rep_inst = opcode in [b"\xf2", b"\xf3"]
    count = state.get_reg_value("ecx") if rep_inst else 1
    if not count or count < 0:
        return

    cmd = idaapi.insn_t()
    inslen = idaapi.decode_insn(cmd, ea)
    dtype = cmd.ops[0].dtype
    word_size = [1, 2, 4][dtype] if dtype < 3 else 4
    count *= word_size

    src = state.get_reg_value("esi")
    dst = state.get_reg_value("edi")
    if src is None or dst is None:
        return
    # In IDA 7, get_bytes doesn't return None on failure, instead it will return
    # a string of \xff the size of count. My theory is that the function changed
    # to return -1 for each byte within the c code and something is casting it to a string before returning.
    # Since, all \xff's could be valid we need to check if src is valid instead.
    if not idc.is_loaded(src):
        return
    bytes_ = idaapi.get_bytes(src, count)
    if bytes_ in (
            None,
            -1):  # Keep this around in-case they fix it in a future version.
        return
    for i in range(count):
        state.stack[dst + i] = ((bytes_[i]), ea)

    if rep_inst:
        state.set_reg_value("ecx", 0, ea)
    state.set_reg_value("esi", src + count, ea)
    state.set_reg_value("edi", dst + count, ea)
Ejemplo n.º 19
0
def get_KEY_BUFFER(init_resolve_func_ea):
    global KEY_BUFFER

    if init_resolve_func_ea is None:
        print('get_KEY_BUFFER fails...')
        return None

    print(hex(init_resolve_func_ea))
    ref_ea = None
    for ref in idautils.CodeRefsTo(init_resolve_func_ea, 1):
        # only 1 ref
        ref_ea = ref
        break

    arg_list = [0, 0, 0]

    curr_ea = ref_ea
    for i in range(0, 3):
        while True:
            prev_instruction_ea = idc.prev_head(curr_ea)
            if idc.print_insn_mnem(prev_instruction_ea) == 'push':
                arg_list[i] = idc.get_operand_value(prev_instruction_ea, 0)
                curr_ea = prev_instruction_ea
                break

    key1 = []
    key1_ea = arg_list[0]
    length = arg_list[2]

    while key1_ea < arg_list[0] + length:
        key1.append(int.from_bytes(idaapi.get_bytes(key1_ea, 4), 'little'))

        key1_ea += 4

    key2 = []
    key2_ea = arg_list[1]

    while key2_ea < arg_list[1] + length:
        key2.append(int.from_bytes(idaapi.get_bytes(key2_ea, 1), 'little'))
        key2_ea += 1

    init_resolve_buffer(key1, key2, length)
Ejemplo n.º 20
0
 def StartDump(self):
     # print self.start
     # print self.endorlen
     self.filepath = idaapi.ask_file(1, "*.dump", "save dump file")
     if self.dumptype == 0:
         ea = self.getHexNum(self.start)
         len = self.getHexNum(self.endorlen)
         if not idaapi.is_loaded(ea) or not idaapi.is_loaded(ea + len):
             idaapi.warning("arrary is out of bound")
             return -1
         if len <= 0:
             idaapi.warning("len is <= 0")
             return -1
         print("start read bytes")
         self.Close(0)
         idaapi.show_wait_box("read bytes")
         self.memdata = idaapi.get_bytes(ea, len)
         print("read bytes end")
         #idaapi.hide_wait_box("read end")
         idaapi.hide_wait_box()
     elif self.dumptype == 1:
         ea = self.getHexNum(self.start)
         len = self.getHexNum(self.endorlen) - self.getHexNum(self.start)
         if not idaapi.is_loaded(ea) or not idaapi.is_loaded(ea + len):
             idaapi.warning("arrary is out of bound")
             return -1
         if len <= 0:
             idaapi.warning("len is <= 0")
             return -1
         print("start read bytes")
         self.Close(0)
         idaapi.show_wait_box("read bytes")
         self.memdata = idaapi.get_bytes(ea, len)
         print("read bytes end")
         #idaapi.hide_wait_box("read end")
         idaapi.hide_wait_box()
     fp = open(self.filepath, 'wb')
     fp.write(self.memdata)
     fp.close()
     idaapi.msg("save:" + self.filepath)
     return 1
Ejemplo n.º 21
0
 def generate_yara_rule(self, mode, is_data=False):
     start, end = get_selection()
     size = end - start
     data = idaapi.get_bytes(start, size)
     ins_set, ins_mode = get_arch_info()
     yr_gen = YaraGenerator(mode, ins_set, ins_mode)
     yr_gen.add_chunk(data, offset=start, is_data=is_data)
     rule_obj = yr_gen.generate_rule()
     file_hash = get_input_file_hash()
     rule_obj.metas["hash"] = "\"{}\"".format(file_hash)
     rule = rule_obj.get_rule_string()
     self.dialog = YaraRuleDialog(None, start, end, rule)
     self.dialog.show()
Ejemplo n.º 22
0
def main():

	text_ea = None
	#for some reason SegByName() isn't working for me - maybe an IDA 7 regression?
	for seg in Segments():
		if get_segm_name(seg) == ".text":
			text_ea = seg

	if text_ea is None:
		print "ERROR: Unable to get .text segment!"
		return

	# first find all the functions
	for head in Heads(text_ea, SegEnd(text_ea)):
		func_ea = idaapi.get_func(head)
		if func_ea is None: 
			if idaapi.get_bytes(head, 13) == '\x8b\xff\xe8\x00\x00\x00\x00\x83\xc4\x04\x0f\xff\xf0':
				print  "Unrecognized apicall function at @ 0x%x"%(head)
				MakeFunction(head)

	#now name the functions
	for funcea in Functions(text_ea, SegEnd(text_ea)): 
		functionName = GetFunctionName(funcea)
		for (startea, endea) in Chunks(funcea):
			for head in Heads(startea, endea):

				insnbytes = idaapi.get_bytes(head, 3)

				if insnbytes == '\x0f\xff\xf0': 
					apicrc = idaapi.get_long(head+3)
					apiname = hashesToNames.get(apicrc)
					if apiname is None:
						print "ERROR: apicrc 0x%x NOT FOUND! @ 0x%x"%(apicrc, head)
					else:
						print "PROCESS - apicall: %s @ 0x%x"%(apiname, head)
						func_ea = idaapi.get_func(head).start_ea
						fname = idc.GetFunctionName(func_ea)
						if fname.startswith("sub_"):
							MakeName(func_ea, "apicall_" + apiname) 
    def activate(self, ctx):
        start, end = idc.read_selection_start(), idc.read_selection_end()
        if start == idaapi.BADADDR:
            print 'Please select something'
            return

        import capstone
        md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
        md.details = True
        data = idaapi.get_bytes(start, end - start)
        for insn in md.disasm(data, start):
            # print "0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str)
            idaapi.set_cmt(insn.address, str('%s %s' % (insn.mnemonic, insn.op_str)), False)
Ejemplo n.º 24
0
    def hook(self, hook_addr=0):
        """
        Args:
            hook_addr(int): address for inline hook code, 0 indicates bpt hook.

        Returns:
            memory size in bytes used for inline hook.
        """

        self.hook_addr = hook_addr
        self.func_addr = idc.get_name_ea_simple(self.name)

        if self.func_addr == 0:
            return 0

        print("Hooking %s at 0x%x" % (self.name, self.func_addr))
        if self.hook_addr == 0:
            idc.add_bpt(self.func_addr)
            idc.set_bpt_cond(self.func_addr, self.bpt_cond_hook_code)
            return 0
        else:
            # assemble jmp code
            jmp_code = "jmp 0x%x" % self.hook_addr
            jmp_buf, _ = assemble(jmp_code, self.func_addr)

            # read function prologue according to jmp code length
            # NOTE: instructions like 'call $+5' in prologue will
            # cause problems.
            insn = idaapi.insn_t()
            move_length = 0
            while move_length < len(jmp_buf):
                idaapi.decode_insn(insn, self.func_addr + move_length)
                move_length += insn.size
            prologue = idaapi.get_bytes(self.func_addr, move_length)

            # write jmp code
            idaapi.patch_bytes(self.func_addr, jmp_buf)

            # assmble hook code
            hook_buf, _ = assemble(self.inline_hook_code, self.hook_addr)
            hook_buf += prologue
            jmp_back_code = 'jmp 0x%x' % (self.func_addr + move_length)
            jmp_back_buf, _ = assemble(jmp_back_code,
                                       self.hook_addr + len(hook_buf))
            hook_buf += jmp_back_buf

            # wirte hook code
            idaapi.patch_bytes(self.hook_addr, hook_buf)
            return len(hook_buf)
Ejemplo n.º 25
0
def get_segment_buffer(seg):
    """return bytes stored in a given segment

    decrease buffer size until IDA is able to read bytes from the segment
    """
    buff = b""
    sz = seg.end_ea - seg.start_ea

    while sz > 0:
        buff = idaapi.get_bytes(seg.start_ea, sz)
        if buff:
            break
        sz -= 0x1000

    # IDA returns None if get_bytes fails, so convert for consistent return type
    return buff if buff else b""
Ejemplo n.º 26
0
def getOpcodes(addr, size):
    md = capstone.Cs(capstone.CS_ARCH_X86, CAPSTONE_MODE)
    md.detail = True
    instr_bytes = idaapi.get_bytes(addr, size)
    opcodes_buf = b''
    for i in md.disasm(instr_bytes, size):
        # get last opcode
        if i.opcode[3] != 0:
            opcodes_buf += "%02x" % (i.opcode[3])
        elif i.opcode[2] != 0:
            opcodes_buf += "%02x" % (i.opcode[2])
        elif i.opcode[1] != 0:
            opcodes_buf += "%02x" % (i.opcode[1])
        else:
            opcodes_buf += "%02x" % (i.opcode[0])
    return opcodes_buf
Ejemplo n.º 27
0
    def __init__(self, targetSeg=".text", vmpSeg=".asp0"):
        #Get Segment Info (start, end, size)

        if self.getVmpCallList(targetSeg, vmpSeg) is not True:
            print("Get Call list Fail")
            return

        for x in self.call_list:
            result = self.functionTracer(x)
            if result is False:
                self.fail_list.append(x)
            else:
                self.gadget_list.append(result)
        self.decodeAddress()

        for x in self.call_list:
            #print ""
            result = self.functionDummyTracer(x)
            if result is False:
                self.dummy_fail_list.append(x)
            else:
                self.dummy_patch_list.append(x + 5)
                self.dummy_gadget_list.append(result)
                if idaapi.get_bytes(x + 5, 1) != '\x90':
                    self.dummy_patch_list.append(x + 5)
                    self.dummy_gadget_list.append(result)
                else:
                    self.dummy_patch_list.append(x + 5)
                    self.dummy_gadget_list.append(result)

        print("################### vmp0 Call List ###################")
        self.printCallList()

        print("################### Trace Fail List ###################")
        self.printFailList()

        print("################### Gadget List ###################")
        self.printGadget()

        print("################### Decoded Api List ###################")
        self.printDecodedApi()

        print("################### Decoded Dummy Api List ###################")
        self.printDummyGadget()

        for x in self.dummy_patch_list:
            print hex(x).rstrip('L')
 def __init__(self, inst, isContent=False):
     # type: (int, bool) -> ()
     """
     Loads the content at the specified address inst. if isContent, inst itself is taken as the content
     :param inst: linear address of instuction item, or the content itself
     :param isContent: whether inst is a linear address or content
     :raises ValueError: if the instruction could not be decoded
     """
     if isContent:
         self.inst = inst
     else:
         self.inst = idaapi.get_bytes(inst, 2)
         self.inst = ord(self.inst[0]) + (ord(self.inst[1]) << 8)
         # TODO: if it's a BL, it's 4 bytes, figure that out here
     self.fields = decode(self.inst)
     if self.fields == None:
         raise ValueError('could not decode {:X}'.format(inst))
Ejemplo n.º 29
0
 def visit_expr(self, e):
     if e.op == idaapi.cot_call and \
         e.x.op == idaapi.cot_obj and \
         e.x.obj_ea == self.ea:
         arg = e.a[0]
         # print(f"arg={arg}, arg.op={arg.op}")
         t = idaapi.tinfo_t.get_stock(idaapi.STI_PCHAR)
         if arg.op == idaapi.cot_obj:
             prefix = idaapi.get_bytes(arg.obj_ea, 2)
             # print(prefix)
             if prefix[0] == 1:
                 log_level = chr(prefix[1])
                 idaapi.del_items(arg.obj_ea)
                 arg.obj_ea += 2
             idc.create_strlit(arg.obj_ea, idaapi.BADADDR)
             arg.type = t
             arg.exflags = idaapi.EXFL_CSTR
     return 0
Ejemplo n.º 30
0
def masked_search(start_addr: int, end_addr: int, bytes_data: bytes, masks_data: bytes) -> Tuple[int, Optional[bytes]]:
    def prepare_first_search(bd: bytes, md: bytes) -> bytes:
        bd_str = binascii.hexlify(bd, ' ').split(b' ')
        md_str = binascii.hexlify(md, ' ').split(b' ')

        for ii, md_token in enumerate(md_str):
            if md_token != b'ff':
                bd_str[ii] = b'?'

        bd_str = b' '.join(bd_str)

        return bd_str

    len_bytes = len(bytes_data)

    bytes_data_prep = prepare_first_search(bytes_data, masks_data)

    if idaapi.IDA_SDK_VERSION >= 760:
        patterns = ida_bytes.compiled_binpat_vec_t()
        idaapi.parse_binpat_str(patterns, start_addr, bytes_data_prep.decode(), 16)
        ea = ida_bytes.bin_search(start_addr, end_addr, patterns,
                                  ida_bytes.BIN_SEARCH_FORWARD |
                                  ida_bytes.BIN_SEARCH_NOBREAK |
                                  ida_bytes.BIN_SEARCH_NOSHOW)
    else:
        ea = ida_search.find_binary(start_addr, end_addr, bytes_data_prep.decode(), 16, idaapi.SEARCH_DOWN)

    if ea == idaapi.BADADDR:
        return idaapi.BADADDR, None

    found_bytes = idaapi.get_bytes(ea, len_bytes)

    equal = True
    for i in range(len_bytes):
        m = masks_data[i]
        if found_bytes[i] & m != bytes_data[i] & m:
            equal = False
            break

    if equal:
        return ea, found_bytes

    return idaapi.BADADDR, None