예제 #1
1
    def search_retns(self):

        if not self.debug: print("found %d modules" % len(self.modules))
        for m in self.modules:

            # Iterate over segments in the module
            # BUG: Iterating over all loaded segments is more stable than looking up by address
            if not self.debug: print("found %d segments" % idaapi.get_segm_qty())
            for n in xrange(idaapi.get_segm_qty()):
                seg = idaapi.getnseg(n)

                # Locate executable segments in a selected modules
                # NOTE: Each module may have multiple executable segments
                if seg and seg.startEA >= m.addr and seg.endEA <= (m.addr + m.size):
                    # If the debugger is attached then we can check if the segment is executable, else
                    # just check if it is code or not.
                    if idaapi.dbg_can_query() and idaapi.get_process_state() < 0:
                        if seg.perm & idaapi.SEGPERM_EXEC == 0:
                            continue
                    elif seg.type & idaapi.SEG_CODE == 0:
                        continue

                    #######################################################
                    # Search for ROP gadgets
                    if self.searchRop:

                        #Search all instances of BLR
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "4E 80 00 20", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break

                            self.retns.append((ea, m.file))

                        # Search all instances of BTCTR
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "4E 80 04 20", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break

                            self.retns.append((ea, m.file))

                        # Search all instances of BTCTRL
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "4E 80 04 21", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break

                            self.retns.append((ea, m.file))
예제 #2
0
def msr_parse():
	start = idc.MinEA()
	stop = idc.MaxEA()
	rdmsr_addr = idaapi.find_binary(start, stop, "0F 32", 0, 0) 
	wrmsr_addr = idaapi.find_binary(start, stop, "0F 30", 0, 0)
	cpuid_addr = idaapi.find_binary(start, stop, "0F A2", 0, 0)
	idc.MakeCode(each)
예제 #3
0
def search_ea(sig, segment="", callback=None):
    eas = []
    if segment != "":
        seg = idaapi.get_segm_by_name(segment)
        if not seg:
            return
        ea, maxea = seg.startEA, seg.endEA
        count = 0
        while ea != idaapi.BADADDR:
            ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN)
            if ea != idaapi.BADADDR:
                count = count + 1
                if callback != None:
                    callback(ea)
                else:
                    eas.append(ea)
                ea += 2
    else:
        for seg in Segments():
            ea = SegStart(seg)
            maxea = SegEnd(ea)
            count = 0
            while ea != idaapi.BADADDR:
                ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN)
                if ea != idaapi.BADADDR:
                    count = count + 1
                    if callback != None:
                        callback(ea)
                    else:
                        eas.append(ea)
                    ea += 2
    return eas
예제 #4
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))
예제 #5
0
def findGoPcLn():
    possible_loc = idaapi.find_binary(0, idc.BADADDR, lookup, 16,
                                      idc.SEARCH_DOWN)  #header of gopclntab
    while possible_loc != idc.BADADDR:
        if check_is_gopclntab(possible_loc):
            return possible_loc
        else:
            #keep searching till we reach end of binary
            possible_loc = idaapi.find_binary(possible_loc + 1, idc.BADADDR,
                                              lookup, 16, idc.SEARCH_DOWN)
    return None
예제 #6
0
파일: helpers.py 프로젝트: walt1998/capa
def find_byte_sequence(start, end, seq):
    """ find byte sequence

        args:
            start: min virtual address
            end: max virtual address
            seq: bytes to search e.g. b'\x01\x03'
    """
    if sys.version_info[0] >= 3:
        return idaapi.find_binary(start, end, " ".join(["%02x" % b for b in seq]), 0, idaapi.SEARCH_DOWN)
    else:
        return idaapi.find_binary(start, end, " ".join(["%02x" % ord(b) for b in seq]), 0, idaapi.SEARCH_DOWN)
예제 #7
0
def find_all_pattern(pat):
    first = idc.FirstSeg()
    last = idc.BADADDR
    result = []

    ea = idaapi.find_binary(first, last, pat, 16, idaapi.SEARCH_DOWN)
    while ea != idaapi.BADADDR and ea < last:
        result.append(ea)
        ea = idaapi.find_binary(ea, last, pat, 16,
                                idaapi.SEARCH_DOWN | idaapi.SEARCH_NEXT)

    return result
예제 #8
0
def process_func_for_string(str, f):
    loc = idaapi.find_binary(0, idc.BADADDR, "\"%s" % str, 16, 0)
    if loc == idc.BADADDR:
        print "String '%s' not found" % str
        return False
    xrEa = 0
    for xr in idautils.XrefsTo(loc):
        xrEa = xr.frm
        break
    if xrEa == 0:
        print "No xrefs to string '%s'" % str
        return False

    fn = idaapi.get_func(xrEa)

    if not fn:
        print "No function at xref to string '%s' (at %x)" % (str, xrEa)
        return False

    fnEa = fn.startEA

    if isThumb(fnEa):
        fnEa += 1

    if f:
        f.write("\t// %s\n" % str)
        f.write("\t{0x%x, 0x%x, 0x%x},\n" % (loc, xrEa, fnEa))

    print "// %s" % str
    print "{0x%x, 0x%x, 0x%x}," % (loc, xrEa, fnEa)

    return True
예제 #9
0
def chendo(address, end, search, struct):
    
    while address < end:
        address = idaapi.find_binary(address, end, search, 0x10, SEARCH_DOWN)
        idaapi.do_unknown_range(address, 0xB0, 0)
        idaapi.create_struct(address, 0xB0, struct)
        address += 0x8
예제 #10
0
def ports_analisys():
	ports_struc = idc.AddEnum(-1, "ports", (FF_WRD|FF_DATA))
	idc.AddConstEx(ports_struc, "PCI_CONFIG_ADDRESS", PCI_CONFIG_ADDRESS, -1)
	idc.AddConstEx(ports_struc, "PCI_CONFIG_DATA", PCI_CONFIG_DATA, -1)

	for each in idaapi.find_binary(start, stop, "", 0, 0): # find_binary(ea_t startea, ea_t endea, char ubinstr, int radix, int sflag) -> ea_t
		idc.MakeCode(each)
예제 #11
0
def kiwidog(address, end, search):
    
    magic = idaapi.find_binary(address, end, search, 0x0, SEARCH_DOWN)
    function = idaapi.get_func(idaapi.get_first_dref_to(magic))
    idaapi.set_name(function.start_ea, '__stack_chk_fail', SN_NOCHECK | SN_NOWARN)
    function.flags |= FUNC_NORET
    idaapi.update_func(function)
예제 #12
0
def process_func_for_string(str, f):
    loc = idaapi.find_binary(0, idc.BADADDR, "\"%s" % str, 16, 0)
    if loc == idc.BADADDR:
        print "String '%s' not found" % str
        return False
    xrEa = 0
    for xr in idautils.XrefsTo(loc):
        xrEa = xr.frm
        break
    if xrEa == 0:
        print "No xrefs to string '%s'" % str
        return False
    
    fn = idaapi.get_func(xrEa)

    if not fn:
        print "No function at xref to string '%s' (at %x)" % (str, xrEa)
        return False

    fnEa = fn.startEA

    if isThumb(fnEa):
        fnEa += 1

    if f:
        f.write("\t// %s\n" % str)
        f.write("\t{0x%x, 0x%x, 0x%x},\n" % (loc, xrEa, fnEa))

    print "// %s" % str
    print "{0x%x, 0x%x, 0x%x}," % (loc, xrEa, fnEa)
    
    return True
예제 #13
0
def create_runtime_ms():
    debug('Attempting to find runtime_morestack function for hooking on...')

    text_seg = get_text_seg()
    if text_seg is None:
        debug('Failed to get text segment')
        return None

    #   Opcodes for "mov     large dword ptr ds:1003h, 0", binary search is faster than text search
    opcodes = 'c7 05 03 10 00 00 00 00 00 00'
    if idaapi.get_inf_structure().is_64bit():
        #   Opcodes for "mov     qword ptr ds:dword_1000+3, 0"
        opcodes = '48 c7 04 25 03 10 00 00 00 00 00 00'

    runtime_ms_end = idaapi.find_binary(text_seg.startEA, text_seg.endEA,
                                        opcodes, 0, SEARCH_DOWN)
    if runtime_ms_end == BADADDR:
        debug('Failed to find opcodes associated with runtime_morestack: %s' %
              opcodes)
        return None

    runtime_ms = idaapi.get_func(runtime_ms_end)
    if runtime_ms is None:
        debug('Failed to get runtime_morestack function from address @ 0x%x' %
              runtime_ms_end)
        return None

    if idc.MakeNameEx(runtime_ms.startEA, "runtime_morestack", SN_PUBLIC):
        debug('Successfully found runtime_morestack')
    else:
        debug('Failed to rename function @ 0x%x to runtime_morestack' %
              runtime_ms.startEA)

    return runtime_ms
예제 #14
0
def znullptr(address, end, search, struct):

    magic = idaapi.find_binary(address, end, search, 0x10, idc.SEARCH_DOWN)
    pattern = '%02X %02X %02X %02X FF FF FF FF' % (magic & 0xFF,
                                                   ((magic >> 0x8) & 0xFF),
                                                   ((magic >> 0x10) & 0xFF),
                                                   ((magic >> 0x18) & 0xFF))

    sysvec = idaapi.find_binary(address, cvar.inf.maxEA, pattern, 0x10,
                                idc.SEARCH_UP) - 0x60
    idaapi.set_name(sysvec, 'sysentvec', SN_NOCHECK | SN_NOWARN | SN_FORCE)

    sysent = idaapi.get_qword(sysvec + 0x8)
    idaapi.set_name(sysent, 'sv_table', SN_NOCHECK | SN_NOWARN | SN_FORCE)

    sysnames = idaapi.get_qword(sysvec + 0xD0)
    idaapi.set_name(sysnames, 'sv_syscallnames',
                    SN_NOCHECK | SN_NOWARN | SN_FORCE)

    # Get the list of syscalls
    offset = idaapi.find_binary(address, cvar.inf.maxEA,
                                '73 79 73 63 61 6C 6C 00 65 78 69 74 00', 0x10,
                                SEARCH_DOWN)

    numsyscalls = idaapi.get_qword(sysvec)
    for entry in xrange(numsyscalls):
        initial = sysnames + (entry * 0x8)
        idc.create_data(initial, FF_QWORD, 0x8, BADNODE)
        offset = idaapi.get_qword(initial)

        length = idaapi.get_max_strlit_length(offset, STRTYPE_C)
        name = idaapi.get_strlit_contents(offset, length, STRTYPE_C)

        sysentoffset = sysent + 0x8 + (entry * 0x30)
        idaapi.do_unknown_range(sysentoffset - 0x8, 0x30, 0)
        idaapi.create_struct(sysentoffset - 0x8, 0x30, struct)
        idc.set_cmt(sysentoffset - 0x8, '#%i' % entry, False)

        if '{' in name:
            continue

        # Rename the functions
        function = idaapi.get_qword(sysentoffset)
        idaapi.set_name(function, name.replace('#', 'sys_'),
                        SN_NOCHECK | SN_NOWARN | SN_FORCE)
예제 #15
0
def function_search(mode, search, address=0):

    while address < BADADDR:
        address = ida.find_binary(address, BADADDR, search, 0x10, SEARCH_DOWN)
        if address < BADADDR:
            address += mode
            ida.do_unknown(address, 0)
            ida.add_func(address, BADADDR)
            address += 1
예제 #16
0
def Binaries(*args):
    """
    Enumerate binary search matches

    @param <range>: see getrange
    @param searchstr:
    @param flags:        for instance SEARCH_CASE

    @return: list of addresses matching searchstr

    Example::

        sysenum= GetEnum("enum_syscalls")
        for ea in Binaries((FirstSeg(), BADADDR), "00 00 00 ef"):
           insn= DecodePreviousInstruction(ea)
           if insn.itype==idaapi.ARM_mov and insn.Op1.is_reg(7) and insn.Op2.type==o_imm:
               OpEnumEx(insn.ea, 1, sysenum, 0)
               if Dword(insn.ea-4)==0xe92d0090 and Dword(insn.ea+8)==0xe8bd0090:
                    syscall= GetConstName(GetConst(sysenum, insn.Op2.value, 0))
                    if syscall:
                        MakeName(insn.ea-4, "syscall_%s" % syscall[4:])
                    else:
                        print "unknown syscall number: %08x" % insn.Op2.value

    This will name all syscall stubs in an android binary.
    Assumes a enum exists with all syscall numbers

    """
    (first, last) = getrange(args)
    i = getstringpos(args)
    if i < 0:
        raise Exception("missing searchstring")

    searchstr = args[i]
    flags = args[i + 1] if i + 1 < len(args) else 0

    ea = idaapi.find_binary(first, last, searchstr, 16,
                            idaapi.SEARCH_DOWN | flags)
    while ea != idaapi.BADADDR and ea < last:
        yield ea
        ea = idaapi.find_binary(
            ea, last, searchstr, 16,
            idaapi.SEARCH_DOWN | idaapi.SEARCH_NEXT | flags)
예제 #17
0
def search_binary(binary_string):
    for i in range(idaapi.get_segm_qty()):
        segm = idaapi.getnseg(i)
        current_ea = segm.startEA
        while True:
            current_ea = idaapi.find_binary(current_ea + 1, segm.endEA, binary_string, 16, idaapi.SEARCH_DOWN)
            if current_ea == idaapi.BADADDR:
                break
            return current_ea
    return 0
예제 #18
0
def find_sig(segment, sig, callback):
    seg = idaapi.get_segm_by_name(segment)
    if not seg:
        return
    ea, maxea = seg.start_ea, seg.end_ea
    while ea != idaapi.BADADDR:
        ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN)
        if ea != idaapi.BADADDR:
            callback(ea)
            ea += 4
예제 #19
0
def Pablo(address, end):

    while address < end:
        offset = idaapi.find_binary(address, end, '?? FF FF FF FF', 0x10,
                                    SEARCH_DOWN)
        offset -= 0x3

        if idaapi.is_unknown(idaapi.get_flags(offset)):
            if text.start_ea <= idaapi.get_qword(offset) <= abs.end_ea:
                idaapi.create_data(offset, FF_QWORD, 0x8, BADNODE)

        address = offset + 0x4
def search_binary(binary_string):
    for i in range(idaapi.get_segm_qty()):
        segm = idaapi.getnseg(i)
        current_ea = segm.startEA
        while True:
            current_ea = idaapi.find_binary(current_ea + 1, segm.endEA,
                                            binary_string, 16,
                                            idaapi.SEARCH_DOWN)
            if current_ea == idaapi.BADADDR:
                break
            return current_ea
    return 0
예제 #21
0
def Binaries(*args):
    """
    Enumerate binary search matches

    @param <range>: see getrange
    @param searchstr:

    @return: list of addresses matching searchstr

    Example::

        sysenum= GetEnum("enum_syscalls")
        for ea in Binaries(FirstSeg(), BADADDR, "00 00 00 ef"):
           insn= DecodePreviousInstruction(ea)
           if insn.itype==idaapi.ARM_mov and insn.Op1.is_reg(7) and insn.Op2.type==o_imm:
               OpEnumEx(insn.ea, 1, sysenum, 0)
               if Dword(insn.ea-4)==0xe92d0090 and Dword(insn.ea+8)==0xe8bd0090:
                    syscall= GetConstName(GetConst(sysenum, insn.Op2.value, 0))
                    if syscall:
                        MakeName(insn.ea-4, "syscall_%s" % syscall[4:])
                    else:
                        print "unknown syscall number: %08x" % insn.Op2.value

    This will name all syscall stubs in an android binary.
    Assumes a enum exists with all syscall numbers

    """
    (first, last)= getrange(args)
    i= getstringpos(args)
    if i<0:
        raise Exception("missing searchstring")

    searchstr= args[i]

    ea= idaapi.find_binary(first, last, searchstr, 16, idaapi.SEARCH_DOWN)
    while ea!=idaapi.BADADDR and ea<last:
        yield ea
        ea= idaapi.find_binary(ea, last, searchstr, 16, idaapi.SEARCH_DOWN|idaapi.SEARCH_NEXT)
예제 #22
0
파일: helpers.py 프로젝트: th14g0d3v/capa
def find_byte_sequence(start, end, seq):
    """yield all ea of a given byte sequence

    args:
        start: min virtual address
        end: max virtual address
        seq: bytes to search e.g. b"\x01\x03"
    """
    seq = " ".join(["%02x" % b for b in seq])
    while True:
        ea = idaapi.find_binary(start, end, seq, 0, idaapi.SEARCH_DOWN)
        if ea == idaapi.BADADDR:
            break
        start = ea + 1
        yield ea
예제 #23
0
파일: decv.py 프로젝트: DogBitesMe/decv
def find_bytes(start, end, seq, seq_len):
    hits = []

    while start < end-seq_len:

        hit_ea = idaapi.find_binary(start, end, seq, 16, idaapi.BIN_SEARCH_FORWARD)
        
        if hit_ea == idaapi.BADADDR:
            break
        
        start = hit_ea+seq_len
        
        #if idaapi.isCode(idc.GetFlags(hit_ea)):
        #    hits.append(hit_ea)
           
        hits.append(hit_ea)

    return hits
예제 #24
0
def pci_analisys():
	# searching snippets:
	# ------------------- 
	# mov eax, 8000xxxxh ; optional line
	# mov dx, CF8h
	# out dx, eax
	# -------------------
	# mov dx, CF8h
	# mov eax, 8000xxxxh
	# out dx, eax
	# -------------------
	position_start = idc.MinEA()
	position_stop = idc.MaxEA()
	outdxeax = position_start
	while outdxeax :
		outdxeax = idaapi.find_binary(position_start, position_stop, "66 EF", 0, 0)
		if outdxeax:
			position_start = outdxeax + 1
예제 #25
0
파일: decv.py 프로젝트: sourav-txt/decv
def find_bytes(start, end, seq, seq_len):
    hits = []

    while start < end - seq_len:

        hit_ea = idaapi.find_binary(start, end, seq, 16,
                                    idaapi.BIN_SEARCH_FORWARD)

        if hit_ea == idaapi.BADADDR:
            break

        start = hit_ea + seq_len

        #if idaapi.isCode(idc.GetFlags(hit_ea)):
        #    hits.append(hit_ea)

        hits.append(hit_ea)

    return hits
예제 #26
0
def pablo(address, end, search):
    
    while address < end:
        address = idaapi.find_binary(address, end, search, 0x10, SEARCH_DOWN)
        
        if address > idaapi.get_segm_by_name('CODE').end_ea:
            offset = address - 0x3
            
            if idaapi.isUnknown(idaapi.getFlags(offset)):
                if idaapi.get_qword(offset) <= end:
                    idaapi.create_data(offset, FF_QWORD, 0x8, BADNODE)
            
            address = offset + 4
        
        else:
            idaapi.do_unknown(address, 0)
            idaapi.create_insn(address)
            idaapi.add_func(address, BADADDR)
            address += 4
예제 #27
0
def find_sig(next_seg, pat, dump_cb):
    """
    Scan binary image for pattern and run dump callback function.

    @param next_seg:   Start address
    @param pat:        Dict with config
    @param dump_cb:    Certificate dump callback
    """
    ea = SegStart(next_seg)
    seg_end = SegEnd(next_seg)
    Message('Searching for %s\n' % pat['name'])
    #    Message('Current Seg %s\n' % SegName(next_seg))
    while next_seg != BADADDR:
        ea = idaapi.find_binary(ea, seg_end, pat['sig'], 16, 1)
        if ea != BADADDR:
            ea = dump_cb(ea, pat)
        else:
            next_seg = ea = NextSeg(seg_end)
            seg_end = SegEnd(next_seg)
예제 #28
0
파일: getkeys.py 프로젝트: 51mple/ctf-1
def find_sig(next_seg, pat, dump_cb):
    """
    Scan binary image for pattern and run dump callback function.

    @param next_seg:   Start address
    @param pat:        Dict with config
    @param dump_cb:    Certificate dump callback
    """
    ea = SegStart(next_seg)
    seg_end = SegEnd(next_seg)
    Message('Searching for %s\n' % pat['name'])
#    Message('Current Seg %s\n' % SegName(next_seg))
    while next_seg != BADADDR:
        ea = idaapi.find_binary(ea, seg_end, pat['sig'], 16, 1)
        if ea != BADADDR:
            ea = dump_cb(ea, pat)
        else:
            next_seg = ea = NextSeg(seg_end)
            seg_end = SegEnd(next_seg)
예제 #29
0
def load_file(f, neflags, format):
    
    print('# PS3 Syscon Loader')
    
    # PS3 Syscon Processor and Library
    processor('arm', 'gnulnx_arm')
    
    print('# Creating ROM Segment...')
    address = 0x0
    end = address + f.size()
    
    f.file2base(address, address, end, FILEREG_PATCHABLE)
    idaapi.add_segm(0x0, address, end, 'ROM', 'CODE', 0x0)
    
    # Processor Specific Segment Details
    idc.set_segm_addressing(address, 0x1)
    idc.set_segm_alignment(address, saAbs)
    idc.set_segm_combination(address, scPriv)
    idc.set_segm_attr(address, SEGATTR_PERM, SEGPERM_MAXVAL)
    idc.set_default_sreg_value(address, 'T', 0x0)
    idc.set_default_sreg_value(address, 'DS', 0x1)
    
    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()
    
    # Create some missing functions...
    while address < end:
        address = idaapi.find_binary(address, end, '?? B5', 0x10, SEARCH_DOWN)
        
        idaapi.create_insn(address)
        
        # Pablo escobar
        if idc.print_insn_mnem(address + 2) in ['LDR', 'MOVS', 'SUB']:
            idc.add_func(address)
        else:
            idaapi.do_unknown(address)
        
        address += 4
    
    print('# Done!')
    return 1

# PROGRAM END
예제 #30
0
def search_dll_hashes(db):
    '''
    Search for DLL hashes
    '''
    # Get information about the .text section
    text_segm = ida_segment.get_segm_by_name('.text')
    seg_start = text_segm.startEA
    seg_end = text_segm.endEA

    # Iter over dll names
    for (dll, funcs) in db.items():
        print("Searching for the {} DLL".format(dll))
        new_hash = sdbm_hash(dll)

        #search for hashes
        ea = idaapi.find_binary(seg_start, seg_end, "0x{:08X}".format(new_hash), 16, SEARCH_DOWN)
        if ea != BADADDR:
            inst_ea = PrevHead(ea) 
            print("Match the hash: {:X} which is the DLL {}, match: 0x{:X}".format(new_hash, dll, inst_ea))
            MakeComm(inst_ea, "{}".format(dll))
예제 #31
0
    def search_sys_gadgets(self, segment, jump_preamble = 0xFF):
        """ Search for SYS jump gadgets """

        # Nothing to do if the option is not set
        if not self.searchSys:
            return

        # Search all instances of JMP reg (FF /4) and CALL reg (FF /2)
        ea = segment.startEA
        while True:

            ea = idaapi.find_binary(ea + 1, segment.endEA, "%X" % jump_preamble, 16, idaapi.SEARCH_DOWN)
            if ea == idaapi.BADADDR: 
                break

            # Read possible ModR/M, SIB, and IMM8/IMM32 bytes
            sys_op = idc.GetManyBytes(ea + 1, self.maxRopSize)

            if self.is_sys_gadget(jop):
                self.retns.append((ea))
예제 #32
0
    def search_rop_gadgets(self, segment, ret_preamble = 0xc3):
        """ Search for rop gadgets """

        # Nothing to do if the option is not set
        if not self.searchRop:
            return
            
        ea = segment.startEA
        while True:

            ea = idaapi.find_binary(ea + 1, segment.endEA, "%X" % ret_preamble, 16, idaapi.SEARCH_DOWN)
            if ea == idaapi.BADADDR: 
                break

            if ret_preamble in [ 0xc2, 0xca, 0xf2c2]:

                 # Read imm16 value and filter large values
                retn_imm16 = idc.Word(ea + 1)
                if retn_imm16 <= self.maxRetnImm:
                    self.retns.append((ea))
            else:
                self.retns.append( (ea))
예제 #33
0
def search_hashes(db, args):
    '''
    Resolution of the API

    Arguments:
      - db (dict): database generated by shellcode_hash
      - args (dict): call arguments 
    '''
    # Get information about the .text section
    text_segm = ida_segment.get_segm_by_name('.text')
    seg_start = text_segm.startEA
    seg_end = text_segm.endEA

    # Iter over the sdbm hashes generated by shellcode_hash
    for (dll, funcs) in db.items():
        print("Searching for functions inside the {} DLL".format(dll))

        for func, hash in funcs:
            new_hash = xor_hash(hash, args["key"])

            #search for hashes
            ea = idaapi.find_binary(seg_start, seg_end, "0x{:08X}".format(new_hash), 16, SEARCH_DOWN)
            if ea != BADADDR:
                # Add comment
                inst_ea = PrevHead(ea) 
                print("Match the hash: {:X} which is the function {}!{} matches: 0x{:X}".format(new_hash, dll, func, inst_ea))
                MakeComm(inst_ea, "{}!{}".format(dll, func))

                # Fix variable name in the function array
                off = (GetOperandValue(inst_ea, 0) ^ 0xffffffff) + 1
                array_off = (args['size'] * 4) - off
                array_va = args['array'] + array_off
                MakeDword(array_va)

                if not MakeName(array_va, "{}".format(func)):
                    MakeName(array_va, "{}_{}".format(dll, func))
                print("Fix the name at 0x{:08X}".format(array_va))
예제 #34
0
	else :
		print "Certs processing fail!"

	# TODO: Parse rights of the keys
	# TODO: Parse ASN1 from digests

	# Processing Images
	i = 0
	while i < 4 :
		print "images type %s " % type (certppa.images)
		if certppa.images[i].image_offset != 0 :
			print "Found PPA image at %x offset " % certppa.images[i].image_offset
		if certisw.images[i].image_offset != 0 :
			print "Found ISW image at %x offset " % certisw.images[i].image_offset
		i += 1

	# image start at certppa mark address + certppa.images[i].image_offset


# Script body

start = idc.MinEA()
stop = idc.MaxEA()
version_addr = idaapi.find_binary(start, stop, "43 65 72 74 49 53 57 00", 0, 0) + 0x79e # "CertISW" string
version_minor = idaapi.get_byte(version_addr)
version_major = idaapi.get_byte(version_addr + 1)
print "MBM loader Major Version: %x " % version_major
print "MBM loader Minor Version: %x " % version_minor
parse_structures()

예제 #35
0
def parse_structures():
	
	# Searching structures, and if not exists - creating them

	# RSA KEY structure

	rsa_key = idc.GetStrucIdByName("rsa_key")
	rsa_key_str = """ struct rsa_key {
								long key_id;
								long key_type;
								long key_rights;
								long modul_length;
								long e_value;
								char modul[256];
							  }; """
	if rsa_key == -1:
		rsa_key = idc.AddStrucEx(-1, "rsa_key", 0)
		idc.AddStrucMember(rsa_key, "key_id", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_key, "key_type", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_key, "key_rights", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_key, "modul_length", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_key, "e_value", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_key, "modul", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 256)
	
	# RSA ASN1 DIGEST structure

	rsa_asn1_digest = idc.GetStrucIdByName("rsa_asn1_digest")
	rsa_asn1_digest_str = """ struct rsa_asn1_digest {
									char signer_info[16];
									long signature_info;
									long key_id;
									char digest[256];
							  }; """
	if rsa_asn1_digest == -1:
		rsa_asn1_digest = idc.AddStrucEx(-1, "rsa_asn1_digest", 0)
		idc.AddStrucMember(rsa_asn1_digest, "signer_info", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 16)
		idc.AddStrucMember(rsa_asn1_digest, "signature_info", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_asn1_digest, "key_id", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(rsa_asn1_digest, "digest", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 256)
	
	# Cert PK - Public Keys structure

	certpk_struct = idc.GetStrucIdByName("Cert_Public")
	certpk_str = """ struct certpk {
						char cert_mark[8];
						long cert_version;
						long cert_type;
						long minver_pk;
						long minver_ppa;
						long minver_rd1;
						long minver_rd2;
						long minver_isw;
						long minver_ki;
						long minver_pau;
						long minver_pas;
						long unkn1;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} root_key;
						long keys_active;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_02;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_03;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_04;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_05;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_06;
						struct {
							long key_id;
							long key_type;
							long key_rights;
							long modul_length;
							long e_value;
							char modul[256];
						} key_07;
						long rights;
						long msv_mask;
						char zero_hole_2[120];
						struct {
							char signer_info[16];
							long signature_info;
							long key_id;
							char digest[256];
						} digest;
					};"""
	if certpk_struct == -1:
		certpk_struct = idc.AddStrucEx(-1, "Cert_Public", 0)
		idc.AddStrucMember(certpk_struct, "cert_mark", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 8)
		idc.AddStrucMember(certpk_struct, "cert_version", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "cert_type", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_pk", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_ppa", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_rd1", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_rd2", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_isw", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_ki", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_pau", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "minver_pas", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "unkn1", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "root_key", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "keys_active", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "key_02", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "key_03", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "key_04", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "key_05", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "key_06", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "key_07", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key))
		idc.AddStrucMember(certpk_struct, "rights", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "msv_mask", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certpk_struct, "zero_hole_2", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 120)
		idc.AddStrucMember(certpk_struct, "digest", -1, 0x60000400, rsa_asn1_digest, idc.GetStrucSize(rsa_asn1_digest))
	
	# CertPPA - Primary Protected Application Certificate structure

	certppa_struct = idc.GetStrucIdByName("Cert_Primary")
	certppa_str = """ struct certppa {
							char cert_mark[8];
							long cert_version;
							long cert_type;
							long minver_src;
							long minver_pk;
							long minver_ppa;
							long minver_rd1;
							long minver_rd2;
							long minver_isw;
							struct {
								int image_offset;
								int image_size;
								int data_byte[5];
							} images[4];
							char zero_hole[128];
							struct {
								char signer_info[16];
								long signature_info;
								long key_id;
								char digest[256];
							} digest;
						};"""
	if certppa_struct == -1:
		certppa_struct = idc.AddStrucEx(-1, "Cert_Primary", 0)
		idc.AddStrucMember(certppa_struct, "cert_mark", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 8)
		idc.AddStrucMember(certppa_struct, "cert_version", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "cert_type", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_src", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_pk", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_ppa", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_rd1", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_rd2", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "minver_isw", -1, (FF_DWRD|FF_DATA)&0xFFFFFFFF, -1, 4)
		idc.AddStrucMember(certppa_struct, "images", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 21)
		idc.AddStrucMember(certppa_struct, "zero_hole", -1, (FF_BYTE|FF_DATA)&0xFFFFFFFF, -1, 128)
		idc.AddStrucMember(certppa_struct, "digest", -1, 0x60000400, rsa_asn1_digest, idc.GetStrucSize(rsa_asn1_digest))

	# CertISW - Initial Software Certificate structure

	certisw_struct = idc.GetStrucIdByName("Cert_ISW")
	certisw_str = """struct certisw {
							char cert_mark[8];
							int cert_version;
							int cert_type;
							int minver_src;
							int minver_pk;
							int minver_ppa;
							int minver_rd1;
							int minver_rd2;
							int minver_isw;
							int watchdog_param;
							int use_DMA;
							int active_images;
							struct {
								int image_offset;
								int image_size;
								int data_byte[5];
							} images[4];
							int magic_1;
							int reg_bitfield;
							struct {
								int reg_address;
								int reg_value;
							} reg_table[32];
							int reg_type_01;
							int reg_type_02;
							int entry_point_offset;
							int zero_hole[32];
							struct {
								char signer_info[16];
								long signature_info;
								long key_id;
								char digest[256];
							} digest;
					};"""

	mbmloader_hdr_str = """struct mbmloader_head {
								void *entry_point;
								int anonymous_0;
								void *anonymous_1;
								void *anonymous_2;
								void *anonymous_3;
								void *anonymous_4;
								int anonymous_5;
								int field_1C;
								void *anonymous_7;
								int field_24;
								void *anonymous_8;
								int anonymous_9;
								int ruler[4];
								char srk_part_1[128];
								int srk_1;
								void *srk_1_pointer;
								int field_C8;
								int field_CC;
								char srk_part_2[128];
								int srk_2;
								void *srk_2_pointer;
								int field_158;
								int field_15C;
								char sha_160_hash[20];
						};"""

	# Searching main structures marks

	start = idc.MinEA()
	stop = idc.MaxEA()
	certpk_addr = idaapi.find_binary(start, stop, "43 65 72 74 50 4B 5F 00", 0, 0) # "CertPK_" string
	print "Found CertPK at 0x%x" % certpk_addr
	certppa_addr = idaapi.find_binary(start, stop, "43 65 72 74 50 50 41 00", 0, 0) # "CertPPA" string
	print "Found CertPPA at 0x%x" % certppa_addr
	certisw_addr = idaapi.find_binary(start, stop, "43 65 72 74 49 53 57 00", 0, 0) # "CertISW" string
	print "Found CertISW at 0x%x" % certisw_addr

	# Apply structure types on Cert* addresses

	# Read Structures from such data

	# If type is not parsed already, then...
	if idc.ParseTypes("certpk;", idc.PT_SILENT) != 0:
		# ...define the type
		idc.ParseTypes(certpk_str, idc.PT_SILENT)
	
	if idc.ParseTypes("certppa;", idc.PT_SILENT) != 0:
		idc.ParseTypes(certppa_str, idc.PT_SILENT)

	if idc.ParseTypes("certisw;", idc.PT_SILENT) != 0:
		idc.ParseTypes(certisw_str, idc.PT_SILENT)

	certpk_ = idaapi.Appcall.typedobj("certpk;")
	certpk_read, certpk = certpk_.retrieve(idaapi.get_many_bytes(certpk_addr, certpk_.size))

	certppa_ = idaapi.Appcall.typedobj("certppa;")
	certppa_read, certppa = certppa_.retrieve(idaapi.get_many_bytes(certppa_addr, certppa_.size))

	certisw_ = idaapi.Appcall.typedobj("certisw;")
	certisw_read, certisw = certisw_.retrieve(idaapi.get_many_bytes(certisw_addr, certisw_.size))

	# Make PEM keys
	if certpk_read == 1 :
		root_key = construct_public_key(certpk.root_key.e_value, int(certpk.root_key.modul[0:certpk.root_key.modul_length].encode("hex"), 16), certpk.root_key.modul_length * 8)
		root_key.save_key("root_key.pem")

		# TODO: add automatic export of all ACTIVE keys from certpk.active_keys
		pk_02 = construct_public_key(certpk.key_02.e_value, int(certpk.key_02.modul[0:certpk.key_02.modul_length].encode("hex"), 16), certpk.key_02.modul_length * 8)
		pk_02.save_key("pk_02.pem")
		pk_03 = construct_public_key(certpk.key_03.e_value, int(certpk.key_03.modul[0:certpk.key_03.modul_length].encode("hex"), 16), certpk.key_03.modul_length * 8)
		pk_03.save_key("pk_03.pem")
		pk_04 = construct_public_key(certpk.key_04.e_value, int(certpk.key_04.modul[0:certpk.key_04.modul_length].encode("hex"), 16), certpk.key_04.modul_length * 8)
		pk_04.save_key("pk_04.pem")
	else :
		print "CertPK read fail!"
	
	# Verify digests
	if (certpk_read == 1) & (certppa_read == 1) & (certisw_read == 1) :
		certpk_digest =  certpk.digest.digest.encode("hex")
		certppa_digest = certppa.digest.digest.encode("hex")
		certisw_digest = certisw.digest.digest.encode("hex")
		# pk_03.public_decrypt(certisw_digest, 1)
		# pk_03.verify(idaapi.get_many_bytes(certisw_addr, certisw_.size), certisw_digest, "sha1")
		# decoder.decode(certpk.digest.signer_info, )
		print "CertPK signer info: %s " % certpk.digest.signer_info.encode("hex")
		print "CertPK digest: %s " % certpk.digest.digest.encode("hex")
		print "CertPPA signer info: %s " % certppa.digest.signer_info.encode("hex")
		print "CertPPA digest: %s " % certppa.digest.digest.encode("hex")
		print "CertISW signer info: %s " % certisw.digest.signer_info.encode("hex")
		print "CertISW digest: %s " % certisw.digest.digest.encode("hex")
	else :
		print "Certs processing fail!"

	# TODO: Parse rights of the keys
	# TODO: Parse ASN1 from digests

	# Processing Images
	i = 0
	while i < 4 :
		print "images type %s " % type (certppa.images)
		if certppa.images[i].image_offset != 0 :
			print "Found PPA image at %x offset " % certppa.images[i].image_offset
		if certisw.images[i].image_offset != 0 :
			print "Found ISW image at %x offset " % certisw.images[i].image_offset
		i += 1
예제 #36
0
def byBytes(ea, string, reverse=False):
    flags = idaapi.SEARCH_UP if reverse else idaapi.SEARCH_DOWN
    return idaapi.find_binary(ea, -1, ' '.join(str(ord(c)) for c in string), 10, idaapi.SEARCH_CASE | flags)
예제 #37
0
    def search_pointers(self):

        # HACK: A separate flag is used to track user canceling the search,
        #       because multiple calls to idaapi.wasBreak() do not properly
        #       detect cancellations.
        breakFlag = False

        # Show wait dialog
        idaapi.show_wait_box("Searching writable function pointers...")

        for m in self.modules:

            ###################################################################
            # Locate all of the CALL and JMP instructions in the current module
            # which use an immediate operand.

            # List of call/jmp pointer calls in a given module
            ptr_calls = list()

            # Iterate over segments in the module
            # BUG: Iterating over all loaded segments is more stable than looking up by address
            for n in xrange(idaapi.get_segm_qty()):
                seg = idaapi.getnseg(n)

                # Segment in a selected modules
                if seg and seg.startEA >= m.addr and seg.endEA <= (m.addr + m.size):

                    # Locate executable segments
                    # NOTE: Each module may have multiple executable segments
                    # TODO: Search for "MOV REG, PTR # CALL REG"
                    if seg.perm & idaapi.SEGPERM_EXEC:

                        # Search all instances of CALL /2 imm32/64 - FF 15
                        # TODO: Alternative pointer calls using SIB: FF 14 E5 11 22 33 44 - call dword/qword ptr [0x44332211]
                        #                                            FF 14 65 11 22 33 44
                        #                                            FF 14 25 11 22 33 44
                        call_ea = seg.startEA
                        while True:
                            call_ea = idaapi.find_binary(call_ea + 1, seg.endEA, "FF 15", 16, idaapi.SEARCH_DOWN)
                            if call_ea == idaapi.BADADDR: break
                            ptr_calls.append(call_ea)

                        # Search all instances of JMP /2 imm32/64 - FF 25
                        # TODO: Alternative pointer calls using SIB: FF 24 E5 11 22 33 44 - jmp dword/qword ptr [0x44332211]
                        #                                            FF 24 65 11 22 33 44
                        #                                            FF 24 25 11 22 33 44
                        call_ea = seg.startEA
                        while True:
                            call_ea = idaapi.find_binary(call_ea + 1, seg.endEA, "FF 25", 16, idaapi.SEARCH_DOWN)
                            if call_ea == idaapi.BADADDR: break
                            ptr_calls.append(call_ea)

            ###################################################################
            # Extract all of the function pointers and make sure they are
            # are writable.

            # List of writable function pointer objects in a given module
            ptrs = list()

            for call_ea in ptr_calls:

                # Decode CALL/JMP instruction
                # NOTE: May result in invalid disassembly of split instructions
                insn_size = idaapi.decode_insn(call_ea)

                if insn_size:

                    insn = idaapi.cmd
                    insn_op1 = insn.Operands[0].type

                    # Verify first operand is a direct memory reference
                    if insn.Operands[0].type == idaapi.o_mem:

                        # Get operand address
                        ptr_ea = insn.Operands[0].addr

                        # Apply pointer offset
                        ptr_ea -= self.ptrOffset

                        # Locate segment where the pointer is located
                        ptr_seg = idaapi.getseg(ptr_ea)

                        # Make sure a valid segment writeable segment was found
                        if ptr_seg and ptr_seg.perm & idaapi.SEGPERM_WRITE:

                            # Get pointer charset
                            ptr_charset = self.sploiter.get_ptr_charset(ptr_ea)

                            # Filter the pointer
                            if not self.filterP2P:
                                if ptr_charset == None:                                    continue
                                if self.ptrNonull and not "nonull" in ptr_charset: continue
                                if self.ptrUnicode and not "unicode" in ptr_charset: continue
                                if self.ptrAscii and not "ascii" in ptr_charset: continue
                                if self.ptrAsciiPrint and not "asciiprint" in ptr_charset: continue
                                if self.ptrAlphaNum and not "alphanum" in ptr_charset: continue
                                if self.ptrNum and not "numeric" in ptr_charset: continue
                                if self.ptrAlpha and not "alpha" in ptr_charset: continue

                            # Increment the fptr counter

                            # Get pointer disassembly
                            insn_disas = idc.GetDisasmEx(call_ea, idaapi.GENDSM_FORCE_CODE)

                            # Add pointer to the list
                            ptr = Ptr(m.file, ptr_ea, self.ptrOffset, ptr_charset, call_ea, insn_disas)
                            ptrs.append(ptr)

            ###################################################################
            # Cache Pointers to Pointers

            ptr_ea_prefix_cache = dict()

            if self.searchP2P:

                # CACHE: Running repeated searches over the entire memory space is
                #        very expensive. Let's cache all of the addresses containing
                #        bytes corresponding to discovered function pointers in a
                #        single search and simply reference this cache for each
                #        function pointer. Specifically running idaapi.find_binary()
                #        is much more expensive than idaapi.dbg_read_memory().
                #
                # NOTE:  For performance considerations, the cache works on a per
                #        module basis, but could be expanded for the entire memory
                #        space.
                #
                # prefix_offset - how many bytes of discovered function
                #        pointers to cache.
                #
                #        Example: For function pointers 0x00401234, 0x00404321, 0x000405678
                #        we are going to use prefix_offset 2, so we will cache all of the
                #        values located at addresses 0x0040XXXX

                if self.sploiter.addr64:
                    pack_format = "<Q"
                    addr_bytes = 8
                    prefix_offset = 6
                else:
                    pack_format = "<I"
                    addr_bytes = 4
                    prefix_offset = 2

                # Set of unique N-byte address prefixes to search in memory
                ea_prefix_set = set()

                for ptr in ptrs:
                    ptr_ea = ptr.ptr_ea

                    ptr_bytes = struct.pack(pack_format, ptr_ea)
                    ptr_bytes = ptr_bytes[-prefix_offset:]

                    ea_prefix_set.add(ptr_bytes)

                # Search the module for all bytes corresponding to the prefix
                # and use them as candidates for pointers-to-pointers

                for ea_prefix in ea_prefix_set:

                    # NOTE: Make sure you search using 44 33 22 11 format and not 11223344
                    ea_prefix_str = " ".join(["%02x" % ord(b) for b in ea_prefix])

                    # Initialize search parameters for a given module
                    ea = m.addr
                    maxea = m.addr + m.size

                    while True:
                        ea = idaapi.find_binary(ea + 1, maxea, ea_prefix_str, 16, idaapi.SEARCH_DOWN)
                        if ea == idaapi.BADADDR: break

                        p2p_ea = ea - (addr_bytes - prefix_offset)

                        dbg_mem = read_module_memory(p2p_ea, addr_bytes)
                        ptr_ea_prefix = unpack(pack_format, dbg_mem)[0]

                        if ptr_ea_prefix in ptr_ea_prefix_cache:
                            ptr_ea_prefix_cache[ptr_ea_prefix].add(p2p_ea)
                        else:
                            ptr_ea_prefix_cache[ptr_ea_prefix] = set([p2p_ea, ])

                        # Detect search cancellation, but allow the loop below
                        # to run to create already cached/found function pointers

                        # Canceled
                        if breakFlag or idaapi.wasBreak():
                            breakFlag = True
                            break

                    # Canceled
                    if breakFlag or idaapi.wasBreak():
                        breakFlag = True
                        break

            ###################################################################
            # Locate Pointer to Pointers

            for ptr in ptrs:

                ptr_ea = ptr.ptr_ea

                # Locate pointers-to-pointers for a given function pointer in the cache
                if self.searchP2P and ptr_ea in ptr_ea_prefix_cache:

                    for p2p_ea in ptr_ea_prefix_cache[ptr_ea]:

                        # Apply pointer-to-pointer offset
                        p2p_ea -= self.p2pOffset

                        p2p_charset = self.sploiter.get_ptr_charset(p2p_ea)

                        # Filter the pointer
                        if self.filterP2P:
                            if p2p_charset == None:                                    continue
                            if self.ptrNonull and not "nonull" in p2p_charset: continue
                            if self.ptrUnicode and not "unicode" in p2p_charset: continue
                            if self.ptrAscii and not "ascii" in p2p_charset: continue
                            if self.ptrAsciiPrint and not "asciiprint" in p2p_charset: continue
                            if self.ptrAlphaNum and not "alphanum" in p2p_charset: continue
                            if self.ptrNum and not "numeric" in p2p_charset: continue
                            if self.ptrAlpha and not "alpha" in p2p_charset: continue

                        # Copy existing pointer object to modify it for the particular p
                        p2p = copy.copy(ptr)
                        p2p.p2p_ea = p2p_ea
                        p2p.p2p_offset = self.p2pOffset
                        p2p.p2p_charset = p2p_charset

                        # Apppend p2p specific pointer object to the global list
                        self.ptrs.append(p2p)

                        # Exceeded maximum number of pointers
                        if self.maxPtrs and len(self.ptrs) >= self.maxPtrs:
                            breakFlag = True
                            print "[idasploiter] Maximum number of pointers exceeded."
                            break

                # Simply append pointer object to the global list
                else:
                    self.ptrs.append(ptr)

                    # Exceeded maximum number of pointers
                    if self.maxPtrs and len(self.ptrs) >= self.maxPtrs:
                        breakFlag = True
                        print "[idasploiter] Maximum number of pointers exceeded."
                        break

                if breakFlag or idaapi.wasBreak():
                    breakFlag = True
                    break

            # Canceled
            # NOTE: Only works when started from GUI not script.
            if breakFlag or idaapi.wasBreak():
                breakFlag = True
                print "[idasploiter] Canceled."
                break

        print "[idasploiter] Found %d total pointers." % len(self.ptrs)
        idaapi.hide_wait_box()
예제 #38
0
    def search_retns(self):

        if not self.debug: print("found %d modules" % len(self.modules))
        for m in self.modules:

            # Iterate over segments in the module
            # BUG: Iterating over all loaded segments is more stable than looking up by address
            if not self.debug: print("found %d segments" % idaapi.get_segm_qty())
            for n in xrange(idaapi.get_segm_qty()):
                seg = idaapi.getnseg(n)

                # Locate executable segments in a selected modules
                # NOTE: Each module may have multiple executable segments
                if seg and seg.startEA >= m.addr and seg.endEA <= (m.addr + m.size):
                    # If the debugger is attached then we can check if the segment is executable, else
                    # just check if it is code or not.
                    if idaapi.dbg_can_query() and idaapi.get_process_state() < 0:
                        if seg.perm & idaapi.SEGPERM_EXEC == 0:
                            continue
                    elif seg.type & idaapi.SEG_CODE == 0:
                        continue

                    #######################################################
                    # Search for ROP gadgets
                    if self.searchRop:

                        # Search all instances of RETN
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "C3", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break
                            self.retns.append((ea, m.file))

                        # Search all instances of RETN imm16
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "C2", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break

                            # Read imm16 value and filter large values
                            retn_imm16 = read_module_memory(ea + 1, 0x2)
                            retn_imm16 = unpack("<H", retn_imm16)[0]

                            if retn_imm16 <= self.maxRetnImm:
                                self.retns.append((ea, m.file))

                    #######################################################
                    # Search for JOP gadgets
                    if self.searchJop:

                        # Search all instances of JMP reg (FF /4) and CALL reg (FF /2)
                        ea = seg.startEA
                        while True:
                            ea = idaapi.find_binary(ea + 1, seg.endEA, "FF", 16, idaapi.SEARCH_DOWN)
                            if ea == idaapi.BADADDR: break

                            # Read possible ModR/M, SIB, and IMM8/IMM32 bytes
                            jop = read_module_memory(ea + 1, 0x6)
                            if jop == None or len(jop) == 0:
                                continue

                            ###################################################
                            # JMP/CALL reg
                            if jop[0] in ["\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7",
                                          "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7"]:
                                self.retns.append((ea, m.file))

                            ###################################################
                            # JMP/CALL [reg] no SIB
                            # NOTE: Do not include pure [disp] instruction.

                            # JMP/CALL [reg] no *SP,*BP
                            elif jop[0] in ["\x20", "\x21", "\x22", "\x23", "\x26", "\x27",
                                            "\x10", "\x11", "\x12", "\x13", "\x16", "\x17"]:
                                self.retns.append((ea, m.file))

                            # JMP/CALL [reg + imm8] no *SP
                            elif jop[0] in ["\x60", "\x61", "\x62", "\x63", "\x65", "\x66", "\x67",
                                            "\x50", "\x51", "\x52", "\x53", "\x55", "\x56", "\x57"]:
                                jop_imm8 = jop[1]
                                jop_imm8 = unpack("b", jop_imm8)[0]  # signed

                                if jop_imm8 <= self.maxJopImm:
                                    self.retns.append((ea, m.file))


                            # JMP/CALL [reg + imm32] no *SP
                            elif jop[0] in ["\xa0", "\xa1", "\xa2", "\xa3", "\xa5", "\xa6", "\xa7",
                                            "\x90", "\x91", "\x92", "\x93", "\x95", "\x96", "\x97"]:
                                jop_imm32 = jop[1:5]
                                jop_imm32 = unpack("<i", jop_imm32)[0]  # signed

                                if jop_imm32 <= self.maxJopImm:
                                    self.retns.append((ea, m.file))

                            ###################################################
                            # JMP/CALL [reg] with SIB
                            # NOTE: Do no include pure [disp] instructions in SIB ([*] - none)
                            elif (jop[0] in ["\x24", "\x64", "\xa4"] and not jop[1] in ["\x25", "\x65", "\xad",
                                                                                        "\xe5"]) or \
                                    (jop[0] in ["\x14", "\x54", "\x94"] and not jop[1] in ["\x25", "\x65", "\xad",
                                                                                           "\xe5"]):

                                # Check for displacement
                                if jop[0] in ["\x64", "\x54"]:
                                    jop_imm8 = jop[2]
                                    jop_imm8 = unpack("b", jop_imm8)[0]  # signed

                                    if jop_imm8 <= self.maxJopImm:
                                        self.retns.append((ea, m.file))

                                elif jop[0] in ["\xa4", "\x94"]:
                                    jop_imm32 = jop[2:6]
                                    jop_imm32 = unpack("<i", jop_imm32)[0]  # signed

                                    if jop_imm32 <= self.maxJopImm:
                                        self.retns.append((ea, m.file))

                                else:
                                    self.retns.append((ea, m.file))

        print "[idasploiter] Found %d returns" % len(self.retns)
예제 #39
0
def byRegex(ea, string, radix=16, reverse=False, sensitive=False):
    flags = idaapi.SEARCH_UP if reverse else idaapi.SEARCH_DOWN
    flags |= idaapi.SEARCH_CASE if sensitive else 0
    return idaapi.find_binary(ea, -1, string, radix, flags)
예제 #40
0
def load_file(f, neflags, format):
    
    print('# PS4 Kernel Loader')
    ps = Binary(f)
    
    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL, 'gnulnx_x64')
    
    # Segment Loading...
    for segm in ps.E_SEGMENTS:
        if segm.name() == 'PHDR':
            kASLR = False if segm.FILE_SIZE == 0x118 else True
        
        # Process Loadable Segments...
        if segm.name() in ['CODE', 'DATA', 'SCE_RELRO']:
            address = segm.MEM_ADDR
            size = segm.MEM_SIZE
            
            # Dumped Kernel Fix-ups
            if segm.name() in ['DATA', 'SCE_RELRO'] and (idaapi.get_segm_by_name('CODE').start_ea != 0xFFFFFFFF82200000 or not kASLR):
                offset = address - idaapi.get_segm_by_name('CODE').start_ea
                dumped = segm.MEM_SIZE
            else:
                offset = segm.OFFSET
                dumped = segm.FILE_SIZE
            
            print('# Creating %s Segment...' % segm.name())
            f.file2base(offset, address, address + dumped, FILEREG_PATCHABLE)
            
            idaapi.add_segm(0, address, address + size, segm.name(), segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)
            
            # Processor Specific Segment Details
            idc.set_segm_addressing(address, bitness)
            idc.set_segm_alignment(address, segm.alignment())
            idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())
        
        # Process Dynamic Segment...
        elif segm.name() == 'DYNAMIC':
            code = idaapi.get_segm_by_name('CODE')
            data = idaapi.get_segm_by_name('DATA')
            relro = idaapi.get_segm_by_name('SCE_RELRO')
            
            # ------------------------------------------------------------------------------------------------------------
            # Dynamic Tag Entry Structure
            members = [('tag', 'Tag', 0x8),
                       ('value', 'Value', 0x8)]
            struct = segm.struct('Tag', members)
            
            # Dynamic Tag Table
            stubs = {}
            modules = {}
            location = segm.MEM_ADDR
            
            # Dumps are offset by a small amount
            if code.start_ea != 0xFFFFFFFF82200000:
                dumped = code.start_ea - 0xFFFFFFFF82200000
            else:
                dumped = 0
            
            f.seek(location - code.start_ea)
            for entry in xrange(segm.MEM_SIZE / 0x10):
                idaapi.create_struct(location + (entry * 0x10), 0x10, struct)
                idc.set_cmt(location + (entry * 0x10), Dynamic(f).process(dumped, stubs, modules), False)
            
            # ------------------------------------------------------------------------------------------------------------
            # Hash Entry Structure
            members = [('bucket', 'Bucket', 0x2),
                       ('chain', 'Chain', 0x2),
                       ('buckets', 'Buckets', 0x2),
                       ('chains', 'Chains', 0x2)]
            struct = segm.struct('Hash', members)
            
            # Hash Table
            try:
                location = Dynamic.HASHTAB
                size = Dynamic.HASHTABSZ
            
            except:
                location = Dynamic.HASH
                size = Dynamic.SYMTAB - location
            
            f.seek(location - code.start_ea)
            for entry in xrange(size / 0x8):
                idaapi.create_struct(location + (entry * 0x8), 0x8, struct)
            
            if kASLR:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)', 0x8),
                           ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)
                
                # Relocation Table (with specific addends)
                location = Dynamic.RELATAB
                
                f.seek(location - code.start_ea)
                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18, struct)
                    idc.set_cmt(location + (entry * 0x18), Relocation(f).process(dumped, code.end_ea), False)
                
                # Initialization Function
                idc.add_entry(Dynamic.INIT, Dynamic.INIT, '.init', True)
            
            else:
                # --------------------------------------------------------------------------------------------------------
                # Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('offset', 'Value', 0x8),
                           ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)
                
                # Symbol Table
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea)
                functions = {}
                
                # .symtab
                idc.add_entry(location, location, '.symtab', False)
                
                for entry in xrange((Dynamic.STRTAB - location) / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18, struct)
                    idc.set_cmt(location + (entry * 0x18), Symbol(f).process(functions), False)
                
                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = Dynamic.STRTAB
                
                # .strtab
                idc.add_entry(location, location, '.strtab', False)
                
                # Functions
                for key in functions:
                    idc.create_strlit(location + key, BADADDR)
                    functions[key] = idc.get_strlit_contents(location + key, BADADDR)
                    idc.set_cmt(location + key, 'Function', False)
                
                functions = sorted(functions.iteritems(), key = operator.itemgetter(0))
                #print('Functions: %s' % functions)
                
                # Resolve Functions
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea + 0x18)
                
                for entry in xrange((Dynamic.STRTAB - location - 0x18) / 0x18):
                    Symbol(f).resolve(functions[entry][1])
    
    # Fix-up
    if kASLR:
        address = relro.start_ea
        del_items(address, DELIT_SIMPLE, relro.end_ea - address)
        
        while address < relro.end_ea:
            create_data(address, FF_QWORD, 0x8, BADNODE)
            address += 0x8
    
    address = code.start_ea
    
    # ELF Header Structure
    members = [('File format', 0x4),
               ('File class', 0x1),
               ('Data encoding', 0x1),
               ('File version', 0x1),
               ('OS/ABI', 0x1),
               ('ABI version', 0x1),
               ('Padding', 0x7),
               ('File type', 0x2),
               ('Machine', 0x2),
               ('File version', 0x4),
               ('Entry point', 0x8),
               ('PHT file offset', 0x8),
               ('SHT file offset', 0x8),
               ('Processor-specific flags', 0x4),
               ('ELF header size', 0x2),
               ('PHT entry size', 0x2),
               ('Number of entries in PHT', 0x2),
               ('SHT entry size', 0x2),
               ('Number of entries in SHT', 0x2),
               ('SHT entry index for string table\n', 0x2)]
    
    for (comment, size) in members:
        flags = idaapi.get_flags_by_size(size)
        idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE)
        idc.set_cmt(address, comment, False)
        address += size
    
    for index, entry in enumerate(ps.E_SEGMENTS):
        # ELF Program Header Structure
        members = [('Type: %s' % entry.name(), 0x4),
                   ('Flags', 0x4),
                   ('File offset', 0x8),
                   ('Virtual address', 0x8),
                   ('Physical address', 0x8),
                   ('Size in file image', 0x8),
                   ('Size in memory image', 0x8),
                   ('Alignment\n', 0x8)]
        
        for (comment, size) in members:
            flags = idaapi.get_flags_by_size(size)
            
            idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE)
            idc.set_cmt(address, comment, False)
            address += size
    
    # Wait for the AutoAnalyzer to Complete...
    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()
    
    if kASLR:
        # Start Function
        idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)
        
        # Xfast_syscall
        address = idaapi.find_binary(code.start_ea, code.end_ea, '0F 01 F8 65 48 89 24 25 A8 02 00 00 65 48 8B 24', 0x10, SEARCH_DOWN)
        idaapi.do_unknown(address, 0)
        idaapi.create_insn(address)
        idaapi.add_func(address, BADADDR)
        idaapi.set_name(address, 'Xfast_syscall', SN_NOCHECK | SN_NOWARN)
        
        # --------------------------------------------------------------------------------------------------------
        # Znullptr's syscalls
        print('# Processing Znullptr\'s Syscalls...')
        
        # Syscall Entry Structure
        members = [('narg', 'Number of Arguments', 0x4),
                   ('_pad', 'Padding', 0x4),
                   ('function', 'Function', 0x8),
                   ('auevent', 'Augmented Event?', 0x2),
                   ('_pad1', 'Padding', 0x2),
                   ('_pad2', 'Padding', 0x4),
                   ('trace_args_func', 'Trace Arguments Function', 0x8),
                   ('entry', 'Entry', 0x4),
                   ('return', 'Return', 0x4),
                   ('flags', 'Flags', 0x4),
                   ('thrcnt', 'Thread Count?', 0x4)]
        struct = segm.struct('Syscall', members)
        
        znullptr(code.start_ea, code.end_ea, '4F 52 42 49 53 20 6B 65 72 6E 65 6C 20 53 45 4C 46', struct)
        
        # --------------------------------------------------------------------------------------------------------
        # Chendo's cdevsw con-struct-or
        print('# Processing Chendo\'s cdevsw structs...')
        
        # cdevsw Entry Structure
        members = [('d_version', 'Version', 0x4),
                   ('d_flags', 'Flags', 0x4),
                   ('d_name', 'Name', 0x8),
                   ('d_open', 'Open', 0x8),
                   ('d_fdopen', 'File Descriptor Open', 0x8),
                   ('d_close', 'Close', 0x8),
                   ('d_read', 'Read', 0x8),
                   ('d_write', 'Write', 0x8),
                   ('d_ioctl', 'Input/Ouput Control', 0x8),
                   ('d_poll', 'Poll', 0x8),
                   ('d_mmap', 'Memory Mapping', 0x8),
                   ('d_strategy', 'Strategy', 0x8),
                   ('d_dump', 'Dump', 0x8),
                   ('d_kqfilter', 'KQFilter', 0x8),
                   ('d_purge', 'Purge', 0x8),
                   ('d_mmap_single', 'Single Memory Mapping', 0x8),
                   ('d_spare0', 'Spare0', 0x8),
                   ('d_spare1', 'Spare1', 0x8),
                   ('d_spare2', 'Spare2', 0x8),
                   ('d_spare3', 'Spare3', 0x8),
                   ('d_spare4', 'Spare4', 0x8),
                   ('d_spare5', 'Spare5', 0x8),
                   ('d_spare6', 'Spare6', 0x4),
                   ('d_spare7', 'Spare7', 0x4)]
        struct = segm.struct('cdevsw', members)
        
        chendo(data.start_ea, data.end_ea, '09 20 12 17', struct)
    
    # --------------------------------------------------------------------------------------------------------
    # Pablo's IDC
    try:
        print('# Processing Pablo\'s Push IDC...')
        
        # Script 1) Push it real good...
        pablo(code.start_ea, code.end_ea, 'C5 FA 5A C0 C5 F2 5A C9 C5 EA 5A D2 C5 FB 59 C1')
        pablo(code.start_ea, code.end_ea, 'C5 F9 7E C0 31 C9')
        pablo(code.start_ea, code.end_ea, '48 89 E0 55 53')
        pablo(code.start_ea, code.end_ea, 'B8 2D 00 00 00 C3')
        pablo(code.start_ea, code.end_ea, '31 C0 C3')
        pablo(code.start_ea, code.end_ea, '55 48 89')
        pablo(code.start_ea, code.end_ea, '48 81 EC A0 00 00 00 C7')
        pablo(code.start_ea, code.end_ea, '48 81 EC A8 00 00 00')
        
        # Script 2) Fix-up Dumped Data Pointers...
        if dumped or not kASLR:
            print('# Processing Pablo\'s Dumped Data Pointers IDC...')
            pablo(data.start_ea, data.end_ea, '?? FF FF FF FF')
    
    except:
        pass
    
    # --------------------------------------------------------------------------------------------------------
    # Kiwidog's __stack_chk_fail
    if kASLR:
        print('# Processing Kiwidog\'s Stack Functions...')
        
        kiwidog(code.start_ea, code.end_ea, '73 74 61 63 6B 20 6F 76 65 72 66 6C 6F 77 20 64 65 74 65 63 74 65 64 3B')
    
    # --------------------------------------------------------------------------------------------------------
    # Final Pass
    print('# Performing Final Pass...')
    address = code.start_ea
    while address < code.end_ea:
        address = idaapi.find_not_func(address, SEARCH_DOWN)
        
        if idaapi.isUnknown(idaapi.getFlags(address)):
            idaapi.create_insn(address)
        else:
            idc.add_func(address)
        
        address += 4
    
    print('# Done!')
    return 1