防止iOS上的反射(objc/runtime)

Hus*_*Rad 7 reflection xcode objective-c static-libraries ios

我正在处理一个处理敏感数据的静态库.使用库的开发人员必须不能在库上使用反射.

在Android上,我们通过aar使用services 开发文件并运行service到单独的进程来解决问题;(当服务运行到另一个进程然后开发人员不能使用反射)但我想知道iOS中是否存在类似的东西?

我们可以将静态库执行到单独的进程中吗?如果没有,我们如何避免反思我们的静态库?

例如:

        MyTestObject *obj = [[[myTestView alloc] init ];

        //===========================================   

        Class clazz = [obj class];
        u_int count;
        Ivar* ivars = class_copyIvarList(clazz, &count);
        NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
        for (int i = 0; i < count ; i++)
        {
            const char* ivarName = ivar_getName(ivars[i]);
            [ivarArray addObject:[NSString  stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
        }
        free(ivars);

        objc_property_t* properties = class_copyPropertyList(clazz, &count);
        NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
        for (int i = 0; i < count ; i++)
        {
            const char* propertyName = property_getName(properties[i]);
            [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
        }
        free(properties);

        Method* methods = class_copyMethodList(clazz, &count);
        NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];
        for (int i = 0; i < count ; i++)
        {
            SEL selector = method_getName(methods[i]);
            const char* methodName = sel_getName(selector);
            [methodArray addObject:[NSString  stringWithCString:methodName encoding:NSUTF8StringEncoding]];
        }
        free(methods);

        NSDictionary* classDump = [NSDictionary dictionaryWithObjectsAndKeys:
                                   ivarArray, @"ivars",
                                   propertyArray, @"properties",
                                   methodArray, @"methods",
                                   nil];

        NSLog(@"%@", classDump);

        //======================================================

        int v2 = [[obj valueForKey:@"testValue"] intValue];

        SEL s = NSSelectorFromString(@"wannatTestIt");
        [obj performSelector:s];
Run Code Online (Sandbox Code Playgroud)

MyTestObject是我图书馆的一个班级.在第一行中,我从该类初始化一个对象.

在下一行中,我读取了类的变量,方法和属性列表并记录它.结果如下:

    {
    ivars =     (
        testValue
    );
    methods =     (
        printTestValue,
        wannatTestIt,
        "initWithFrame:"
    );
    properties =     (
    );
}
Run Code Online (Sandbox Code Playgroud)

wannaTestIt是一个私有方法,testValue是一个私有变量.所以我希望使用该库的开发人员无法访问它们.但是,因为库的用户可以获得名称,所以用户最终可以调用该方法来读取iVar的值.

我怎么能阻止这个?

Dim*_*_ov 5

如果你想完全"防止"反射,那么,你必须使用不同的语言.反射是Objective C中的一个关键因素,它不可能"阻止"或"禁用"它.

但是,通过模糊处理,您可以使此运行时信息对研究人员的用处更少.例如,看看这个工具:https://github.com/Polidea/ios-class-guard.这只是一个例子.我与这个特定的项目无关,您可以自由选择不同的混淆器或编写自己的混淆器.

如果你需要的只是限制反映到公共API,甚至披露一些私人方法和ivars(没有他们的实际名称)是不合适的,那么你别无选择,只能用不同的语言写敏感代码.您可以使用Pimpl设计模式来实现您想要的效果.这样,您的类只有公共方法和单个私有ivar _impl(或类似的东西).其中_impl是用C++编写的实现类的实例(如果需要访问ObjC API,则使用Objective C++),并且所有公共方法都像代理一样.像这样的东西:

- (NSInteger)computeSuperSensitiveStuffWithFoo:(Foo *)foo Bar:(Bar *)bar {
    return _impl->computeStuff(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

这样,所有私有数据和方法都将封装在MyClassImpl类中.如果你私下保持这样的类的声明和实现(即不用MyClassImpl.h你的库分发文件)并使用像C++这样的语言来实现它,那么你将实现你想要的.

另请注意,如果选择Objective C++,则MyClassImpl应该是C++类(使用class关键字声明)而不是Objective C类(使用@interface/ @endblock 声明并在@implementation/ @endblock中实现).否则,无论如何,您的所有私人数据都可用于反射,但需要研究人员进行一些额外的步骤.