2016-10-01 22 views
7

Pracuję na statycznej bibliotece, która obsługuje poufne dane. Konieczne jest, aby programista korzystający z biblioteki nie mógł użyć refleksji w bibliotece.zapobiega odbiciu (objc/runtime) na iOS

Na Androidzie możemy rozwiązać ten problem poprzez stworzenie pliku aar z service s i uruchomić service do oddzielnego procesu; (Gdy usługa jest uruchomiona w innym procesie następnie deweloper nie może użyć refleksji), ale zastanawiam się czy coś podobne istnieje w iOS?

Czy możemy wykonać statyczną bibliotekę w oddzielnym procesie? jeśli nie, jak możemy uniknąć refleksji na temat naszych bibliotek statycznych?

Na przykład:

 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 jest klasa z mojej biblioteki. W pierwszym wierszu inicjuję obiekt z tej klasy.

W następnym wierszu odczytuję zmienne, metody i listę właściwości klasy i loguję ją. Oto wynik:

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

wannaTestIt to prywatna metoda i testValue jest zmienną prywatne. Oczekuję więc, że programista korzystający z biblioteki nie będzie mógł uzyskać do nich dostępu. Ponieważ jednak użytkownik biblioteki może uzyskać nazwę, użytkownik może ostatecznie wywołać metodę odczytania wartości iVar.

Jak mogę temu zapobiec?

Odpowiedz

5

Jeśli chcesz całkowicie "zapobiec" refleksji, to musisz użyć innego języka. Odbicie jest kluczową rzeczą w Celu C i nie można go "zablokować" ani "wyłączyć".

Jednak informacje te mogą być mniej użyteczne dla badacza poprzez jego zaciemnienie. Na przykład spójrz na to narzędzie: https://github.com/Polidea/ios-class-guard. To tylko przykład. Nie jestem związany z tym konkretnym projektem i możesz dowolnie wybrać inny obfuscator lub napisać własny.

Jeśli to, co potrzebne jest, aby ograniczyć odbicia do publicznych API tylko i nawet ujawniających szereg metod prywatnych Ivars (bez ich rzeczywistych nazw) nie jest w porządku dla ciebie to nie masz innego wyjścia niż pisanie Ci kod poufnych w innym języku. Możesz użyć wzoru projektu Pimpl, aby osiągnąć to, co chcesz. W ten sposób twoje klasy będą miały tylko publiczne metody i pojedyncze prywatne ivar _impl (lub coś w tym stylu). Gdzie _impl jest instancją klasy implementacji napisaną w C++ (lub Objective C++, jeśli potrzebujesz dostępu do interfejsów API ObjC), a wszystkie publiczne metody działają jak proxy. Coś takiego:

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

ten sposób wszystkie swoje prywatne dane i metody będą obudowane w klasie MyClassImpl. Jeśli zachowujesz deklarację i implementację takiej klasy na prywatnej (tzn. Nie rozpowszechniasz pliku MyClassImpl.h w swojej bibliotece) i używasz języka takiego jak C++ do jej implementacji, osiągniesz to, co chcesz.

Należy również pamiętać, że jeśli wybraliśmy Objective C++ następnie MyClassImpl powinny być klasy C++ (deklarowany z class hasła) i nieobiektywne klasy C (zadeklarowanego przy @interface/@end bloku i realizowane wewnątrz @implementation/@end bloku).W przeciwnym razie wszystkie twoje prywatne dane będą dostępne do rozważenia, ale wymagają od badacza kilku dodatkowych kroków.

+0

Moja biblioteka ma również kontrolery uiview. Czy możemy tworzyć kody z C++, które również wspierają kontrolery uiview? –

+0

@HuseinBehboodiRad, na pewno. Nie wymaga zmian dla UIViewControllers. Po prostu utwórz zwykłą podklasę 'UIViewController' (powiedzmy' MyViewController'), utwórz klasę implementacji napisaną w Objective C++ (powiedzmy 'MyVCImpl'). I zrób dokładnie te same rzeczy, które opisałem w mojej odpowiedzi. W 'MyViewController' dodaj' _impl' ivar wskazując na instancję 'MyVCImpl'. Proxy wszystkie publiczne metody do '_impl' i zachowaj wszystkie prywatne metody/pola wewnątrz' MyVCImpl'. Możesz przekazać 'self' do konstruktora' MyVCImpl', aby uzyskać dostęp do rzeczywistego kontrolera widoku od środka klasy implementacji. –

Powiązane problemy