Beispiel #1
0
def get_backend_info():
    rv = rpc.GetBackendInfoResult()
    info = py_olly.get_backend_info()
    rv.bitness = int(info['bitness'])
    rv.dbg_name = info['name']
    rv.labeless_ver = py_olly.labeless_ver()
    return rv
Beispiel #2
0
def mem_is_allocated(addr):
    mbi_ctor = D.MEMORY_BASIC_INFORMATION if int(py_olly.get_backend_info()['bitness']) == 32 else D.MEMORY_BASIC_INFORMATION64
    mbi = mbi_ctor()
    VirtualQueryEx = C.windll.kernel32.VirtualQueryEx

    h_process = wintypes.HANDLE(py_olly.get_hprocess())
    queried = VirtualQueryEx(h_process, C.c_void_p(addr), C.byref(mbi), C.sizeof(mbi))
    return queried > 0
Beispiel #3
0
def safe_read_chunked_memory_region_as_one(base, size):
    mbi_ctor = (
        D.MEMORY_BASIC_INFORMATION if int(py_olly.get_backend_info()["bitness"]) == 32 else D.MEMORY_BASIC_INFORMATION64
    )
    mbi = mbi_ctor()
    VirtualQueryEx = C.windll.kernel32.VirtualQueryEx
    VirtualProtectEx = C.windll.kernel32.VirtualProtectEx
    GetLastError = C.windll.kernel32.GetLastError
    GRANULARITY = 0x1000

    h_process = wintypes.HANDLE(py_olly.get_hprocess())  # oa.Plugingetvalue(oa.VAL_HPROCESS))
    try:
        rv = bytearray(size)
    except MemoryError:
        return

    guarded = list()
    gpoints = dict()
    protect = 0

    queried = VirtualQueryEx(h_process, C.c_void_p(base), C.byref(mbi), C.sizeof(mbi))
    if queried:
        protect = mbi.Protect
    else:
        print >> sys.stderr, "safe_read_chunked_memory_region_as_one: VirtualQueryEx(ptr 0x%08X, size 0x%08X) failed, error: %u" % (
            base,
            C.sizeof(mbi),
            GetLastError(),
        )
    if queried and mbi.Protect & D.PAGE_GUARD:
        g = {"ea": base, "size": GRANULARITY, "p": mbi.Protect}
        gpoints[base] = 0
        ea = base
        while True:
            ea -= GRANULARITY
            if (
                VirtualQueryEx(h_process, C.c_void_p(ea), C.byref(mbi), C.sizeof(mbi))
                and (mbi.Protect & D.PAGE_GUARD) != 0
                and g["p"] == mbi.Protect
            ):
                g["ea"] -= GRANULARITY
                g["size"] += GRANULARITY
            else:
                break

        guarded.append(g)

    for i in long_xrange(base + GRANULARITY, base + size, GRANULARITY):
        p_addr = C.c_void_p(i)
        if VirtualQueryEx(h_process, p_addr, C.byref(mbi), C.sizeof(mbi)) and mbi.Protect & D.PAGE_GUARD:
            prevaddr = i - GRANULARITY
            if prevaddr in gpoints and guarded[gpoints[prevaddr]]["p"] == mbi.Protect:
                idx = gpoints[prevaddr]
            else:
                guarded.append({"ea": i, "size": 0L, "p": mbi.Protect})
                idx = len(guarded) - 1
            guarded[idx]["size"] += GRANULARITY
            gpoints[i] = idx
Beispiel #4
0
def mem_is_allocated(addr):
    mbi_ctor = (
        D.MEMORY_BASIC_INFORMATION if int(py_olly.get_backend_info()["bitness"]) == 32 else D.MEMORY_BASIC_INFORMATION64
    )
    mbi = mbi_ctor()
    VirtualQueryEx = C.windll.kernel32.VirtualQueryEx

    h_process = wintypes.HANDLE(py_olly.get_hprocess())
    queried = VirtualQueryEx(h_process, C.c_void_p(addr), C.byref(mbi), C.sizeof(mbi))
    return queried > 0
Beispiel #5
0
def safe_read_chunked_memory_region_as_one(base, size):
    mbi_ctor = D.MEMORY_BASIC_INFORMATION if int(py_olly.get_backend_info(
    )['bitness']) == 32 else D.MEMORY_BASIC_INFORMATION64
    mbi = mbi_ctor()
    VirtualQueryEx = C.windll.kernel32.VirtualQueryEx
    VirtualProtectEx = C.windll.kernel32.VirtualProtectEx
    GetLastError = C.windll.kernel32.GetLastError
    GRANULARITY = 0x1000

    h_process = wintypes.HANDLE(
        py_olly.get_hprocess())  # oa.Plugingetvalue(oa.VAL_HPROCESS))
    try:
        rv = bytearray(size)
    except MemoryError:
        return

    guarded = list()
    gpoints = dict()
    protect = 0

    queried = VirtualQueryEx(h_process, C.c_void_p(base), C.byref(mbi),
                             C.sizeof(mbi))
    if queried:
        protect = mbi.Protect
    else:
        print >> sys.stderr, 'safe_read_chunked_memory_region_as_one: VirtualQueryEx(ptr 0x%08X, size 0x%08X) failed, error: %u' %\
                             (base, C.sizeof(mbi), GetLastError())
    if queried and mbi.Protect & D.PAGE_GUARD:
        g = {'ea': base, 'size': GRANULARITY, 'p': mbi.Protect}
        gpoints[base] = 0
        ea = base
        while True:
            ea -= GRANULARITY
            if VirtualQueryEx(h_process, C.c_void_p(ea), C.byref(mbi), C.sizeof(mbi)) and\
                    (mbi.Protect & D.PAGE_GUARD) != 0 and g['p'] == mbi.Protect:
                g['ea'] -= GRANULARITY
                g['size'] += GRANULARITY
            else:
                break

        guarded.append(g)

    for i in long_xrange(base + GRANULARITY, base + size, GRANULARITY):
        p_addr = C.c_void_p(i)
        if VirtualQueryEx(h_process, p_addr, C.byref(mbi), C.sizeof(mbi)) and\
                        mbi.Protect & D.PAGE_GUARD:
            prevaddr = i - GRANULARITY
            if prevaddr in gpoints and guarded[
                    gpoints[prevaddr]]['p'] == mbi.Protect:
                idx = gpoints[prevaddr]
            else:
                guarded.append({'ea': i, 'size': 0L, 'p': mbi.Protect})
                idx = len(guarded) - 1
            guarded[idx]['size'] += GRANULARITY
            gpoints[i] = idx
Beispiel #6
0
def scan_for_ref_api_calls(ea_from, ea_to, increment, rv, base, size, mem):
    # import inspect
    if ea_from > ea_to:
        print >> sys.stderr, 'Invalid arguments passed'
        return None
    logger.info((
        'scan_for_ref_api_calls(ea_from=0x%08X, ea_to=0x%08X, increment=0x%08X, base=0x%08X)\n'
        + 'getting modules meta') % (ea_from, ea_to, increment, base))

    global modules_meta
    global modules_exports
    logger.info('scan_for_ref_api_calls() modules_meta got')

    this_module_exports = set()
    for name, info in modules_meta.items():
        for i in xrange(len(info['base'])):
            if info['base'][i] <= ea_from < info['base'][i] + info['size'][i]:
                this_module_exports = set(
                    map(lambda x: x['ea'], info['apis'][i]))
                print 'module found: %s, len of exports: %u' % (
                    name, len(this_module_exports))
                break

    unpack_fmt = '<I' if int(
        py_olly.get_backend_info()['bitness']) == 32 else '<Q'
    intptr_size = struct.calcsize(unpack_fmt)

    def isPointsToExternalDll(addr):
        if addr not in modules_exports:
            return False
        if addr in this_module_exports:
            return False
        if base <= addr <= base + size - intptr_size:
            return False
        return modules_exports[addr]

    for ea in long_xrange(ea_from, ea_to, increment):
        try:
            l = ea_to - ea
            offs = ea - ea_from
            cmd = bytearray(mem[offs:offs + min(MAXCMDSIZE, l)])

            dis = api.BASIC_INSTRUCTION_INFO()
            dis.size = 0

            funcs = api.DbgFunctions()
            funcs.DisasmFast_(cmd, ea, dis)

            if dis.size <= 0:
                continue
            if dis.type == api.TYPE_VALUE:
                v = isPointsToExternalDll(dis.value.value)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_IMMCONST
                    ref.module, ref.proc = v.split('.')
                    ref.v = dis.value.value
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace('\0', ''))
                    print 'api.TYPE_VALUE points to %s at %08X as %s' % (
                        v, ea, ref.dis)
                continue
            if dis.type == api.TYPE_ADDR:
                v = isPointsToExternalDll(dis.addr)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_ADDRCONST
                    ref.module, ref.proc = v.split('.')
                    ref.v = dis.addr
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace('\0', ''))
                    print 'api.TYPE_ADDR points to %s at %08X as %s' % (
                        v, ea, ref.dis)
                continue
            if dis.type == api.TYPE_MEMORY:
                v = isPointsToExternalDll(dis.memory.value)
                # if not v and mem_is_allocated(dis.memory.value):
                #     mem_size, mem_raw, _ = safe_read_chunked_memory_region_as_one(dis.memory.value, intptr_size)
                #     tmp = struct.unpack_from(unpack_fmt, buffer(mem_raw), 0)[0]
                #     v = isPointsToExternalDll(tmp)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_JMPCONST
                    ref.module, ref.proc = v.split('.')
                    ref.v = dis.memory.value
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace('\0', ''))
                    print 'api.TYPE_MEMORY points to %s at %08X as %s' % (
                        v, ea, ref.dis)
                continue

                #for k, v in inspect.getmembers(dis):
                #    if '_' not in k:
                #        print "%r: %r" % (k, v)
        except Exception as exc:
            print >> sys.stderr, 'Exception: %r\r\n%s' % (
                exc, traceback.format_exc().replace('\n', '\r\n'))
Beispiel #7
0
def analyze_external_refs(ea_from, ea_to, increment, analysing_base,
                          analysing_size):
    # print >> sys.stderr, 'analyze_external_refs(%08X, %08X, %08X, %08X, %08X)' % \
    #                      (ea_from, ea_to, increment, analysing_base, analysing_size)
    # import labeless.rdebug

    rv = rpc.AnalyzeExternalRefsResult()
    if ea_from > ea_to:
        print >> sys.stderr, 'Invalid arguments passed'
        return rv

    mem = safe_read_chunked_memory_region_as_one(ea_from, ea_to - ea_from)
    if not mem:
        print >> sys.stderr, 'Unable to read specified memory (0x%08X - 0x%08X)' % (
            ea_from, ea_to)
        return rv
    mem = buffer(mem[1])

    unpack_fmt = '<I' if int(
        py_olly.get_backend_info()['bitness']) == 32 else '<Q'
    intptr_size = struct.calcsize(unpack_fmt)

    main_module_name = bridgemain.DbgGetModuleAt(analysing_base)
    if main_module_name:
        main_module_name = path.splitext(
            path.basename(main_module_name))[0].lower()

    rv.context.eax = api.Register_GetEAX()
    rv.context.ecx = api.Register_GetECX()
    rv.context.edx = api.Register_GetEDX()
    rv.context.ebx = api.Register_GetEBX()
    rv.context.esp = api.Register_GetESP()
    rv.context.ebp = api.Register_GetEBP()
    rv.context.esi = api.Register_GetESI()
    rv.context.edi = api.Register_GetEDI()
    rv.context.rip = api.Register_GetCIP()

    if int(py_olly.get_backend_info()['bitness']) == 64:
        rv.context.rax = api.Register_GetRAX()
        rv.context.rbx = api.Register_GetRBX()
        rv.context.rcx = api.Register_GetRCX()
        rv.context.rdx = api.Register_GetRDX()
        rv.context.rsi = api.Register_GetRSI()
        rv.context.rdi = api.Register_GetRDI()
        rv.context.rbp = api.Register_GetRBP()
        rv.context.rsp = api.Register_GetRSP()

    # thread_list = xd.THREADLIST()
    # xd.DbgGetThreadList(thread_list)
    # try:
    #     current = thread_list.CurrentThread
    #     if thread_list.count <= current:
    #         print >> sys.stderr, '[-] Invalid thread info got'
    #         return rv
    #     rv.context.eax = xd.Register_GetEAX()
    #     rv.context.ecx = xd.Register_GetECX()
    #     rv.context.edx = xd.Register_GetEDX()
    #     rv.context.ebx = xd.Register_GetEBX()
    #     rv.context.esp = xd.Register_GetESP()
    #     rv.context.ebp = xd.Register_GetEBP()
    #     rv.context.esi = xd.Register_GetESI()
    #     rv.context.edi = xd.Register_GetEDI()
    #     rv.context.eip = xd.Register_GetEIP()
    #
    # finally:
    #     if thread_list.list:
    #         xd.BridgeFree(thread_list.list)

    global modules_exports

    scan_for_ref_api_calls(ea_from,
                           ea_to,
                           increment,
                           rv=rv,
                           mem=mem,
                           base=analysing_base,
                           size=analysing_size)
    used_addrs = set([])

    for ea in long_xrange(ea_from, ea_to, increment):
        try:
            if ea in used_addrs:
                continue
            l = ea_to - ea
            off = ea - ea_from

            if l < intptr_size:
                break
            addr = struct.unpack_from(unpack_fmt, mem, off)[0]
            if addr not in modules_exports:
                continue
            symb = modules_exports[addr]
            module_name, proc_name = symb.split('.')
            if module_name == main_module_name:
                continue

            v = rv.api_constants.add()
            v.ea = ea
            v.module = module_name
            v.proc = proc_name

        except Exception as exc:
            print >> sys.stderr, 'Exception: %r\r\n%s' % (
                exc, traceback.format_exc().replace('\n', '\r\n'))
    print 'AnalyzeExternalRefs(ea_from=0x%x, ea_to=0x%x): api consts found %u, refs found: %u' % (
        ea_from, ea_to, len(rv.api_constants), len(rv.refs))
    # print rv
    return rv
Beispiel #8
0
def scan_for_ref_api_calls(ea_from, ea_to, increment, rv, base, size, mem):
    # import inspect
    if ea_from > ea_to:
        print >> sys.stderr, "Invalid arguments passed"
        return None
    logger.info(
        (
            "scan_for_ref_api_calls(ea_from=0x%08X, ea_to=0x%08X, increment=0x%08X, base=0x%08X)\n"
            + "getting modules meta"
        )
        % (ea_from, ea_to, increment, base)
    )

    global modules_meta
    global modules_exports
    logger.info("scan_for_ref_api_calls() modules_meta got")

    this_module_exports = set()
    for name, info in modules_meta.items():
        for i in xrange(len(info["base"])):
            if info["base"][i] <= ea_from < info["base"][i] + info["size"][i]:
                this_module_exports = set(map(lambda x: x["ea"], info["apis"][i]))
                print "module found: %s, len of exports: %u" % (name, len(this_module_exports))
                break

    unpack_fmt = "<I" if int(py_olly.get_backend_info()["bitness"]) == 32 else "<Q"
    intptr_size = struct.calcsize(unpack_fmt)

    def isPointsToExternalDll(addr):
        if addr not in modules_exports:
            return False
        if addr in this_module_exports:
            return False
        if base <= addr <= base + size - intptr_size:
            return False
        return modules_exports[addr]

    for ea in long_xrange(ea_from, ea_to, increment):
        try:
            l = ea_to - ea
            offs = ea - ea_from
            cmd = bytearray(mem[offs : offs + min(MAXCMDSIZE, l)])

            dis = api.BASIC_INSTRUCTION_INFO()
            dis.size = 0

            funcs = api.DbgFunctions()
            funcs.DisasmFast_(cmd, ea, dis)

            if dis.size <= 0:
                continue
            if dis.type == api.TYPE_VALUE:
                v = isPointsToExternalDll(dis.value.value)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_IMMCONST
                    ref.module, ref.proc = v.split(".")
                    ref.v = dis.value.value
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace("\0", ""))
                    print "api.TYPE_VALUE points to %s at %08X as %s" % (v, ea, ref.dis)
                continue
            if dis.type == api.TYPE_ADDR:
                v = isPointsToExternalDll(dis.addr)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_ADDRCONST
                    ref.module, ref.proc = v.split(".")
                    ref.v = dis.addr
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace("\0", ""))
                    print "api.TYPE_ADDR points to %s at %08X as %s" % (v, ea, ref.dis)
                continue
            if dis.type == api.TYPE_MEMORY:
                v = isPointsToExternalDll(dis.memory.value)
                # if not v and mem_is_allocated(dis.memory.value):
                #     mem_size, mem_raw, _ = safe_read_chunked_memory_region_as_one(dis.memory.value, intptr_size)
                #     tmp = struct.unpack_from(unpack_fmt, buffer(mem_raw), 0)[0]
                #     v = isPointsToExternalDll(tmp)
                if v:
                    ref = rv.refs.add()
                    ref.ref_type = rpc.AnalyzeExternalRefsResult.RefData.REFT_JMPCONST
                    ref.module, ref.proc = v.split(".")
                    ref.v = dis.memory.value
                    ref.ea = ea
                    ref.len = dis.size
                    ref.dis = str(dis.instruction.replace("\0", ""))
                    print "api.TYPE_MEMORY points to %s at %08X as %s" % (v, ea, ref.dis)
                continue

                # for k, v in inspect.getmembers(dis):
                #    if '_' not in k:
                #        print "%r: %r" % (k, v)
        except Exception as exc:
            print >> sys.stderr, "Exception: %r\r\n%s" % (exc, traceback.format_exc().replace("\n", "\r\n"))
Beispiel #9
0
def analyze_external_refs(ea_from, ea_to, increment, analysing_base, analysing_size):
    # print >> sys.stderr, 'analyze_external_refs(%08X, %08X, %08X, %08X, %08X)' % \
    #                      (ea_from, ea_to, increment, analysing_base, analysing_size)
    # import labeless.rdebug

    rv = rpc.AnalyzeExternalRefsResult()
    if ea_from > ea_to:
        print >> sys.stderr, "Invalid arguments passed"
        return rv

    mem = safe_read_chunked_memory_region_as_one(ea_from, ea_to - ea_from)
    if not mem:
        print >> sys.stderr, "Unable to read specified memory (0x%08X - 0x%08X)" % (ea_from, ea_to)
        return rv
    mem = buffer(mem[1])

    unpack_fmt = "<I" if int(py_olly.get_backend_info()["bitness"]) == 32 else "<Q"
    intptr_size = struct.calcsize(unpack_fmt)

    main_module_name = bridgemain.DbgGetModuleAt(analysing_base)
    if main_module_name:
        main_module_name = path.splitext(path.basename(main_module_name))[0].lower()

    rv.context.eax = api.Register_GetEAX()
    rv.context.ecx = api.Register_GetECX()
    rv.context.edx = api.Register_GetEDX()
    rv.context.ebx = api.Register_GetEBX()
    rv.context.esp = api.Register_GetESP()
    rv.context.ebp = api.Register_GetEBP()
    rv.context.esi = api.Register_GetESI()
    rv.context.edi = api.Register_GetEDI()
    rv.context.rip = api.Register_GetCIP()

    if int(py_olly.get_backend_info()["bitness"]) == 64:
        rv.context.rax = api.Register_GetRAX()
        rv.context.rbx = api.Register_GetRBX()
        rv.context.rcx = api.Register_GetRCX()
        rv.context.rdx = api.Register_GetRDX()
        rv.context.rsi = api.Register_GetRSI()
        rv.context.rdi = api.Register_GetRDI()
        rv.context.rbp = api.Register_GetRBP()
        rv.context.rsp = api.Register_GetRSP()

    # thread_list = xd.THREADLIST()
    # xd.DbgGetThreadList(thread_list)
    # try:
    #     current = thread_list.CurrentThread
    #     if thread_list.count <= current:
    #         print >> sys.stderr, '[-] Invalid thread info got'
    #         return rv
    #     rv.context.eax = xd.Register_GetEAX()
    #     rv.context.ecx = xd.Register_GetECX()
    #     rv.context.edx = xd.Register_GetEDX()
    #     rv.context.ebx = xd.Register_GetEBX()
    #     rv.context.esp = xd.Register_GetESP()
    #     rv.context.ebp = xd.Register_GetEBP()
    #     rv.context.esi = xd.Register_GetESI()
    #     rv.context.edi = xd.Register_GetEDI()
    #     rv.context.eip = xd.Register_GetEIP()
    #
    # finally:
    #     if thread_list.list:
    #         xd.BridgeFree(thread_list.list)

    global modules_exports

    scan_for_ref_api_calls(ea_from, ea_to, increment, rv=rv, mem=mem, base=analysing_base, size=analysing_size)
    used_addrs = set([])

    for ea in long_xrange(ea_from, ea_to, increment):
        try:
            if ea in used_addrs:
                continue
            l = ea_to - ea
            off = ea - ea_from

            if l < intptr_size:
                break
            addr = struct.unpack_from(unpack_fmt, mem, off)[0]
            if addr not in modules_exports:
                continue
            symb = modules_exports[addr]
            module_name, proc_name = symb.split(".")
            if module_name == main_module_name:
                continue

            v = rv.api_constants.add()
            v.ea = ea
            v.module = module_name
            v.proc = proc_name

        except Exception as exc:
            print >> sys.stderr, "Exception: %r\r\n%s" % (exc, traceback.format_exc().replace("\n", "\r\n"))
    print "AnalyzeExternalRefs(ea_from=0x%x, ea_to=0x%x): api consts found %u, refs found: %u" % (
        ea_from,
        ea_to,
        len(rv.api_constants),
        len(rv.refs),
    )
    # print rv
    return rv
Beispiel #10
0
# -*- coding: utf-8 -*
# Labeless
# by Aliaksandr Trafimchuk
#
# Source code released under
# Creative Commons BY-NC 4.0
# http://creativecommons.org/licenses/by-nc/4.0

__author__ = 'a1ex_t'

from labeless import py_olly
if int(py_olly.get_backend_info()['bitness']) == 32:
    from x64dbgapi import *
else:
    from x64dbgapi64 import *