Az alábbi cikket Ys. írta a 0x90 blogon, és mivel a cikksorozata kapcsolódik az iPhone-hoz, mi érdekesnek gondoljuk a számotokra is, így ezeket engedelmével egymás után át is emelnénk ide, a Szifonra.
***
A jailbreakinggel foglalkozó résznél szóltam arról, hogy az egész hacacáré egyik legkirályabb hozadéka az, hogy lesz gdb a készülékeden. Ha meg van gdb, akkor tulajdonképpen bármit meg tudsz tenni az alkalmazás binárisának futtatása közben. Mutatok egy konkrét példát arra, hogy hogy lehet mindezt használni arra, hogy belehallgassunk az alkalmazásunkban futó objektumok kommunikációjába.
Mielőtt belevágnánk a dinamikus analízisbe, egy nagyon fontos dologra szeretném felhívni a figyelmet. A példában nem törjük meg meg az alkalmazást, nem hekkeljük meg – a példával egyetlen célunk az, hogy megértsük az alkalmazás működését anélkül, hogy meglenne a forráskód.
Ahhoz, hogy a következőket megértsük, elkerülhetetlen némi ObjectiveC-gyorstalpaló. Először is, az ObjC, mint a nevében is benne van, objektumorientált programozási nyelv és egy csomó advanced szolgáltatást tud a futtatókörnyezet, ami haxolási szempontból hasznos. Próbálom ezt a részt csak annyira kibontani, amennyire feltétlenül szükséges – mindazonáltal előre kell bocsátanom, hogy nem vagyok ObjC kóder.
Ami az ObjectiveC frameworkből haxorként minket érdekel, az elsősorban az, ahogy az app maga működik és az objektumok füttyögnek egymásnak futás közben. A class-dump utility használatával a binárisban található ObjC metaadatok segítségével előállítottuk az osztályok és a függvényeik fejléclistáját a statikus analízis során – most arra vagyunk kíváncsiak, hogy mi történik, ha elkezdik az objektumok egymást rángatni futási időben.
Az alábbi példákat ebben a könyvben is megtalálhatjátok. Tekintsünk alábbi helloworld programot:
#import <Foundation/Foundation.h>
@interface SaySomething : NSObject
– (void) say: (NSString *) phrase;@end
@implementation SaySomething
– (void) say: (NSString *) phrase {printf(“%s\n”, [ phrase UTF8String ]);}@end
int main(void) {
SaySomething *saySomething = [ [ SaySomething alloc ] init ];
[ saySomething say: @”Hello, world!” ];
[ saySomething release ];
return 0;
}
Itt tehát először is leidézünk a táblára egy SaySomething nevű objektumot, meghívjuk a say függvényét a “Hello, world!” stringgel, végül pedig megöljük az objektumunkat. Az, hogy az adott objektum mit csinál, az most lényegtelen. A fenti ObjC-kódból a main függvényt a következőképpen is lehet interpretálni eggyel alacsonyabb szinten, C-ben:
objc_msgSend(
objc_msgSend(
objc_msgSend(
objc_getClass(“SaySomething”), NSSelectorFromString(@”alloc”)),
NSSelectorFromString(@”init”)),
NSSelectorFromString(@”say:”), @”Hello, world!”),
NSSelectorFromString(@”release:”));
Az objc_msgSend függvény kulcsszerepet játszik az ObjC framework működésében, ugyanis a színfalak mögött ez a függvény hívódik meg, ha valamelyik objektum meghívja egy másik objektum valamilyen függvényét. Az ObjC-nek ezen része open-source, így meg lehet nézni a prototípusát:
id objc_msgSend(id theReceiver, SEL theSelector, …)
Az elnevezések ne tévesszenek meg: a theReceiver objektum theSelector nevű függvényét hívjuk meg. Javában ez valahogy úgy festene, hogy theReceiver.theSelector(…);, vagy javás nyelvjárásban object.Method(…);.
Mire jó az, hogy ezt tudjuk? Hát, például ráakaszkodva erre a függvényre hallgatózni lehet, hogy mi történik az alkalmazásunkban. Például tekintsük a már bevált PhotoVault app tekintetében a hívásokat.
Némi magyarázat a gdb-s varázsláshoz elöljáróban. Az ARM assemblyben az r0-r7-ig terjedő, első nyolc regiszter általános célokat szolgál, és többnyire függvényhívások argumentumait tárolják bennük. Azaz, ha megnézzük az objc_msgSend függvény prototípusát, r0 fogja tárolni a címzettet, r1 pedig a függvény nevét (illetve a rámutató pointert).
white-iPhone:~ root# gdb -q -p `ps aux | grep PhotoVault | awk '{print $2}'`
305: No such file or directory
/private/var/root/290: No such file or directory
Attaching to process 290.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ............................................................................................................................................... done
0x362a6c00 in mach_msg_trap ()
(gdb) break objc_msgSend
Breakpoint 1 at 0x351b2c96
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>x/a $r0
>x/s $r1
>c
>end
(gdb) c
Continuing.
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3ad850: 0x3eef02fc <OBJC_CLASS_$___NSCFTimer>
0x319ef814 <__PRETTY_FUNCTION__.70356+9908>: "retain"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a1a10: 0x3ef7ac48 <OBJC_CLASS_$_UITextSelectionView>
0x319ef814 <__PRETTY_FUNCTION__.70356+9908>: "retain"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a1a10: 0x3ef7ac48 <OBJC_CLASS_$_UITextSelectionView>
0x31a545e5 <__PRETTY_FUNCTION__.69227+177429>: "caretBlinkTimerFired:"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a1a10: 0x3ef7ac48 <OBJC_CLASS_$_UITextSelectionView>
0x31a549c4 <__PRETTY_FUNCTION__.69227+178420>: "_animationIsPaused"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a1a10: 0x3ef7ac48 <OBJC_CLASS_$_UITextSelectionView>
0x319f2888 <__PRETTY_FUNCTION__.70356+22312>: "layer"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a5800: 0x3f8fa11c <OBJC_CLASS_$_CALayer>
0x319f51a2 <__PRETTY_FUNCTION__.67982+9482>: "speed"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a5800: 0x3f8fa11c <OBJC_CLASS_$_CALayer>
0x319e7120: "class"
Breakpoint 1, 0x351b2c96 in objc_msgSend ()
0x3a5800: 0x3f8fa11c <OBJC_CLASS_$_CALayer>
0x31a14d24 <__PRETTY_FUNCTION__.67982+139404>: "superlayer"
…és ebből végtelen. Az alkalmazásunk, ami látszólag nem csinál semmit, folyamatosan hívogat ilyen-olyan objektumokat, ide-oda mennnek az üzenetek.
A következő részben arról lesz szó, hogy hogy tudunk mi is belenyúlni a tesztelt alkalmazás idegrendszerébe.
No comment yet, add your voice below!