Ejemplo n.º 1
0
def mem_dump(debugger, command, exe_ctx, result, internal_dict):
    command_args = shlex.split(command, posix=False)

    _ = exe_ctx.target
    _ = exe_ctx.thread

    if len(command_args) != 3:
        utils.ELOG("[usage] mem_dump outFile addr size")
        return

    outfile = command_args[0]
    start_addr = utils.convertToInt(command_args[1])
    size = eval(command_args[2])

    if not start_addr:
        utils.ELOG("params format error")
        return

    utils.ILOG("default address will plus main image slide")
    slide = utils.get_image_slide(debugger, 0)
    start_addr = start_addr + slide

    cmd = "memory read --binary --outfile {} --count {} {}".format(
        outfile, size, start_addr)
    utils.ILOG("mem dump:{}".format(cmd))
    ret = utils.exe_cmd(debugger, cmd)

    result.AppendMessage(str(ret))
    return
Ejemplo n.º 2
0
def debugme(debugger):
    utils.ILOG("start patch ptrace funtion to bypass anti debug")
    patch_ptrace(debugger)
    utils.SLOG("ptrace funtion patach done")

    utils.ILOG("start patch svc ins to bypass anti debug")
    images = utils.get_all_image_of_app()
    for image in images:
        utils.ILOG("search svc from:{}".format(image["name"]))
        text_addr_arr_str = get_text_segment(debugger, image["idx"])
        text_addr_arr = text_addr_arr_str.strip()[1:-1].split(",")
        if len(text_addr_arr) < 2:
            utils.ELOG("failed to get text segment of image:{}" + image["name"])
            continue
        text_start = text_addr_arr[0]
        text_end = text_addr_arr[1]
        utils.ILOG("text start:{} end:{}".format(text_start, text_end))
        svc_arr_str = lookup_svc_insn(debugger, text_start, text_end)
        if "<object returned empty description>" in svc_arr_str:
            utils.ILOG("not found svc ins, so don't need patch")
            continue
        
        svc_arr = svc_arr_str.strip()
        svc_arr = svc_arr.split()

        if len(svc_arr) < 1:
            utils.ELOG("not found svc ins, so don't need patch")
            continue
        for svc_addr in svc_arr:
            utils.ILOG("start hook svc at address:{}".format(svc_addr))
            ret = xia0Hook(debugger, svc_addr)
            if ret:
                utils.SLOG("hook svc at address:{} done".format(svc_addr))
    return
Ejemplo n.º 3
0
def mr(debugger, command, exe_ctx, result, internal_dict):
    command_args = shlex.split(command, posix=False)

    _ = exe_ctx.target
    _ = exe_ctx.thread

    if len(command_args) != 2:
        utils.ELOG("[usage] mr addr count")
        return

    start_addr = utils.convertToInt(command_args[0])
    size = eval(command_args[1])

    if not start_addr:
        utils.ELOG("params format error")
        return

    # utils.ILOG("default address will plus main image slide")
    # slide = utils.get_image_slide(debugger, 0)
    # start_addr = start_addr + slide

    cmd = "memory read  {} --count {}".format(start_addr, size)
    utils.ILOG("mem read:{}".format(cmd))
    ret = utils.exe_cmd(debugger, cmd)

    result.AppendMessage(str(ret))
    return
Ejemplo n.º 4
0
def debugme(debugger):
    utils.ILOG("start patch ptrace funtion to bypass antiDebug")
    patch_ptrace(debugger)
    utils.SLOG("success ptrace funtion to bypass antiDebug")

    utils.ILOG("start patch svc ins to bypass antiDebug")
    # get text segment start/end address

    ret = get_text_segment(debugger)
    # remove " \n"
    ret = ret.strip()
    ret = ret[1:-1]

    textAddrs = ret.split(',')

    if len(textAddrs) < 2:
        utils.ELOG("failed to get text segment:" + str(textAddrs))
        return

    textStart = ret.split(',')[0]
    textEnd = ret.split(',')[1]
    textStart = textStart.strip()
    textEnd = textEnd.strip()

    utils.SLOG("get text segment start address:{} and end address:{}".format(
        textStart, textEnd))

    # lookup svc ins go through all text code
    ret = lookup_svc_insn(debugger, textStart, textEnd)

    if "<object returned empty description>" in ret:
        utils.ILOG("not found svc ins, so don't need patch")
        return

    svcAddrs = ret.strip()
    svcAddrs = svcAddrs.split()

    if len(svcAddrs) < 1:
        utils.ELOG("not found svc ins, so don't need patch")
        return

    for svcAddr in svcAddrs:
        utils.SLOG("found svc address:{}".format(svcAddr))
        utils.ILOG("start hook svc at address:{}".format(svcAddr))
        ret = xia0Hook(debugger, svcAddr)
        if ret:
            utils.SLOG("success hook svc at address:{}".format(svcAddr))

    utils.ILOG("all patch done")

    return
Ejemplo n.º 5
0
def save_image(debugger, command, exe_ctx, result, internal_dict):
    command_args = shlex.split(command, posix=False)

    _ = exe_ctx.target
    _ = exe_ctx.thread

    if len(command_args) < 1:
        utils.ELOG("[usage] save_image UIImageObj")
        return

    image_obj_addr = command_args[0]
    script = '@import Foundation;'
    script += "UIImage* image = (UIImage*){}".format(image_obj_addr)
    script += '''
    NSString* ret = @"DONE";
    if (image != nil){
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                            NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString* path = [documentsDirectory stringByAppendingPathComponent:
                        @"xia0.gif" ];
        NSData* data = UIImagePNGRepresentation(image);
        [data writeToFile:path atomically:YES];
    }

    ret
    '''
    ret = utils.exe_script(debugger, script)

    result.AppendMessage(str(ret))
    return
Ejemplo n.º 6
0
def methods(debugger, command, exe_ctx, result, internal_dict):
    def generate_option_parser():
        usage = "usage: xmethods"
        parser = optparse.OptionParser(usage=usage, prog="lookup")

        parser.add_option("-n",
                          "--name",
                          action="store",
                          default=None,
                          dest="name",
                          help="set the class name for methods")

        return parser

    command_args = shlex.split(command, posix=False)
    parser = generate_option_parser()
    try:
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    _ = exe_ctx.target
    _ = exe_ctx.thread

    if options.name:
        clzname = options.name
        try:
            clzname = re.search("^\"(.*)\"$", clzname).group(1)
        except:
            utils.ELOG("input format error! need \"class name\"")
            return
        utils.ILOG("will get methods for class:\"{}\"".format(clzname))
        code = '''  
            Class clz =  objc_getClass(\"{}\");
            id ret = [clz _shortMethodDescription];

            ret
        '''.format(clzname)
        ret = utils.exe_script(debugger, code)

        result.AppendMessage(ret)
        return result

    clz = args[0]
    code = '''
        id ret = [{} _shortMethodDescription];
        ret
    '''.format(clz)
    ret = utils.exe_script(debugger, code)

    result.AppendMessage(ret)
    return result
Ejemplo n.º 7
0
def get_module_info_by_name(debugger, moduleName):

    command_script = '@import Foundation;NSString* moduleName = @"' + moduleName + '";'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];
    
    uint32_t count = (uint32_t)_dyld_image_count();
    for(uint32_t i = 0; i < count; i++){
        char* curModuleName_cstr = (char*)_dyld_get_image_name(i);
        long slide = (long)_dyld_get_image_vmaddr_slide(i);
        uintptr_t baseAddr = (uintptr_t)_dyld_get_image_header(i);
        NSString* curModuleName = @(curModuleName_cstr);
        if([curModuleName containsString:moduleName]) {
            [retStr appendString:@"\n=======\nModule Path : "];
            [retStr appendString:@(curModuleName_cstr)];
            [retStr appendString:@"\nModule Silde: "];
            [retStr appendString:(id)[@(slide) stringValue]];
            [retStr appendString:@"\nModule base : "];
            [retStr appendString:(id)[@(baseAddr) stringValue]];
        }
    }
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    if "error" in retStr:
        utils.ELOG("something error in OC script # " + retStr.strip())
        utils.ILOG("so use command to get info")
        ret = utils.exe_cmd(debugger, "im li -o -f")
        pattern = ".*" + moduleName.replace("\"", "")
        match = re.search(pattern, ret)  # TODO: more strict
        if match:
            found = match.group(0)
        else:
            utils.ELOG("not found image:" + moduleName)
            return

        return found

    return utils.hex_int_in_str(retStr)
Ejemplo n.º 8
0
def handle_command(debugger, command, exe_ctx, result, internal_dict):
    command_args = shlex.split(command, posix=False)
    parser = generate_option_parser()
    try:
        (options, _) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    _ = exe_ctx.target
    _ = exe_ctx.thread

    if options.patchInstrument:
        if options.patchAddress:
            patch_addr = int(options.patchAddress, 16)
        else:
            ret = utils.exe_cmd(debugger, "p/x $pc")
            ret = ret.strip()
            pattern = '0x[0-9a-f]+'
            match = re.search(pattern, ret)
            if match:
                found = match.group(0)
            else:
                utils.ELOG("not get address:" + ret)
                return

            utils.ILOG(
                "you not set patch address, default is current pc address:{}".
                format(found))
            patch_addr = int(found, 16)

        patch_ins = options.patchInstrument
        # default instrument size is 1
        patch_size = 0x1
        patch_ins = patch_ins.replace("\"", "")
        patch_ins = patch_ins.replace("'", "")

        if options.patchSize:
            patch_size = int(options.patchSize)

        ret = patcher(debugger, patch_ins, patch_addr, patch_size)

        result.AppendMessage(str(ret))
    else:
        result.AppendMessage("[-] args error, check it !")

    return
Ejemplo n.º 9
0
def patcher(debugger, ins, addr, size):
    if is_raw_data(ins):
        utils.ILOG("detect you manual set ins data:{}".format(ins))
        utils.ILOG(
            "start patch text at address:{} size:{} to ins data:{}".format(
                hex(addr), size, ins))
        patch_code(debugger, hex(addr), ins, size)
        return "[x] power by xia0@2019"

    supportInsList = {
        'nop': '0x1f, 0x20, 0x03, 0xd5 ',
        'ret': '0xc0, 0x03, 0x5f, 0xd6',
        'mov0': '0x00, 0x00, 0x80, 0xd2',
        'mov1': '0x20, 0x00, 0x80, 0xd2'
    }
    if ins not in supportInsList.keys():
        utils.ELOG("patcher not support this ins type:{}".format(ins))
        return "[x] power by xia0@2019"

    utils.ILOG(
        "start patch text at address:{} size:{} to ins:\"{}\" and data:{}".
        format(hex(addr), size, ins, supportInsList[ins]))

    # for i in range(size):
    #     patch_code(debugger, hex(curPatchAddr), supportInsList[ins])
    #     utils.SLOG("current patch address:{} patch done".format(hex(curPatchAddr)))
    #     curPatchAddr += 4
    ins_data = ""
    for i in range(size):
        ins_data += supportInsList[ins]
        if i != size - 1:
            ins_data += ","

    build_ins_data = "{" + ins_data + "}"

    utils.ILOG("make ins data:\n{}".format(build_ins_data))

    patch_code(debugger, hex(addr), build_ins_data, size)
    utils.SLOG("patch done")
    return "[x] power by xia0@2019"
Ejemplo n.º 10
0
def dumpdecrypted(debugger, modulePath=None, moduleIdx=None):
    # must delete all breakpoints.
    utils.ILOG("delete all breakpoints")
    utils.exe_cmd(debugger, "br de -f")
    #dump_macho_to_file(debugger,)
    if modulePath and moduleIdx:
        print(dump_macho_to_file(debugger, moduleIdx, modulePath))
    else:
        mainImagePath = get_main_image_path(debugger)
        appDir = os.path.dirname(mainImagePath)

        appImagesStr = get_all_image_of_app(debugger, appDir)

        appImagesArr = appImagesStr.split("#")
        for imageInfo in appImagesArr:
            if not imageInfo or not "," in imageInfo:
                utils.ELOG("image info is null, skip image # " + imageInfo)
                continue

            utils.ILOG("now is image: " + imageInfo)
            info = imageInfo.split(",")

            if len(info) == 2:
                utils.ILOG("start dump [" + info[0] + "] image:" + info[1])
                # print "idx:" + info[0]
                # print "path:" + info[1]
                if info[1] == mainImagePath:
                    entryAddrStr = get_macho_entry_offset(debugger)
                    entryAddr_int = int(entryAddrStr.strip()[1:-1], 16)
                    utils.SLOG("fix main addr:" + hex(entryAddr_int))
                    print(
                        dump_macho_to_file(debugger, info[0], info[1],
                                           entryAddr_int))
                    continue
                print(dump_macho_to_file(debugger, info[0], info[1]))
    return '\n\n[*] Developed By xia0@2019'
Ejemplo n.º 11
0
def xbr(debugger, command, result, dict):
    raw_args = create_command_arguments(command)

    command_args = shlex.split(command, posix=False)
    parser = generate_option_parser()
    try:
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    # check is options?
    if options.address:
        targetAddr = options.address

        if targetAddr.startswith("0x"):
            targetAddr_int = int(targetAddr, 16)
        else:
            targetAddr_int = int(targetAddr, 10)
          
        utils.ILOG("breakpoint at address:{}".format(hex(targetAddr_int)))
        lldb.debugger.HandleCommand ('breakpoint set --address %d' % targetAddr_int)
        return

    if options.entryAddress:
        if options.entryAddress == "main":
            entryAddrStr = get_macho_entry_offset(debugger)
            entryAddr_int = int(entryAddrStr.strip()[1:-1], 16)
            utils.ILOG("breakpoint at main function:{}".format(hex(entryAddr_int)))
            lldb.debugger.HandleCommand ('breakpoint set --address %d' % entryAddr_int)
        elif options.entryAddress == "init":
            initFunAddrStr = get_macho_mod_init_first_func(debugger)
            initFunAddr_int = int(initFunAddrStr.strip()[1:-1], 16)
            utils.ILOG("breakpoint at mod int first function:{}".format(hex(initFunAddr_int)))
            lldb.debugger.HandleCommand ('breakpoint set --address %d' % initFunAddr_int)
        elif options.entryAddress == "load":
            
            ret = get_all_class_plus_load_methods(debugger)
            if "<object returned empty description>" in ret:
                utils.ILOG("not found +[* load] method")
                return
            all_load_addrs_str_arr = ret.strip().split(",")
            all_load_addrs = []
            for addr in all_load_addrs_str_arr:
                if addr != "":
                    all_load_addrs.append(int(addr, 10))
            utils.ILOG("will set breakpoint at all +[* load] methold, count:{}".format(len(all_load_addrs)))
            for addr in all_load_addrs:
                lldb.debugger.HandleCommand ('breakpoint set --address %d' % addr)
                utils.SLOG("set br at:{}".format(hex(addr)))
            # utils.ILOG("load:\n{}\n".format([hex(addr) for addr in all_load_addrs]))
        else:
            utils.ELOG("you should special the -E options:[main/init/load]")

        return
        

    # check is arg is address ? mean auto add slide
    if is_just_address_cmd(args):

        if options.modulePath:
            modulePath = options.modulePath
            utils.ILOG("you special the module:" + modulePath)
        else:
            utils.ILOG("you not special the module, default is main module")
            modulePath = None

        targetAddr = args[0]

        if targetAddr.startswith("0x"):
            targetAddr_int = int(targetAddr, 16)
        else:
            targetAddr_int = int(targetAddr, 10)

        moduleSlide = get_process_module_slide(debugger, modulePath)
        if "error" in moduleSlide:
            utils.ELOG("error in oc script # " + moduleSlide.strip())
            if modulePath:
                targetImagePath = modulePath
            else:               
                mainImagePath = get_main_image_path(debugger)
                if "no value available" in  mainImagePath or "error" in mainImagePath:
                    ret = utils.exe_cmd(debugger, "target list")
                    # pylint: disable=anomalous-backslash-in-string
                    pattern = '/.*\('
                    match = re.search(pattern, ret) # TODO: more strict
                    if match:
                        found = match.group(0)
                        found = found.split("(")[0]
                        found = found.strip()
                    else:
                        utils.ELOG("failed to auto get main module, use -m option")
                        return
 
                    mainImagePath = found
                    print("[+] use \"target list\" to get main module:" + mainImagePath)
                else:
                    mainImagePath = mainImagePath.strip()[1:-1]

                targetImagePath = mainImagePath

            ret = utils.exe_cmd(debugger, "image list -o -f")
            pattern = '0x.*?' + targetImagePath.replace("\"", "")
            match = re.search(pattern, ret) # TODO: more strict
            if match:
                found = match.group(0)
            else:
                utils.ELOG("not found image:"+targetImagePath)
                return
            moduleSlide = found.split()[0]
            utils.ILOG("use \"image list -o -f\" cmd to get image slide:"+moduleSlide)
            moduleSlide = int(moduleSlide, 16)

        else:
            moduleSlide = int(moduleSlide, 10)
            
        brAddr = moduleSlide + targetAddr_int

        utils.ILOG("ida's address:{} module slide:{} target breakpoint address:{}".format(hex(targetAddr_int), hex(moduleSlide), hex(brAddr)))
        
        lldb.debugger.HandleCommand ('breakpoint set --address %d' % brAddr)
        return

    # check is breakpoint at all methods address(IMP) for given classname
    if is_br_all_cmd_x(args):
        classname = args[0]
        begin = classname.find('$')
        end = classname.rfind('$')
        classname = classname[begin+1 : end]
        utils.ILOG("classname:{}".format(classname))

        ret = get_all_method_address_of_class(debugger, classname)

        addrArr = ret.split('-')[:-1]

        for addr in addrArr:
            address = int(addr)
            if address:
                lldb.debugger.HandleCommand ('breakpoint set --address %x' % address)
        
        result.AppendMessage("Set %ld breakpoints of %s" % (len(addrArr),classname))
        return

    if is_br_all_cmd(args):
        classname = args[0]
        ret = get_all_method_address_of_class(debugger, classname)

        addrArr = ret.split('-')[:-1]

        for addr in addrArr:
            address = int(addr)
            if address:
                lldb.debugger.HandleCommand ('breakpoint set --address %x' % address)
        
        result.AppendMessage("Set %ld breakpoints of %s" % (len(addrArr),classname))
        return
    


    if not is_command_valid(raw_args):
        print('please specify the param, for example: "-[UIView initWithFrame:]"')
        return

    arg_ = raw_args[0]
    class_name = get_class_name(arg_)
    method_name = get_method_name(arg_)
#    xlog = 'className:'+ str(class_name) + '\tmethodName:' + str(method_name)
    utils.ILOG("className:{} methodName:{}".format(class_name, method_name))
    # print class_name, method_name
    address = 0
    if is_class_method(arg_):
        address = get_class_method_address(class_name, method_name)
    else:
        address = get_instance_method_address(class_name, method_name)

    utils.SLOG('found method address:0x%x' % address)
    if address:
        lldb.debugger.HandleCommand ('breakpoint set --address %x' % address)
    else:
        utils.ELOG("fail, please check the arguments")
Ejemplo n.º 12
0
def objc_dump_protocol(debugger, protocol_name):
    command_script = '@import Foundation;const char * name = (const char *)\"' + protocol_name + '\";'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];
    
    struct objc_method_description {
        SEL _Nullable name;               /**< The name of the method */
        char * _Nullable types;           /**< The types of the method arguments */
    };
    unsigned int protocolCount;
    Protocol * * __protocols = (Protocol **)objc_copyProtocolList (&protocolCount);

    for (int i = 0; i < protocolCount; i++) {
        const char *protocolName = (const char * )protocol_getName (__protocols[i]);
        
        
        if (strcmp(name, protocolName) == 0) {
            unsigned int adopteeCount;
            Protocol ** adoptees = (Protocol **)protocol_copyProtocolList (__protocols[i], &adopteeCount);
            free (adoptees);

            struct objc_method_description *methods;
            unsigned int count;
            unsigned int requiredCount = 0;
            unsigned int optionalCount = 0;

            methods = (struct objc_method_description *)protocol_copyMethodDescriptionList (__protocols[i], YES, YES, &count);
            for (int i = 0; i < count; i++) {
                [retStr appendString:@"-"];
                [retStr appendString:@","];
                [retStr appendString:NSStringFromSelector(methods[i].name)];
                [retStr appendString:@","];
                [retStr appendString:[NSString stringWithUTF8String:methods[i].types]];
                [retStr appendString:@"||"];
            }
            requiredCount += count;
            free (methods);
            
            
            
            methods = (struct objc_method_description *)protocol_copyMethodDescriptionList (__protocols[i], YES, NO, &count);
            for (int i = 0; i < count; i++) {
                [retStr appendString:@"+"];
                [retStr appendString:@","];
                [retStr appendString:NSStringFromSelector(methods[i].name)];
                [retStr appendString:@","];
                [retStr appendString:[NSString stringWithUTF8String:methods[i].types]];
                [retStr appendString:@"||"];
            }
            requiredCount += count;
            free (methods);

            methods = (struct objc_method_description *)protocol_copyMethodDescriptionList (__protocols[i], NO, YES, &count);
            for (int i = 0; i < count; i++) {
                [retStr appendString:@"-"];
                [retStr appendString:@","];
                [retStr appendString:NSStringFromSelector(methods[i].name)];
                [retStr appendString:@","];
                [retStr appendString:[NSString stringWithUTF8String:methods[i].types]];
                [retStr appendString:@"||"];
            }
            optionalCount += count;
            free (methods);
            
            
            methods = (struct objc_method_description *)protocol_copyMethodDescriptionList (__protocols[i], NO, NO, &count);
            for (int i = 0; i < count; i++) {
                [retStr appendString:@"+"];
                [retStr appendString:@","];
                [retStr appendString:NSStringFromSelector(methods[i].name)];
                [retStr appendString:@","];
                [retStr appendString:[NSString stringWithUTF8String:methods[i].types]];
                [retStr appendString:@"||"];
            }
            optionalCount += count;
            free (methods);

            break;
        }
    }

    free (__protocols);

    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)

    arr = retStr.strip().split("||")
    retArr = []

    for item in arr:
        if len(item) <= 0:
            continue

        protocolInfo = item.split(",")

        if len(protocolInfo) != 3:
            utils.ELOG("Error for protocolInfo")
            break

        retArr.append([protocolInfo[0], protocolInfo[1], protocolInfo[2]])

    return retArr
Ejemplo n.º 13
0
def xmethods(debugger, command, exe_ctx, result, internal_dict):
    def generate_option_parser():
        usage = "usage: xmethods"
        parser = optparse.OptionParser(usage=usage, prog="lookup")

        parser.add_option("-a",
                          "--address",
                          action="store",
                          default=None,
                          dest="address",
                          help="set a breakpoint at absolute address")

        return parser

    command_args = shlex.split(command, posix=False)
    parser = generate_option_parser()
    try:
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    _ = exe_ctx.target
    _ = exe_ctx.thread

    def is_address(args):
        if len(args) == 0:
            return False

        arg = args[0]
        if len(arg) == 0:
            return False

        ret = re.match('^0x[0-9a-fA-F]+$', arg)

        if not ret:
            return False
        return True

    clz = args[0]
    obj = clz
    if is_address(args):
        clz = objc_obj_name(debugger, args[0])

    ret = objc_dump_methods(debugger, clz)

    utils.ILOG("Dump methods for {}({})".format(obj, clz))
    # print(ret)

    for method in ret:
        if len(method) < 4:
            utils.ELOG("Error method!")
            break

        addr = hex(utils.convertToInt(method[2]))

        retType = method[3]
        retTypeList = objc_parse_typesign(method[3])

        if retTypeList and len(retTypeList) > 0:
            retType = retTypeList[0]

        selname = method[1]
        argCount = len(method) - 4

        if argCount > 0:
            global methodArgIdx

            arr = method[4:]
            methodArgIdx = 0

            def handler(reobj):
                global methodArgIdx
                r = reobj.group(0)

                argType = arr[methodArgIdx]
                argTypeList = objc_parse_typesign(argType)

                if argTypeList and len(argTypeList) > 0:
                    argType = argTypeList[0]

                r = r + "(" + argType + ")" + "a" + str(methodArgIdx) + " "
                methodArgIdx = methodArgIdx + 1
                return r

            selname = re.sub(":", handler, selname, flags=0)

        line = "\t{} ({}){};// {}".format(method[0], retType, selname, addr)

        print(line)

    # result.AppendMessage("command is still developing. please wait...\n")

    return parser
Ejemplo n.º 14
0
def pblock(debugger, command, exe_ctx, result, internal_dict):
    command_args = shlex.split(command, posix=False)

    _ = exe_ctx.target
    _ = exe_ctx.thread

    block_addr_raw = command_args[0]
    block_addr = utils.convertToInt(block_addr_raw)
    if block_addr:
        utils.ILOG("block addr:{}".format(hex(block_addr)))
    else:
        utils.ELOG("block addr format err:{}".format(block_addr_raw))
        return

    header = '''
    enum {
        BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
        BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code
        BLOCK_IS_GLOBAL =         (1 << 28),
        BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE
        BLOCK_HAS_SIGNATURE =     (1 << 30),
    };

    struct Block_literal_1 {
        void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
        int flags;
        int reserved;
        void (*invoke)(void *, ...);
        struct Block_descriptor_1 {
            unsigned long int reserved; // NULL
            unsigned long int size;         // sizeof(struct Block_literal_1)
            // optional helper functions
            void (*copy_helper)(void *dst, void *src);     // IFF (1<<25)
            void (*dispose_helper)(void *src);             // IFF (1<<25)
            // required ABI.2010.3.16
            const char *signature;                         // IFF (1<<30)
        } *descriptor;
        // imported variables
    };
    '''

    code = header
    code += 'struct Block_literal_1 real = *((struct Block_literal_1 *)(void*){});'.format(
        block_addr)
    code += '''
    NSString* ret = @"";
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:[NSNumber numberWithLong:(long)real.invoke] forKey:@"invoke"];

#if 0
    if (real.flags & BLOCK_HAS_SIGNATURE) {
        char *signature;
        if (real.flags & BLOCK_HAS_COPY_DISPOSE) {
            signature = (char *)(real.descriptor)->signature;
        } else {
            signature = (char *)(real.descriptor)->copy_helper;
        }
        
        NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:signature];
        NSMutableArray *types = [NSMutableArray array];
        
        [types addObject:[NSString stringWithUTF8String:(char *)[sig methodReturnType]]];
        
        for (NSUInteger i = 0; i < sig.numberOfArguments; i++) {
            char *type = (char *)[sig getArgumentTypeAtIndex:i];
            [types addObject:[NSString stringWithUTF8String:type]];
        }
        
        [dict setObject:types forKey:@"signature"];
    }
    
    NSMutableArray* sigArr = dict[@"signature"];
    
    if(!sigArr){
        ret = [NSString stringWithFormat:@"Imp: 0x%lx", [dict[@"invoke"] longValue]];
    }else{
        NSMutableString* sig = [NSMutableString stringWithFormat:@"%@ ^(", decode(sigArr[0])];
        for (int i = 2; i < sigArr.count; i++) {
            if(i == sigArr.count - 1){
                [sig appendFormat:@"%@", decode(sigArr[i])];
            }else{
                [sig appendFormat:@"%@ ,", decode(sigArr[i])];
            }
        }
        [sig appendString:@");"];
        ret = [NSString stringWithFormat:@"Imp: 0x%lx    Signature: %s", [dict[@"invoke"] longValue], [sig UTF8String]];
    }
    ret
#else
    dict
#endif
    '''
    ret = utils.exe_script(debugger, code)

    print(ret)