防止 iOS 上的反射(对象/运行时) [英] prevent reflection (objc/runtime) on iOS

查看:75
本文介绍了防止 iOS 上的反射(对象/运行时)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我们可以在一个单独的进程中执行一个静态库吗?如果没有,我们如何避免对我们的静态库进行反射?

例如:

 MyTestObject *obj = [[[myTestView alloc] init ];//==========================================类 clazz = [obj 类];u_int 计数;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]];}免费(伊瓦斯);objc_property_t* 属性 = 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]];}免费(属性);Method* methods = class_copyMethodList(clazz, &count);NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];for (int i = 0; i < count ; i++){SEL 选择器 = method_getName(methods[i]);const char* methodName = sel_getName(selector);[methodArray addObject:[NSString stringWithCString:methodName encoding:NSUTF8StringEncoding]];}免费(方法);NSDictionary* classDump = [NSDictionary dictionaryWithObjectsAndKeys:ivarArray, @"ivars",属性数组,@属性",methodArray, @"methods",零];NSLog(@"%@", classDump);//======================================================int v2 = [[obj valueForKey:@"testValue"] intValue];SEL s = NSSelectorFromString(@"wannatTestIt");[obj performSelector:s];

MyTestObject 是我库中的一个类.在第一行,我从这个类初始化一个对象.

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

<代码> {伊瓦尔 = (测试值);方法 = (打印测试值,想测试一下,initWithFrame:");属性 = ();}

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

我怎样才能防止这种情况发生?

解决方案

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

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

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

- (NSInteger)computeSuperSensitiveStuffWithFoo:(Foo *)foo Bar:(Bar *)bar {返回 _impl->computeStuff(foo, bar);}

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

还要注意,如果你选择了 Objective C++,那么 MyClassImpl 应该是一个 C++ 类(用 class 关键字声明)而不是 Objective C 类(用 @ 声明)interface/@end 块并在 @implementation/@end 块内实现).否则,无论如何,您的所有私人数据都可以用于反思,但需要研究人员执行一些额外的步骤.

I am working on a static library that handles sensitive data. It is imperative that the developer using the library can not use reflection on the library.

On Android, we solve the problem by developing an aar file with services and run the service into separate process;(When the service is running into another process then the developer can not use reflection) but I am wondering if something similar exists in iOS ?

Can we execute a static library into a separate process? if not, how we can avoid reflection on our static libraries?

For example:

        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];

MyTestObject is a class from my library. In the first line, I initialize an object from this class.

In the next line, I read the variables, methods and property list of the class and log it. Here is the result:

    {
    ivars =     (
        testValue
    );
    methods =     (
        printTestValue,
        wannatTestIt,
        "initWithFrame:"
    );
    properties =     (
    );
}

wannaTestIt is a private method and testValue is a private variable. So I expect that the developer that uses the library can not access them. However, because the user of the library could get the name, the user can ultimately call the method to read the value of the iVar.

How can I prevent this?

解决方案

If you want to completely "prevent" reflection then, well, you have to use a different language. Reflection is a key thing in Objective C and it's not possible to "block" or "disable" it.

However, you can make this run-time information much less useful for the researcher by obfuscating it. For example, take a look at this tool: https://github.com/Polidea/ios-class-guard. This is just an example. I'm not related to this particular project and you can freely chose a different obfuscator or write your own.

If what you need is to limit reflection to public API only and even disclosing a number of private methods and ivars (without their actual names) is not okay for you then you have no other choice than writing you sensitive code in a different language. You can use Pimpl design pattern to achieve what you want. This way, your classes would only have public methods and a single private ivar _impl (or something like that). Where _impl is an instance of the implementation class that is written in C++ (or Objective C++ if you need access to ObjC APIs) and all public methods act like a proxy. Something like this:

- (NSInteger)computeSuperSensitiveStuffWithFoo:(Foo *)foo Bar:(Bar *)bar {
    return _impl->computeStuff(foo, bar);
}

This way all your private data and methods would be encapsulated in the MyClassImpl class. If you keep declaration and implementation of such class in private (i.e. do not distribute MyClassImpl.h file with your library) and use language like C++ for implementing it, then you will achieve what you want.

Also note that if you chose Objective C++ then MyClassImpl should be a C++ class (declared with class keyword) and not Objective C class (declared with @interface/@end block and implemented inside @implementation/@end block). Otherwise all you private data will be available for reflection anyway, but would require a couple of additional steps from the researcher.

这篇关于防止 iOS 上的反射(对象/运行时)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆