根据变量名获取实例对象&根据实例对象获取变量名

996.icu LICENSE

  • 问题背景
  • 解决方法
  • 总结

问题背景

在iOS逆向过程中,尽管可以根据class-dump获取应用相关头文件,但是如果成员变量没有声明为@property,就无法获取到这部分变量的实例对象。

解决方法

在正向开发中,有一种方法可以根据实例对象获取到变量名。参考IOS高级教程2:反射根据变量的引用获取变量名。可以写出如下C风格的代码:

#import <objc/runtime.h>
/** 
 * 根据成员变量的实例对象获取在类中对应的变量名
 * 
 * @param self 类自身的实例对象id
 * @param instance 类中变量的实例对象id
 * 
 * @return 实例对象的变量名
 */
NSString *getNameWithInstance(id self, id instance)
{
    unsigned int numIvars = 0;
    NSString *key=nil;
    Ivar * ivars = class_copyIvarList([self class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        const char *type = ivar_getTypeEncoding(thisIvar);
        NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        if (![stringType hasPrefix:@"@"]) {
            continue;
        }
        if ((object_getIvar(self, thisIvar) == instance)) {
            key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            break;
        }
    }
    free(ivars);
    return key;
}

那么反过来,如何根据变量名获取实例对象呢。有如下代码:

#import <objc/runtime.h>
/** 
 * 根据成员变量在类中对应的变量名获取实例对象
 * 
 * @param self 类自身的实例对象id
 * @param name 成员变量在类中对应的变量名
 * 
 * @return 变量名对应的实例对象
 */
id getInstanceWithName(id self, NSString* name)
{
    unsigned int numIvars = 0;
    NSString *key=nil;
    id ret;
    Ivar * ivars = class_copyIvarList([self class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        const char *type = ivar_getTypeEncoding(thisIvar);
        NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        if (![stringType hasPrefix:@"@"]) {
            continue;
        }
        key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
        if([key isEqualToString:name])
        {
            ret = (object_getIvar(self, thisIvar));
            break;
        }
    }
    free(ivars);
    return ret;
}

总结

这些技巧,要靠看苹果官方文档。或者在网络上善于发现已有的解决方法,并加以修改。

参考资料

  1. IOS高级教程2:反射根据变量的引用获取变量名
1 Like

有点意思,收藏了 :star_struck:

#define varString(var) @#var