7 votes

empêcher la réflexion (objc/runtime) sur iOS

Je travaille sur une bibliothèque statique qui traite des données sensibles. Il est impératif que le développeur qui utilise la bibliothèque ne puisse pas utiliser la réflexion sur la bibliothèque.

Sur Android, nous résolvons le problème en développant une aar avec service et exécuter le service (Lorsque le service est exécuté dans un autre processus, le développeur ne peut pas utiliser la réflexion) mais je me demande si quelque chose de similaire existe dans iOS ?

Peut-on exécuter une bibliothèque statique dans un processus séparé ? Si non, comment éviter la réflexion sur nos bibliothèques statiques ?

Par exemple :

        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 est un cours de ma bibliothèque. Dans la première ligne, j'initialise un objet de cette classe.

Dans la ligne suivante, je lis la liste des variables, méthodes et propriétés de la classe et je l'enregistre. Voici le résultat :

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

wannaTestIt est une méthode privée et testValue est une variable privée. Je m'attends donc à ce que le développeur qui utilise la bibliothèque ne puisse pas y accéder. Cependant, comme l'utilisateur de la bibliothèque a pu obtenir le nom, il peut finalement appeler la méthode pour lire la valeur de l'iVar.

Comment puis-je éviter cela ?

5voto

Dim_ov Points 1243

Si vous voulez "empêcher" complètement la réflexion, vous devez utiliser un autre langage. La réflexion est un élément clé en Objective C et il n'est pas possible de la "bloquer" ou de la "désactiver".

Cependant, vous pouvez rendre ces informations d'exécution beaucoup moins utiles pour le chercheur en les obscurcissant. Par exemple, jetez un coup d'oeil à cet outil : https://github.com/Polidea/ios-class-guard . Il ne s'agit que d'un exemple. Je ne suis pas lié à ce projet particulier et vous pouvez librement choisir un autre obfuscateur ou écrire le vôtre.

Si ce dont vous avez besoin est de limiter la réflexion à l'API publique seulement et même de divulguer un nombre de méthodes privées et d'ivars (sans leurs noms réels) ne vous convient pas, vous n'avez pas d'autre choix que d'écrire votre code sensible dans un autre langage. Vous pouvez utiliser Pimpl pour obtenir ce que vous voulez. De cette façon, vos classes n'auront que des méthodes publiques et une seule méthode privée. _impl (ou quelque chose comme ça). Où _impl est une instance de la classe d'implémentation qui est écrite en C++ (ou en Objective C++ si vous avez besoin d'accéder aux API ObjC) et toutes les méthodes publiques agissent comme un proxy. Quelque chose comme ceci :

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

De cette façon, toutes vos données et méthodes privées seront encapsulées dans l'environnement de l'utilisateur. MyClassImpl la classe. Si vous gardez la déclaration et l'implémentation d'une telle classe en privé (c'est-à-dire que vous ne distribuez pas MyClassImpl.h avec votre bibliothèque) et utiliser un langage comme le C++ pour l'implémenter, alors vous obtiendrez ce que vous voulez.

Notez également que si vous avez choisi Objective C++ alors MyClassImpl doit être une classe C++ (déclarée avec class ) et non une classe Objective C (déclarée avec le mot-clé @interface / @end et mis en œuvre à l'intérieur du bloc @implementation / @end bloc). Dans le cas contraire, toutes vos données privées seront de toute façon disponibles pour la réflexion, mais cela nécessitera quelques étapes supplémentaires de la part du chercheur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X