Exemplo n.º 1
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
Exemplo n.º 2
0
def get_all_class_plus_load_methods(debugger):
    command_script = '@import Foundation;' 
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    unsigned int c_size = 0;
    const char *path = (char *)[[[NSBundle mainBundle] executablePath] UTF8String];
    const char **allClasses = (const char **)objc_copyClassNamesForImage(path, &c_size);

    for (int i = 0; i < c_size; i++) {
        Class cls = objc_getClass(allClasses[i]);
        unsigned int cm_size = 0;
        struct objc_method **classMethods = (struct objc_method **)class_copyMethodList((Class)objc_getMetaClass((const char *)class_getName(cls)), &cm_size);

        for (int k = 0; k < cm_size; k++) {
            struct objc_method * meth = classMethods[k];
            id implementation = (id)method_getImplementation(meth);
            NSString* cm_name = NSStringFromSelector((SEL)method_getName(meth));
            if([cm_name isEqualToString:@"load"]){
                [retStr appendString:(id)[@((uintptr_t)implementation) stringValue]];
                [retStr appendString:@","];
            }
        }
        free(classMethods);
    }
    free(allClasses);
    retStr
    '''
    return utils.exe_script(debugger, command_script)
Exemplo n.º 3
0
def get_main_image_macho_header(debugger):
    command_script = r''' 

    typedef integer_t       cpu_type_t;
    typedef integer_t       cpu_subtype_t;
    typedef integer_t       cpu_threadtype_t;

    struct mach_header_64 {
        uint32_t    magic;      /* mach magic number identifier */
        cpu_type_t  cputype;    /* cpu specifier */
        cpu_subtype_t   cpusubtype; /* machine specifier */
        uint32_t    filetype;   /* type of file */
        uint32_t    ncmds;      /* number of load commands */
        uint32_t    sizeofcmds; /* the size of all the load commands */
        uint32_t    flags;      /* flags */
        uint32_t    reserved;   /* reserved */
    };
    struct mach_header_64* header = (struct mach_header_64*)_dyld_get_image_header(0);

    uint64_t header_int = (uint64_t)header;

    header_int
    '''
    # is in executable path?
    ret = utils.exe_script(debugger, command_script)
    return hex(int(ret, 10))
Exemplo n.º 4
0
def is_main_module_from_address(target, debugger, address):
    #  get moduleName of address
    addr = target.ResolveLoadAddress(address)
    moduleName = addr.module.file.basename
    modulePath = str(addr.module.file)
    #  get executable path
    getExecutablePathScript = r''' 
    const char *path = (char *)[[[NSBundle mainBundle] executablePath] UTF8String];
    path
    '''
    # is in executable path?
    path = utils.exe_script(debugger, getExecutablePathScript)
    appDir = os.path.dirname(path.strip()[1:-1])

    if not moduleName or not str(path):
        return False

    if appDir in modulePath:
        return True

    else:
        return False

    if moduleName in str(path):
        return True
    else:
        return False
Exemplo 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
Exemplo n.º 6
0
def get_address_info_by_address(debugger, address):
    command_script = 'void * targetAddr = (void*)' + address + ';'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    typedef struct dl_info {
        const char      *dli_fname;     /* Pathname of shared object */
        void            *dli_fbase;     /* Base address of shared object */
        const char      *dli_sname;     /* Name of nearest symbol */
        void            *dli_saddr;     /* Address of nearest symbol */
    } Dl_info;

    Dl_info dl_info;

    dladdr(targetAddr, &dl_info);

    char* module_path = (char*)dl_info.dli_fname;
    uintptr_t module_base = (uintptr_t)dl_info.dli_fbase;
    char* symbol_name = (char*)dl_info.dli_sname;
    uintptr_t symbol_addr = (uintptr_t)dl_info.dli_saddr;


    [retStr appendString:@"Module  path: "];
    [retStr appendString:@(module_path)];
    [retStr appendString:@"\nModule  base: "];
    [retStr appendString:(id)[@(module_base) stringValue]];

    long slide = 0;
    NSString* targetModulePath = @(module_path);
    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);
        slide = (long)_dyld_get_image_vmaddr_slide(i);
        uintptr_t baseAddr = (uintptr_t)_dyld_get_image_header(i);
        NSString* curModuleName = @(curModuleName_cstr);
        if([curModuleName isEqualToString:targetModulePath]) {
            [retStr appendString:@"\nModule slide: "];
            [retStr appendString:(id)[@(slide) stringValue]];
            break;
        }
    }
    [retStr appendString:@"\ntarget  addr: "];
    [retStr appendString:(id)[@((uintptr_t)targetAddr) stringValue]];

    uintptr_t target_file_addr = (uintptr_t)((uint64_t)targetAddr - slide);
    [retStr appendString:@"\nFile    addr: "];
    [retStr appendString:(id)[@(target_file_addr) stringValue]];

    [retStr appendString:@"\nSymbol  name: "];
    [retStr appendString:@(symbol_name)];
    [retStr appendString:@"\nSymbol  addr: "];
    [retStr appendString:(id)[@(symbol_addr) stringValue]];
    
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    return utils.hex_int_in_str(retStr)
Exemplo n.º 7
0
def get_main_image_path(debugger):

    command_script = r''' 
    const char *path = (char *)[[[NSBundle mainBundle] executablePath] UTF8String];
    path
    '''
    # is in executable path?
    ret = utils.exe_script(debugger, command_script)
    ret = ret.strip()
    return ret[1:-1]
Exemplo n.º 8
0
def get_func_info_by_name(debugger, funcName):
    command_script = 'const char * func_name = "' + funcName + '";'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    #define RTLD_LAZY   0x1
    #define RTLD_NOW    0x2
    #define RTLD_LOCAL  0x4
    #define RTLD_GLOBAL 0x8

    typedef struct dl_info {
        const char      *dli_fname;     /* Pathname of shared object */
        void            *dli_fbase;     /* Base address of shared object */
        const char      *dli_sname;     /* Name of nearest symbol */
        void            *dli_saddr;     /* Address of nearest symbol */
    } Dl_info;

    Dl_info dl_info;

    void* handle = (void*)dlopen(0, RTLD_GLOBAL | RTLD_NOW);
    void* target_ptr = (void*)dlsym(handle, func_name);

    if(target_ptr){
        uintptr_t target_addr = (uintptr_t)target_ptr;
        
        dladdr(target_ptr, &dl_info);
        
        char* module_path = (char*)dl_info.dli_fname;
        uintptr_t module_base = (uintptr_t)dl_info.dli_fbase;
        char* symbol_name = (char*)dl_info.dli_sname;
        uintptr_t symbol_addr = (uintptr_t)dl_info.dli_saddr;
        

        [retStr appendString:@"Func   name: "];
        [retStr appendString:@((char*)func_name)];
        [retStr appendString:@"\nFunc   addr: "];
        [retStr appendString:(id)[@(target_addr) stringValue]];
        
        [retStr appendString:@"\nModule Path: "];
        [retStr appendString:@(module_path)];
        [retStr appendString:@"\nModule base: "];
        [retStr appendString:(id)[@(module_base) stringValue]];
        [retStr appendString:@"\nSymbol name: "];
        [retStr appendString:@(symbol_name)];
        [retStr appendString:@"\nSymbol addr: "];
        [retStr appendString:(id)[@(symbol_addr) stringValue]];
    
    }else{
        [retStr appendString:@"[-] dlsym not found symbol:"];
        [retStr appendString:@((char*)func_name)];
    }
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    return utils.hex_int_in_str(retStr)
Exemplo n.º 9
0
def objc_obj_name(debugger, obj_addr):
    command_script = '@import Foundation;NSObject* obj = (NSObject*)' + obj_addr + ';'
    command_script += r'''    
    Class clz = [obj class];
    const char * clz_name = (const char *)class_getName(clz);
    NSString* clzName = [NSString stringWithUTF8String:clz_name];
    clzName
    '''
    retStr = utils.exe_script(debugger, command_script)

    return str(retStr.strip())
Exemplo n.º 10
0
def get_userdefaults_info_by_key(debugger, key):
    command_script = r'''
    NSArray *keys = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys];
    NSArray *values = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allValues];
    
    
    NSMutableDictionary *retDic = [NSMutableDictionary dictionaryWithObjects:values forKeys:keys]

    retDic
    '''
    return utils.exe_script(debugger, command_script)
Exemplo n.º 11
0
def get_main_image_path(debugger):
    command_script = '@import Foundation;' 
    command_script += r'''

    // const char *path = (char *)[[[NSBundle mainBundle] executablePath] UTF8String];
    id bundle = objc_msgSend((Class)objc_getClass("NSBundle"), @selector(mainBundle));
    id exePath = objc_msgSend((id)bundle, @selector(executablePath));
    const char *path  = (char *)objc_msgSend((id)exePath, @selector(UTF8String));
    
    path
    '''
    retStr = utils.exe_script(debugger, command_script)
    return retStr
Exemplo n.º 12
0
def objc_dump_ivars(debugger, obj_addr):
    command_script = '@import Foundation;NSObject* obj = (NSObject*)' + obj_addr + ';'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    typedef struct objc_ivar *Ivar;

    Class clz = [obj class];
    unsigned int count = 0;
    Ivar *vars = (Ivar *)class_copyIvarList(clz, &count);

    for (int i=0; i<count; i++) {
        Ivar var = vars[i];
        long offset = (long)ivar_getOffset(var);
        NSString* varName = [NSString stringWithUTF8String:(const char *)ivar_getName(var)];
        NSString* varTypeStr = [NSString stringWithUTF8String:(const char *)ivar_getTypeEncoding(var)];

        //NSString* dumpStr = [NSString stringWithFormat:@"-> %@ %@; // %p -> %p", ParseTypeString(varTypeStr)[0], varName, varAddr, *varAddr];
        void** varAddr = (void**)((unsigned char *)(__bridge void *)obj + offset);
        
        [retStr appendString:varName];
        [retStr appendString:@","];
        [retStr appendString:varTypeStr];
        [retStr appendString:@","];
        [retStr appendString:(id)[@((long)varAddr) stringValue]];
        [retStr appendString:@"||"];
    }
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    arr = retStr.strip().split("||")

    retArr = []

    for item in arr:
        if len(item) <= 0:
            continue
        info = item.split(",")

        if len(info) != 3:
            continue

        retArr.append([info[0], info[1], hex(utils.convertToInt(info[2]))])

    return retArr
Exemplo n.º 13
0
def get_all_image_of_app(debugger, appDir):
    command_script = '@import Foundation;NSString* appDir = @"' + appDir + '";'
    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:appDir]) {
            [retStr appendString:(id)[@(i) stringValue]];
            [retStr appendString:@","];
            [retStr appendString:@(curModuleName_cstr)];
            [retStr appendString:@"#"];
        }
    }
    retStr
    '''
    ret = utils.exe_script(debugger, command_script)
    return ret
Exemplo n.º 14
0
def get_all_method_address_of_class(debugger, classname):

    command_script = '@import Foundation;const char* className = "' + classname + '";' 

    command_script += r'''
    //NSMutableArray *mAddrArr = [NSMutableArray array];
    NSMutableString* retStr = [NSMutableString string];

    unsigned int m_size = 0;
    Class cls = objc_getClass(className);
    struct objc_method ** metholds = (struct objc_method **)class_copyMethodList(cls, &m_size);
    

    for (int j = 0; j < m_size; j++) {
        struct objc_method * meth = metholds[j];
        id implementation = (id)method_getImplementation(meth);
        NSString* m_name = NSStringFromSelector((SEL)method_getName(meth));
        
        //[mAddrArr addObject:(id)[@((uintptr_t)implementation) stringValue]];
        NSNumber* implementationNum =  [NSNumber numberWithUnsignedLongLong:(uintptr_t)implementation];
        [retStr appendString:(id)[implementationNum stringValue]];
        [retStr appendString:@"-"];
    }

    unsigned int cm_size = 0;
    struct objc_method **classMethods = (struct objc_method **)class_copyMethodList((Class)objc_getMetaClass((const char *)class_getName(cls)), &cm_size);
    for (int k = 0; k < cm_size; k++) {
        struct objc_method * meth = classMethods[k];
        id implementation = (id)method_getImplementation(meth);
        NSString* cm_name = NSStringFromSelector((SEL)method_getName(meth));
        //[mAddrArr addObject:(id)[@((uintptr_t)implementation) stringValue]];
        NSNumber* implementationNum =  [NSNumber numberWithUnsignedLongLong:(uintptr_t)implementation];
        [retStr appendString:(id)[implementationNum stringValue]];
        [retStr appendString:@"-"];
    }
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    return retStr
Exemplo n.º 15
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)
Exemplo n.º 16
0
def get_process_module_slide(debugger, modulePath):
    command_script = '@import Foundation;' 
    command_script += r'''
    uint32_t count = (uint32_t)_dyld_image_count();
    NSMutableString* retStr = [NSMutableString string];
    uint32_t idx = 0;
    NSString* image_name = @"";
    const char *path = (char *)[[[NSBundle mainBundle] executablePath] UTF8String];
    '''
   
    if modulePath:
        command_script += 'NSString* modulePath = @"{}"\n'.format(modulePath)
    else:
        command_script += 'NSString* modulePath = [[NSString alloc] initWithUTF8String:path];'

    command_script += r'''
    NSString* imagePath = modulePath;
    for(uint32_t i = 0; i < count; i++){
        const char* imageName = (const char*)_dyld_get_image_name(i);
        NSString* imageNameStr = [[NSString alloc] initWithUTF8String:imageName];
        if([imageNameStr isEqualToString:imagePath]){
            idx = i;
            image_name = imageNameStr;
            break;
        }
    }
    uintptr_t slide =  (uintptr_t)_dyld_get_image_vmaddr_slide(idx);
    NSString *slideStr = [@(slide) stringValue];
    [retStr appendString:image_name];
    [retStr appendString:@"#"];
    [retStr appendString:slideStr];

    slideStr
    '''
    slide = utils.exe_script(debugger, command_script)
    return slide
Exemplo n.º 17
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
Exemplo n.º 18
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)
Exemplo n.º 19
0
def symbolish_stack_trace_frame(debugger, target, thread):
    frame_string = ''
    idx = 0

    for f in thread.frames:
        function = f.GetFunction()
        # mem address
        load_addr = f.addr.GetLoadAddress(target)

        if not function:
            # file address
            file_addr = f.addr.GetFileAddress()
            # offset
            start_addr = f.GetSymbol().GetStartAddress().GetFileAddress()
            symbol_offset = file_addr - start_addr
            modulePath = str(f.addr.module.file)

            # is_main_module_from_address? findname : symbol name
            if is_main_module_from_address(target, debugger, load_addr):
                if idx + 2 == len(thread.frames):
                    metholdName = 'main + ' + str(symbol_offset)
                else:
                    command_script = find_symbol_from_address_script(
                        load_addr, modulePath)
                    one = utils.exe_script(debugger, command_script)
                    # is set the block file path
                    if BLOCK_JSON_FILE and len(BLOCK_JSON_FILE) > 0:
                        two = find_block_symbol_from_adress(file_addr)
                        response = choose_best(one, two)
                    else:
                        response = one
                    response = check_if_analysis_error(response)
                    metholdName = str(response).replace("\n", "")
                frame_string += '  frame #{num}: [file:{f_addr} mem:{m_addr}] {mod}`{symbol}\n'.format(
                    num=idx,
                    f_addr=colorme.attr_str(str(hex(file_addr)), 'cyan'),
                    m_addr=colorme.attr_str(hex(load_addr), 'grey'),
                    mod=colorme.attr_str(str(f.addr.module.file.basename),
                                         'yellow'),
                    symbol=colorme.attr_str(metholdName, 'green'))
            else:
                metholdName = f.addr.symbol.name
                frame_string += '  frame #{num}: [file:{f_addr} mem:{m_addr}] {mod}`{symbol} + {offset} \n'.format(
                    num=idx,
                    f_addr=colorme.attr_str(str(hex(file_addr)), 'cyan'),
                    m_addr=colorme.attr_str(hex(load_addr), 'grey'),
                    mod=colorme.attr_str(str(f.addr.module.file.basename),
                                         'yellow'),
                    symbol=metholdName,
                    offset=symbol_offset)
        else:
            frame_string += '  frame #{num}: {addr} {mod}`{func} at {file}\n'.format(
                num=idx,
                addr=hex(load_addr),
                mod=colorme.attr_str(str(f.addr.module.file.basename),
                                     'yellow'),
                func='%s [inlined]' % function if f.IsInlined() else function,
                file=f.addr.symbol.name)

        idx = idx + 1
    return frame_string
Exemplo n.º 20
0
def dump_macho_to_file(debugger, machoIdx, machoPath, fix_addr=0):
    command_script_header = r'''
    // header
    #define MH_MAGIC    0xfeedface  /* the mach magic number */
    #define MH_CIGAM    0xcefaedfe  /* NXSwapInt(MH_MAGIC) */

    #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
    #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */

    #define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */
    #define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */

    #define FAT_MAGIC   0xcafebabe
    #define FAT_CIGAM   0xbebafeca  /* NXSwapLong(FAT_MAGIC) */

    #define O_RDONLY        0x0000          /* open for reading only */
    #define O_WRONLY        0x0001          /* open for writing only */
    #define O_RDWR          0x0002          /* open for reading and writing */
    #define O_ACCMODE       0x0003          /* mask for above modes */

    #define SEEK_CUR    1   /* set file offset to current plus offset */
    #define SEEK_SET    0

    #define O_CREAT         0x0200          /* create if nonexistant */
    #define O_TRUNC         0x0400          /* truncate to zero length */
    #define O_EXCL          0x0800          /* error if already exists */

    #define SEEK_END    2
    // #define errno (*__error())

    typedef long long               __int64_t;
    typedef __int64_t       __darwin_off_t;         /* [???] Used for file sizes */
    typedef __darwin_off_t          off_t;

    typedef int                     integer_t;
    typedef integer_t       cpu_type_t;
    typedef integer_t       cpu_subtype_t;
    typedef integer_t       cpu_threadtype_t;

    

    #define swap32(value) (((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24) )

    struct mach_header {
        uint32_t    magic;      /* mach magic number identifier */
        cpu_type_t  cputype;    /* cpu specifier */
        cpu_subtype_t   cpusubtype; /* machine specifier */
        uint32_t    filetype;   /* type of file */
        uint32_t    ncmds;      /* number of load commands */
        uint32_t    sizeofcmds; /* the size of all the load commands */
        uint32_t    flags;      /* flags */
    };

    struct mach_header_64 {
        uint32_t    magic;      /* mach magic number identifier */
        cpu_type_t  cputype;    /* cpu specifier */
        cpu_subtype_t   cpusubtype; /* machine specifier */
        uint32_t    filetype;   /* type of file */
        uint32_t    ncmds;      /* number of load commands */
        uint32_t    sizeofcmds; /* the size of all the load commands */
        uint32_t    flags;      /* flags */
        uint32_t    reserved;   /* reserved */
    };

    struct load_command {
        uint32_t cmd;       /* type of load command */
        uint32_t cmdsize;   /* total size of command in bytes */
    };

    struct encryption_info_command {
       uint32_t cmd;        /* LC_ENCRYPTION_INFO */
       uint32_t cmdsize;    /* sizeof(struct encryption_info_command) */
       uint32_t cryptoff;   /* file offset of encrypted range */
       uint32_t cryptsize;  /* file size of encrypted range */
       uint32_t cryptid;    /* which enryption system,0 means not-encrypted yet */
    };

    struct fat_header {
        uint32_t    magic;      /* FAT_MAGIC or FAT_MAGIC_64 */
        uint32_t    nfat_arch;  /* number of structs that follow */
    };

    struct fat_arch {
        cpu_type_t  cputype;    /* cpu specifier (int) */
        cpu_subtype_t   cpusubtype; /* machine specifier (int) */
        uint32_t    offset;     /* file offset to this object file */
        uint32_t    size;       /* size of this object file */
        uint32_t    align;      /* alignment as a power of 2 */
    };
    '''
    command_script_init = 'struct mach_header* mh = (struct mach_header*)_dyld_get_image_header({});'.format(
        machoIdx)
    command_script_init += 'const char *path = "{}";'.format(machoPath)
    command_script_init += 'uint64_t main_addr = (uint64_t){};'.format(
        fix_addr)

    command_script = command_script_header + command_script_init

    command_script += r'''
    struct load_command *lc;
    struct encryption_info_command *eic;
    struct fat_header *fh;
    struct fat_arch *arch;
    char x_buffer[1024];
    char rpath[4096],npath[4096]; /* should be big enough for PATH_MAX */
    unsigned int fileoffs = 0, off_cryptid = 0, restsize;
    int i,fd,outfd,r,n,toread;
    char *tmp;
    
    if ((char*)realpath(path, rpath) == NULL) {
        strlcpy(rpath, path, sizeof(rpath));
    }
    /* extract basename */
    tmp = (char*)strrchr(rpath, '/');
    //printf("\n\n");
    if (tmp == NULL) {
        printf("[-] Unexpected error with filename.\n");
        _exit(1);
    } else {
        printf("[+] Dumping %s\n", tmp+1);
    }

    /* detect if this is a arm64 binary */
    if (mh->magic == MH_MAGIC_64) {
        lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header_64));
        printf("[+] detected 64bit ARM binary in memory.\n");
    } else { /* we might want to check for other errors here, too */
        lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header));
        printf("[+] detected 32bit ARM binary in memory.\n");
    }
    /* searching all load commands for an LC_ENCRYPTION_INFO load command */
    BOOL is_image_crypted = NO;
    for (i=0; i<mh->ncmds; i++) {
        if (lc->cmd == LC_ENCRYPTION_INFO || lc->cmd == LC_ENCRYPTION_INFO_64) {

            eic = (struct encryption_info_command *)lc;
            /* If this load command is present, but data is not crypted then exit */
            if (eic->cryptid == 0) {
                break;
            }
            is_image_crypted = YES;
            off_cryptid=(off_t)((uint8_t*)&eic->cryptid - (uint8_t*)mh);
            
            printf("[+] offset to cryptid found: @%p(from %p) = %x\n", &eic->cryptid, mh, off_cryptid);
            
            printf("[+] Found encrypted data at address %08x of length %u bytes - type %u.\n", eic->cryptoff, eic->cryptsize, eic->cryptid);
            
            printf("[+] Opening %s for reading.\n", rpath);

            fd = (int)open(rpath, O_RDONLY);
            if (fd == -1) {
                printf("[-] Failed opening.\n");
                break;
            }
            printf("[+] Reading header\n");
            n = (long)read(fd, (void *)x_buffer, sizeof(x_buffer));
            if (n != sizeof(x_buffer)) {
                printf("[W] Warning read only %d bytes\n", n);
            }

            printf("[+] Detecting header type\n");
            fh = (struct fat_header *)x_buffer;

            /* Is this a FAT file - we assume the right endianess */
            if (fh->magic == FAT_CIGAM) {
                printf("[+] Executable is a FAT image - searching for right architecture\n");
                arch = (struct fat_arch *)&fh[1];
                for (i=0; i<swap32(fh->nfat_arch); i++) {
                    if ((mh->cputype == swap32(arch->cputype)) && (mh->cpusubtype == swap32(arch->cpusubtype))) {
                        fileoffs = swap32(arch->offset);
                        printf("[+] Correct arch is at offset %u in the file\n", fileoffs);
                        break;
                    }
                    arch++;
                }
                if (fileoffs == 0) {
                    printf("[-] Could not find correct arch in FAT image\n");
                    _exit(1);
                }
            } else if (fh->magic == MH_MAGIC || fh->magic == MH_MAGIC_64) {
                printf("[+] Executable is a plain MACH-O image\n");
            } else {
                printf("[-] Executable is of unknown type\n");
                break;
            }

            // NSDocumentDirectory == 9 NSUserDomainMask == 1   
            NSString *docPath = ((NSArray*)NSSearchPathForDirectoriesInDomains(9, 1, YES))[0];
            
            strlcpy(npath, docPath.UTF8String, sizeof(npath));
            strlcat(npath, tmp, sizeof(npath));
            strlcat(npath, ".decrypted", sizeof(npath));
            strlcpy(x_buffer, npath, sizeof(x_buffer));
            printf("[+] Opening %s for writing.\n", npath);

            outfd = (int)open(npath, O_RDWR|O_CREAT|O_TRUNC, 0644);
            if (outfd == -1) {
                if ((int)strncmp("/private/var/mobile/Applications/", rpath, 33) == 0) {
                    printf("[-] Failed opening. Most probably a sandbox issue. Trying something different.\n");
                    
                    /* create new name */
                    strlcpy(npath, "/private/var/mobile/Applications/", sizeof(npath));
                    tmp = (char*)strchr(rpath+33, '/');
                    if (tmp == NULL) {
                        printf("[-] Unexpected error with filename.\n");
                        return;
                    }
                    tmp++;
                    *tmp++ = 0;
                    strlcat(npath, rpath+33, sizeof(npath));
                    strlcat(npath, "tmp/", sizeof(npath));
                    strlcat(npath, x_buffer, sizeof(npath));
                    printf("[+] Opening %s for writing.\n", npath);
                    outfd = (int)open(npath, O_RDWR|O_CREAT|O_TRUNC, 0644);
                }
                if (outfd == -1) {
                    printf("[-] Failed opening\n");
                    break;
                }
            }

            /* calculate address of beginning of crypted data */
            n = fileoffs + eic->cryptoff;
            
            restsize = (off_t)lseek(fd, 0, SEEK_END) - n - eic->cryptsize;
            (off_t)lseek(fd, 0, SEEK_SET);
            
            printf("[+] Copying the not encrypted start of the file\n");
            /* first copy all the data before the encrypted data */
            while (n > 0) {
                toread = (n > sizeof(x_buffer)) ? sizeof(x_buffer) : n;
                r = (long)read(fd, x_buffer, toread);
                if (r != toread) {
                    printf("[-] Error reading file\n");
                    return;
                }
                n -= r;
                
                r = (long)write(outfd, x_buffer, toread);
                if (r != toread) {
                    printf("[-] Error writing file\n");
                    return;
                }
            }

            /* now write the previously encrypted data */

            printf("[+] Dumping the decrypted data into the file\n");

            // (unsigned char *)mh + eic->cryptoff

            
            unsigned char * tmp_buf = (unsigned char *)malloc(eic->cryptsize);
            unsigned char * tmp_ptr = (unsigned char *)((unsigned char *)mh + eic->cryptoff);

            for(int i = 0; i < eic->cryptsize; i ++){
                if(main_addr != 0 && main_addr == (uint64_t)tmp_ptr){
                    tmp_buf[i] = 0xF6;
                    tmp_buf[++i] = 0x57;
                    tmp_buf[++i] = 0xBD;
                    tmp_buf[++i] = 0xA9;
                    tmp_ptr += 4;
                    continue;
                }
                tmp_buf[i] = *tmp_ptr;
                tmp_ptr ++;
            }
            

            r = (long)write(outfd, (unsigned char *)tmp_buf, eic->cryptsize);
            if (r != eic->cryptsize) {
                uint64_t flag = (uint64_t)(mh);
                // printf("Error no.%d: %s\n", errno, strerror(errno));
                printf("[-] read memory from:0x%lx size:%ld\n", mh + eic->cryptoff, eic->cryptsize);
                printf("[-] Error writing file r=%lx offset=%lx size=%lx flag=%lx\n", r,eic->cryptoff, eic->cryptsize, flag);
                return;
            }

            free(tmp_buf);
            
            /* and finish with the remainder of the file */
            n = restsize;
            (off_t)lseek(fd, eic->cryptsize, SEEK_CUR);
            printf("[+] Copying the not encrypted remainder of the file\n");
            while (n > 0) {
                toread = (n > sizeof(x_buffer)) ? sizeof(x_buffer) : n;
                r = (long)read(fd, x_buffer, toread);
                if (r != toread) {
                    printf("[-] Error reading file\n");
                    return;
                }
                n -= r;
                
                r = (long)write(outfd, x_buffer, toread);
                if (r != toread) {
                    printf("[-] Error writing file\n");
                    return;
                }
            }
            if (off_cryptid) {
                uint32_t x_zero=0;
                off_cryptid+=fileoffs;
                printf("[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset %x\n", off_cryptid);
                if (((off_t)lseek(outfd, off_cryptid, SEEK_SET)) != off_cryptid || (long)write(outfd, &x_zero, 4) != 4) {
                    printf("[-] Error writing cryptid value\n");
                }
            }
            
            printf("[+] Closing original file\n");
            close(fd);
            printf("[+] Closing dump file\n");
            close(outfd);
            break;
        }

        lc = (struct load_command *)((unsigned char *)lc+lc->cmdsize);
    }
    NSMutableString* retStr = [NSMutableString string];
    if(is_image_crypted){
        printf("[*] This mach-o file decrypted done.\n");
        [retStr appendString:@"[+] dump macho file at:"];
        [retStr appendString:@(npath)];
    }else{
        printf("[*] this image is not crypted\n");
        [retStr appendString:@"[+] this macho file at:"];
        [retStr appendString:@(rpath)];
    }

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

    return ret
Exemplo n.º 21
0
def choose(debugger, classname):
    command_script = 'NSString * className = @"' + classname + '";' 
    command_script += r'''
    
    // define
    #define KERN_SUCCESS 0
    
    // typedef
    typedef unsigned long       uintptr_t;

    
    #define MALLOC_PTR_IN_USE_RANGE_TYPE    1
    typedef int kern_return_t;
    typedef unsigned int mach_port_t;
    typedef mach_port_t     task_t;
    
    typedef uintptr_t       vm_offset_t;
    typedef vm_offset_t         vm_address_t;
    typedef uintptr_t       vm_size_t;
    typedef struct {
        vm_address_t    address;
        vm_size_t       size;
    } vm_range_t;
    
    typedef kern_return_t (*memory_reader_t)(task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory);
    typedef void (*vm_range_recorder_t)(task_t task, void *baton, unsigned type, vm_range_t *range, unsigned size);
    typedef struct malloc_introspection_t {
        kern_return_t (*enumerator)(task_t task, void *, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t recorder); /* enumerates all the malloc pointers in use */
    } malloc_introspection_t;
    
    typedef struct _malloc_zone_t {
        void  *reserved1; 
        void  *reserved2; 
        size_t  (*size)(struct _malloc_zone_t *zone, const void *ptr); 
        void  *(*malloc)(struct _malloc_zone_t *zone, size_t size);
        void  *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); 
        void  *(*valloc)(struct _malloc_zone_t *zone, size_t size); 
        void  (*free)(struct _malloc_zone_t *zone, void *ptr);
        void  *(*realloc)(struct _malloc_zone_t *zone, void *ptr, size_t size);
        void  (*destroy)(struct _malloc_zone_t *zone); 
        const char  *zone_name;
        unsigned  (*batch_malloc)(struct _malloc_zone_t *zone, size_t size, void **results, unsigned num_requested); 
        void  (*batch_free)(struct _malloc_zone_t *zone, void **to_be_freed, unsigned num_to_be_freed); 
        struct malloc_introspection_t *introspect;
        unsigned  version;
        void *(*memalign)(struct _malloc_zone_t *zone, size_t alignment, size_t size);
        void (*free_definite_size)(struct _malloc_zone_t *zone, void *ptr, size_t size);
        size_t  (*pressure_relief)(struct _malloc_zone_t *zone, size_t goal);
    } malloc_zone_t;
    

    struct XZChoice {
        NSMutableArray * query_; // std::set<Class> query_;
        NSMutableArray * result_; // std::set<id> result_;
    };

    struct XZObjectStruct {
        Class isa_;
    };
    
    // function memory_reader_t
    
    memory_reader_t task_peek = [](task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory) -> kern_return_t {
        *local_memory = (void*) remote_address;
        return KERN_SUCCESS;
    };
    
    // function copy_class_list: get the class list
    typedef Class * (*copy_class_list_t)(size_t &size);
    copy_class_list_t copy_class_list = [](size_t &size) -> Class *{
        size = (size_t)objc_getClassList(NULL, 0);
        Class * data = (Class *)(malloc(sizeof(Class) * size));
        for (;;) {
            size_t writ = (size_t)objc_getClassList(data, (int)size);
            if (writ <= size) {
                size = writ;
                return data;
            }
            
            Class * copy = (Class *)(realloc(data, sizeof(Class) * writ));
            if (copy == NULL) {
                free(data);
                return NULL;
            }
            data = copy;
            size = writ;
        }
    }
    // function void choose_(task_t task, void *baton, unsigned type, vm_range_t *ranges, unsigned count)
    typedef void (*choose__t)(task_t task, void *baton, unsigned type, vm_range_t *ranges, unsigned count);
    choose__t choose_ = [](task_t task, void *baton, unsigned type, vm_range_t *ranges, unsigned count) -> void {
        XZChoice * choiz = (struct XZChoice *)(baton);
        for (unsigned i = 0; i < count; ++i) {
            vm_range_t &range = ranges[i];
            void * data = (void *)(range.address);
            size_t size = range.size;
            if (size < sizeof(XZObjectStruct))
                continue;
            
            uintptr_t * pointers = (uintptr_t *)(data);
    #ifdef __arm64__
            struct objc_class * isa = (struct objc_class *)(pointers[0] & 0x1fffffff8);
    #else
            struct objc_class * isa = (struct objc_class *)(pointers[0]);
    #endif
            //uint64_t p = (uint64_t)isa;
            //[choiz->result_ addObject:[@(p) stringValue]];

            size_t needed;
            for(unsigned i=0; i < [choiz->query_ count]; i++){
                struct objc_class * result = (struct objc_class *)[choiz->query_ objectAtIndex:i];
                uint64_t result_intv = (uint64_t)result;
                uint64_t isa_intv = (uint64_t)isa;
                uint64_t data_intv = (uint64_t)data;
                
                if(result_intv == isa_intv){
                    /*
                    NSMutableString* tmpStr = [NSMutableString string];
                    [tmpStr appendString:@"isa:"];
                    [tmpStr appendString:[@(isa_intv) stringValue]];
                    [tmpStr appendString:@"query:"];
                    [tmpStr appendString:[@(result_intv) stringValue]];
                    [tmpStr appendString:@"object:"];
                    [tmpStr appendString:[@(data_intv) stringValue]];
                    [choiz->result_ addObject:tmpStr];
                    continue;
                    */
                    
                    size_t boundary = 496;
                    
                    #ifdef __LP64__
                            boundary *= 2;
                    #endif
                    
                    needed = (size_t)class_getInstanceSize((Class)result));
                    if ((needed <= boundary && (needed + 15) / 16 * 16 != size) || (needed > boundary && (needed + 511) / 512 * 512 != size)){
                        continue;
                    }
                    [choiz->result_ addObject:(id)data];
                }
            }
        }
    }
    
    XZChoice choice;
    choice.query_ = (NSMutableArray*)[NSMutableArray array];
    choice.result_ = (NSMutableArray*)[NSMutableArray array];
    
    Class _class = NSClassFromString(className);
    size_t number;
    Class * classes = copy_class_list(number);
    
    for (size_t i = 0; i != number; ++i) {
        for (Class current = classes[i]; current != Nil; current = (Class)class_getSuperclass(current)) {
            if (current == _class) {
                [choice.query_ addObject:classes[i]];
                break;
            }
        }
    }
    free(classes);
    
    vm_address_t *zones = 0;
    unsigned int num_zones = 0;
    task_t task = 0;
    kern_return_t err = (kern_return_t)malloc_get_all_zones (task, task_peek, &zones, &num_zones);
    
    for (unsigned i = 0; i != num_zones; ++i) {
        const malloc_zone_t * zone = (const malloc_zone_t *)(zones[i]);
        if (zone == NULL || zone->introspect == NULL)
            continue;
        zone->introspect->enumerator((task_t)mach_task_self(), &choice, MALLOC_PTR_IN_USE_RANGE_TYPE, zones[i], task_peek, choose_);
    }

    NSArray* choosed = choice.result_;
    NSMutableString* retStr = [NSMutableString string];
    unsigned choosedSize = [choosed count];
    if(choosedSize == 0){

        [retStr appendString:@"Not found any object of class: "];
        [retStr appendString:className];

    }else{
        uint64_t objAdrr = (uint64_t)choosed;
        [retStr appendString:@"====>xia0LLDB NSArray Address: "];
        [retStr appendString:[@(objAdrr) stringValue]];
        [retStr appendString:@"\tsize: "];
        [retStr appendString:[@(choosedSize) stringValue]];
        [retStr appendString:@"\n"];
        [retStr appendString:@"|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | \n"];
        [retStr appendString:@"V  V  V  V  V  V  V  V  V  V  V  V  V  V  V  V  V  V  V  V \n"];

        for (unsigned i = 0; i != [choosed count]; ++i) {

            if([(NSObject*)([choosed objectAtIndex:i]) isKindOfClass:[NSString class]]){
                [retStr appendString: @"Now not support print the NSString, You can po it by yourself like below:"];
                [retStr appendString:@"\n1. p/x "];
                [retStr appendString:[@(objAdrr) stringValue]];
                [retStr appendString:@"\n2. po (NSArray*)above_hex_address_vaule : print the NSArray contain NSString"];
                [retStr appendString:@"\n3. po [(NSArray*)above_hex_address_vaule objectAtIndex:0] : print first NSString"];
                break;
            
            }else{

                uint64_t objAdrr = (uint64_t)[choosed objectAtIndex:i];
                [retStr appendString:@"======>xia0LLDB Object Address: "];
                [retStr appendString:[@(objAdrr) stringValue]];
                [retStr appendString:@"\n"];
                [retStr appendString:[(NSObject*)([choosed objectAtIndex:i]) description]];
            }
            
            [retStr appendString:@"\n"];
        }

    }

    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    return colorme.attr_str(utils.hex_int_in_str(retStr), 'green')
Exemplo n.º 22
0
def objc_dump_methods(debugger, classname):
    command_script = '@import Foundation;char* classname = (char*)\"' + classname + '\";'
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    typedef struct objc_method *Method;
   
    unsigned int m_size = 0;
    Class cls = objc_getClass(classname);
    struct objc_method ** metholds = (struct objc_method **)class_copyMethodList(cls, &m_size);
    
    for (int j = 0; j < m_size; j++) {
        struct objc_method * meth = metholds[j];
        id implementation = (id)method_getImplementation(meth);
        NSString* m_name = NSStringFromSelector((SEL)method_getName(meth));
        

        char buffer[100];
        buffer[0] = '\0';
        method_getReturnType (meth, buffer, sizeof(buffer));

        NSString* retTypeStr =[NSString stringWithUTF8String:buffer];


        //[mAddrArr addObject:(id)[@((uintptr_t)implementation) stringValue]];
        NSNumber* implementationNum =  [NSNumber numberWithUnsignedLongLong:(uintptr_t)implementation];
        [retStr appendString:@"-"];
        [retStr appendString:@","];
        [retStr appendString:m_name];
        [retStr appendString:@","];
        [retStr appendString:(id)[implementationNum stringValue]];
        [retStr appendString:@","];
        [retStr appendString:retTypeStr];
        [retStr appendString:@","];

        unsigned int argumentCount = (unsigned int)method_getNumberOfArguments (meth);
        for (int i = 2; i < argumentCount; i++) {
            method_getArgumentType (meth, i, buffer, sizeof(buffer));
            NSString* argTypeStr =[NSString stringWithUTF8String:buffer];
            [retStr appendString:argTypeStr];
            [retStr appendString:@","];
        }
        [retStr appendString:@"||"];
    }

    unsigned int cm_size = 0;
    struct objc_method **classMethods = (struct objc_method **)class_copyMethodList((Class)objc_getMetaClass((const char *)class_getName(cls)), &cm_size);
    for (int k = 0; k < cm_size; k++) {
        struct objc_method * meth = classMethods[k];
        id implementation = (id)method_getImplementation(meth);
        NSString* cm_name = NSStringFromSelector((SEL)method_getName(meth));

        char buffer[100];
        buffer[0] = '\0';
        method_getReturnType (meth, buffer, sizeof(buffer));

        NSString* retTypeStr =[NSString stringWithUTF8String:buffer];


        //[mAddrArr addObject:(id)[@((uintptr_t)implementation) stringValue]];
        NSNumber* implementationNum =  [NSNumber numberWithUnsignedLongLong:(uintptr_t)implementation];
        [retStr appendString:@"+"];
        [retStr appendString:@","];
        [retStr appendString:cm_name];
        [retStr appendString:@","];
        [retStr appendString:(id)[implementationNum stringValue]];
        [retStr appendString:@","];
        [retStr appendString:retTypeStr];
        [retStr appendString:@","];
        unsigned int argumentCount = (unsigned int)method_getNumberOfArguments (meth);
        for (int i = 2; i < argumentCount; i++) {
            method_getArgumentType (meth, i, buffer, sizeof(buffer));
            NSString* argTypeStr =[NSString stringWithUTF8String:buffer];
            [retStr appendString:argTypeStr];
            [retStr appendString:@","];
        }
        [retStr appendString:@"||"];
    }

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

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

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

        methodInfo = item.split(",")

        methodArr = []
        for val in methodInfo:
            if len(val) <= 0:
                continue
            methodArr.append(val)

        retArr.append(methodArr)

    return retArr
Exemplo n.º 23
0
def get_macho_entry_offset(debugger):
    command_script = '@import Foundation;' 
    command_script += r'''
    //NSMutableString* retStr = [NSMutableString string];

    #define MH_MAGIC_64 0xfeedfacf 
    #define LC_SEGMENT_64   0x19
    #define LC_REQ_DYLD     0x80000000
    #define LC_MAIN         (0x28|LC_REQ_DYLD)

    typedef int             integer_t;
    typedef integer_t       cpu_type_t;
    typedef integer_t       cpu_subtype_t;
    typedef integer_t       cpu_threadtype_t;

    struct mach_header_64 {
        uint32_t    magic;      /* mach magic number identifier */
        cpu_type_t  cputype;    /* cpu specifier */
        cpu_subtype_t   cpusubtype; /* machine specifier */
        uint32_t    filetype;   /* type of file */
        uint32_t    ncmds;      /* number of load commands */
        uint32_t    sizeofcmds; /* the size of all the load commands */
        uint32_t    flags;      /* flags */
        uint32_t    reserved;   /* reserved */
    };

    struct load_command {
        uint32_t cmd;       /* type of load command */
        uint32_t cmdsize;   /* total size of command in bytes */
    };

    typedef int             vm_prot_t;
    struct segment_command_64 { /* for 64-bit architectures */
        uint32_t    cmd;        /* LC_SEGMENT_64 */
        uint32_t    cmdsize;    /* includes sizeof section_64 structs */
        char        segname[16];    /* segment name */
        uint64_t    vmaddr;     /* memory address of this segment */
        uint64_t    vmsize;     /* memory size of this segment */
        uint64_t    fileoff;    /* file offset of this segment */
        uint64_t    filesize;   /* amount to map from the file */
        vm_prot_t   maxprot;    /* maximum VM protection */
        vm_prot_t   initprot;   /* initial VM protection */
        uint32_t    nsects;     /* number of sections in segment */
        uint32_t    flags;      /* flags */
    };

    struct section_64 { /* for 64-bit architectures */
        char        sectname[16];   /* name of this section */
        char        segname[16];    /* segment this section goes in */
        uint64_t    addr;       /* memory address of this section */
        uint64_t    size;       /* size in bytes of this section */
        uint32_t    offset;     /* file offset of this section */
        uint32_t    align;      /* section alignment (power of 2) */
        uint32_t    reloff;     /* file offset of relocation entries */
        uint32_t    nreloc;     /* number of relocation entries */
        uint32_t    flags;      /* flags (section type and attributes)*/
        uint32_t    reserved1;  /* reserved (for offset or index) */
        uint32_t    reserved2;  /* reserved (for count or sizeof) */
        uint32_t    reserved3;  /* reserved */
    };

    struct entry_point_command {
        uint32_t  cmd;  /* LC_MAIN only used in MH_EXECUTE filetypes */
        uint32_t  cmdsize;  /* 24 */
        uint64_t  entryoff; /* file (__TEXT) offset of main() */
        uint64_t  stacksize;/* if not zero, initial stack size */
    };

    int x_offset = 0;
    struct mach_header_64* header = (struct mach_header_64*)_dyld_get_image_header(0);

    if(header->magic != MH_MAGIC_64) {
        return ;
    }

    x_offset = sizeof(struct mach_header_64);
    int ncmds = header->ncmds;
    //uint64_t textStart = 0;
    //uint64_t textEnd = 0;
    uint64_t main_addr = 0;
    while(ncmds--) {
        /* go through all load command to find __TEXT segment*/
        struct load_command * lcp = (struct load_command *)((uint8_t*)header + x_offset);
        x_offset += lcp->cmdsize;
        if(lcp->cmd == LC_MAIN) {
            uintptr_t slide =  (uintptr_t)_dyld_get_image_vmaddr_slide(0);          
            struct entry_point_command* main_cmd = (struct entry_point_command*)lcp;
            main_addr = (uint64_t)slide + main_cmd->entryoff + 0x100000000;

            break;
        }
    }
    char ret[50];

    /*
    char textStartAddrStr[20];
    sprintf(textStartAddrStr, "0x%016lx", textStart);

    char textEndAddrStr[20];
    sprintf(textEndAddrStr, "0x%016lx", textEnd);


    char* splitStr = ",";
    strcpy(ret,textStartAddrStr);
    strcat(ret,splitStr);
    strcat(ret,textEndAddrStr);
    */

    sprintf(ret, "0x%016lx", main_addr);

    ret
    '''
    retStr = utils.exe_script(debugger, command_script)
    return retStr
Exemplo n.º 24
0
def get_macho_mod_init_first_func(debugger):
    command_script = '@import Foundation;'
    command_script += r'''
    //NSMutableString* retStr = [NSMutableString string];

    #define MH_MAGIC_64 0xfeedfacf 
    #define LC_SEGMENT_64   0x19
    typedef int                     integer_t;
    typedef integer_t       cpu_type_t;
    typedef integer_t       cpu_subtype_t;
    typedef integer_t       cpu_threadtype_t;

    struct mach_header_64 {
        uint32_t    magic;      /* mach magic number identifier */
        cpu_type_t  cputype;    /* cpu specifier */
        cpu_subtype_t   cpusubtype; /* machine specifier */
        uint32_t    filetype;   /* type of file */
        uint32_t    ncmds;      /* number of load commands */
        uint32_t    sizeofcmds; /* the size of all the load commands */
        uint32_t    flags;      /* flags */
        uint32_t    reserved;   /* reserved */
    };

    struct load_command {
        uint32_t cmd;       /* type of load command */
        uint32_t cmdsize;   /* total size of command in bytes */
    };

    typedef int             vm_prot_t;
    struct segment_command_64 { /* for 64-bit architectures */
        uint32_t    cmd;        /* LC_SEGMENT_64 */
        uint32_t    cmdsize;    /* includes sizeof section_64 structs */
        char        segname[16];    /* segment name */
        uint64_t    vmaddr;     /* memory address of this segment */
        uint64_t    vmsize;     /* memory size of this segment */
        uint64_t    fileoff;    /* file offset of this segment */
        uint64_t    filesize;   /* amount to map from the file */
        vm_prot_t   maxprot;    /* maximum VM protection */
        vm_prot_t   initprot;   /* initial VM protection */
        uint32_t    nsects;     /* number of sections in segment */
        uint32_t    flags;      /* flags */
    };

    struct section_64 { /* for 64-bit architectures */
        char        sectname[16];   /* name of this section */
        char        segname[16];    /* segment this section goes in */
        uint64_t    addr;       /* memory address of this section */
        uint64_t    size;       /* size in bytes of this section */
        uint32_t    offset;     /* file offset of this section */
        uint32_t    align;      /* section alignment (power of 2) */
        uint32_t    reloff;     /* file offset of relocation entries */
        uint32_t    nreloc;     /* number of relocation entries */
        uint32_t    flags;      /* flags (section type and attributes)*/
        uint32_t    reserved1;  /* reserved (for offset or index) */
        uint32_t    reserved2;  /* reserved (for count or sizeof) */
        uint32_t    reserved3;  /* reserved */
    };

    int x_offset = 0;
    struct mach_header_64* header = (struct mach_header_64*)_dyld_get_image_header(0);

    if(header->magic != MH_MAGIC_64) {
        return ;
    }

    x_offset = sizeof(struct mach_header_64);
    int ncmds = header->ncmds;
    uint64_t modInitFirstAddr = 0;
    char* secName;

    while(ncmds--) {
        /* go through all load command to find __TEXT segment*/
        struct load_command * lcp = (struct load_command *)((uint8_t*)header + x_offset);
        x_offset += lcp->cmdsize;
        
        if(lcp->cmd == LC_SEGMENT_64) {
            struct segment_command_64 * curSegment = (struct segment_command_64 *)lcp;
            struct section_64* curSection = (struct section_64*)((uint8_t*)curSegment + sizeof(struct segment_command_64));
            
            if(!strcmp(curSection->segname, "__DATA")){

                for (int i = 0; i < curSegment->nsects; i++) {

                    if (!strcmp(curSection->sectname, "__mod_init_func")) {
                        uint64_t memAddr = curSection->addr;
                        uint64_t modInitAddrArr = memAddr + (uint64_t)_dyld_get_image_vmaddr_slide(0);
                        modInitFirstAddr = *((uint64_t*)modInitAddrArr)
                        break;
                    }
                    curSection = (struct section_64*)((uint8_t*)curSection + sizeof(struct section_64));
                }
                break;
            }
        }
    }
    char ret[50];

    sprintf(ret, "0x%016lx", modInitFirstAddr);

    ret
    '''
    retStr = utils.exe_script(debugger, command_script)
    return utils.hex_int_in_str(retStr)
Exemplo n.º 25
0
def patch_code(debugger, addr, ins, count):
    command_script = '@import Foundation;\n'
    command_script += 'uint64_t x_addr = {};\n'.format(addr)
    command_script += 'uint8_t patch_data[] = {};\n'.format(ins)
    command_script += 'int insCount = {};\n'.format(count)
    command_script += r'''
    NSMutableString* retStr = [NSMutableString string];

    void * patch_addr = (void*)x_addr;
    //uint8_t patch_data[] = {0xc0, 0x03, 0x5f, 0xd6};
    int patch_data_size = 4*insCount;

    // =====================================================patch code=============================================
    typedef bool (*patch_code_t)(void* patch_addr, uint8_t* patch_data, int patch_data_size);
        patch_code_t patch_code = [](void* patch_addr, uint8_t* patch_data, int patch_data_size) -> bool {
        #define PAGE_SIZE        0x0000000000004000

        #define PAGE_MASK        0x0000000000003fff
        
        #define RTLD_LAZY   0x1
        #define RTLD_NOW    0x2
        #define RTLD_LOCAL  0x4
        #define RTLD_GLOBAL 0x8

        #define VM_PROT_READ    ((vm_prot_t) 0x01) 
        #define VM_PROT_WRITE   ((vm_prot_t) 0x02)  
        #define VM_PROT_EXECUTE ((vm_prot_t) 0x04)

        #define PROT_NONE   0x00    /* [MC2] no permissions */
        #define PROT_READ   0x01    /* [MC2] pages can be read */
        #define PROT_WRITE  0x02    /* [MC2] pages can be written */
        #define PROT_EXEC   0x04    /* [MC2] pages can be executed */

        #define MAP_SHARED  0x0001
        #define MAP_ANON    0x1000

        #define KERN_SUCCESS            0

        typedef unsigned int mach_port_t;
        typedef int     kern_return_t;
        typedef unsigned int        vm_inherit_t;
        typedef mach_port_t     task_t;
        typedef int     vm_prot_t;

        typedef unsigned long       uintptr_t;
        typedef uintptr_t       vm_offset_t;
        typedef vm_offset_t         vm_address_t;
        typedef uint64_t        mach_vm_address_t;
        typedef int     boolean_t;
        typedef int     vm_behavior_t;
        typedef uint32_t vm32_object_id_t;
        typedef uintptr_t       vm_size_t;
        typedef int *vm_region_recurse_info_t;

        typedef unsigned long long  memory_object_offset_t;
        struct vm_region_submap_short_info_64 {
            vm_prot_t       protection;     /* present access protection */
            vm_prot_t       max_protection; /* max avail through vm_prot */
            vm_inherit_t        inheritance;/* behavior of map/obj on fork */
            memory_object_offset_t  offset;     /* offset into object/map */
                unsigned int            user_tag;   /* user tag on map entry */
                unsigned int            ref_count;   /* obj/map mappers, etc */
                unsigned short          shadow_depth;   /* only for obj */
                unsigned char           external_pager;  /* only for obj */
                unsigned char           share_mode; /* see enumeration */
            boolean_t       is_submap;  /* submap vs obj */
            vm_behavior_t       behavior;   /* access behavior hint */
            vm32_object_id_t    object_id;  /* obj/map name, not a handle */
            unsigned short      user_wired_count; 
        };

        typedef unsigned int        __darwin_natural_t;
        typedef __darwin_natural_t  natural_t;
        typedef natural_t mach_msg_type_number_t;

        typedef struct vm_region_submap_short_info_64    vm_region_submap_short_info_data_64_t;

        #define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64                \
        ((mach_msg_type_number_t)                   \
         (sizeof (vm_region_submap_short_info_data_64_t) / sizeof (natural_t)))

        #define VM_FLAGS_OVERWRITE 0x4000  /* delete any existing mappings first */

        typedef int                     __int32_t;

        typedef __int32_t       __darwin_pid_t;   

        typedef __darwin_pid_t        pid_t; 

        // init value
        kern_return_t kret;
        task_t self_task = (task_t)mach_task_self();

        /* Set platform binary flag */
        #define FLAG_PLATFORMIZE (1 << 1)

        // platformize_me 
        // https://github.com/pwn20wndstuff/Undecimus/issues/112
        /*

        void* handle = (void*)dlopen("/usr/lib/libjailbreak.dylib", RTLD_LAZY);
        if (!handle){
            //[retStr appendString:@"[-] /usr/lib/libjailbreak.dylib dlopen failed!\n"];
            return false;
        }
        
        // Reset errors
        (const char *)dlerror();
        typedef void (*fix_entitle_prt_t)(pid_t pid, uint32_t what);
        fix_entitle_prt_t ptr = (fix_entitle_prt_t)dlsym(handle, "jb_oneshot_entitle_now");
        
        const char *dlsym_error = (const char *)dlerror();
        if (dlsym_error) return;
        
        ptr((pid_t)getpid(), FLAG_PLATFORMIZE);
        //[retStr appendString:@"\n[+] platformize me success!"];

        */

        void* target_addr = patch_addr;

        // 1. get target address page and patch offset
        unsigned long page_start = (unsigned long) (target_addr) & ~PAGE_MASK;
        unsigned long patch_offset = (unsigned long)target_addr - page_start;

        // map new page for patch
        void *new_page = (void *)mmap(NULL, PAGE_SIZE, 0x1 | 0x2, 0x1000 | 0x0001, -1, 0);
        if (!new_page ){
            //[retStr appendString:@"[-] mmap failed!\n"];
            return false;
        }

        kret = (kern_return_t)vm_copy(self_task, (unsigned long)page_start, PAGE_SIZE, (vm_address_t) new_page);
        if (kret != KERN_SUCCESS){
            //[retStr appendString:@"[-] vm_copy faild!\n"];
            return false;
        }


        // 4. start patch
        /*
         nop -> {0x1f, 0x20, 0x03, 0xd5}
         ret -> {0xc0, 0x03, 0x5f, 0xd6}
        */
        // char patch_ins_data[4] = {0x1f, 0x20, 0x03, 0xd5};
        //    mach_vm_write(task_self, (vm_address_t)(new+patch_offset), patch_ret_ins_data, 4);
        memcpy((void *)((uint64_t)new_page+patch_offset), patch_data, patch_data_size);
        //[retStr appendString:@"[+] patch ret[0xc0 0x03 0x5f 0xd6] with memcpy\n"];
        
        // set back to r-x
        (int)mprotect(new_page, PAGE_SIZE, PROT_READ | PROT_EXEC);
        //[retStr appendString:@"[*] set new page back to r-x success!\n"];

        
        // remap
        vm_prot_t prot;
        vm_inherit_t inherit;
        
        // get page info
        vm_address_t region = (vm_address_t) page_start;
        vm_size_t region_len = 0;
        struct vm_region_submap_short_info_64 vm_info;
        mach_msg_type_number_t info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
        natural_t max_depth = 99999;
        kret = (kern_return_t)vm_region_recurse_64(self_task, &region, &region_len,
                                                &max_depth,
                                                (vm_region_recurse_info_t) &vm_info,
                                                &info_count);
        if (kret != KERN_SUCCESS){
            //[retStr appendString:@"[-] vm_region_recurse_64 faild!\n"];
            return false;
        }

        prot = vm_info.protection & (PROT_READ | PROT_WRITE | PROT_EXEC);
        inherit = vm_info.inheritance;
        //[retStr appendString:@"[*] get page info done.\n"];
        
        vm_prot_t c;
        vm_prot_t m;
        mach_vm_address_t target = (mach_vm_address_t)page_start;
        
        kret = (kern_return_t)mach_vm_remap(self_task, &target, PAGE_SIZE, 0,
                           VM_FLAGS_OVERWRITE, self_task,
                           (mach_vm_address_t) new_page, true,
                           &c, &m, inherit);
        if (kret != KERN_SUCCESS){
            //[retStr appendString:@"[-] remap mach_vm_remap faild!\n"];
            return false;
        }
        //[retStr appendString:@"[+] remap to target success!\n"];

        // clear cache
        void* clear_start_ = (void*)(page_start + patch_offset);
        sys_icache_invalidate (clear_start_, 4);
        sys_dcache_flush (clear_start_, 4);

        return true;
    };
    // =====================================================patch code=============================================
    
    patch_code(patch_addr, patch_data, patch_data_size);

    [retStr appendString:@"patch done."];
    retStr
    '''
    retStr = utils.exe_script(debugger, command_script)
    return utils.hex_int_in_str(retStr)