この記事は iOS Jailbreaking Advent Calendar 2015 の6日目の記事です。
cycriptはObjective-C++とJavaScriptのSyntaxで記述出来るiOS, OSX上で実行出来るObjective-C++のREPLおよびプロセスにアタッチしLLDBのように変更が出来るツールです。
ちなみにGPL3のOSSです。
for debug
その性質上、プロセスにアタッチし
- このタイミングでこの型のインスタンスが取れると良いんだけどなあ
- ここでどうにかしてこんな状態にもっていきたい
とかいった状況の時によく利用しています。
get instance
tweak上でNSLogでオブジェクトについてログを吐かせておけばそのアドレスがわかります。
そのインスタンスから試行錯誤する際に#<Address>
でインスタンスを取得出来ます。
cy# var a = #0x12fd509c0
#"<Application: 0x12fd509c0>"
ObjC message send
Objective-Cのメッセージ送信、プロパティへのアクセスはそのまま書けます
cy# [a keyWindow]
#"<MobileSafariWindow: 0x12fef5c70; baseClass = UIWindow; frame = (0 0; 375 667); opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x12fef7a40>; layer = <UIWindowLayer: 0x12fef61b0>>"
cy# a.keyWindow
#"<MobileSafariWindow: 0x12fef5c70; baseClass = UIWindow; frame = (0 0; 375 667); opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x12fef7a40>; layer = <UIWindowLayer: 0x12fef61b0>>"
cycriptでdebugする上で素晴らしいのはunrecognized selectorにメッセージ送信してもプロセスがクラッシュしない点です。
cy# [a hoge]
Error: unrecognized selector hoge sent to object 0x12fd509c0
ivar
ivarへはCにおける構造体ポインタ書式->
でアクセス出来ます。
cy# a->_backgroundHitTestWindow
#"<_UIBackgroundHitTestWindow: 0x12fd451d0; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x1311059f0>; layer = <UIWindowLayer: 0x12fdc1720>>"
choose(Class)
choose(Class)
でメモリ上からいい感じにインスタンスをゲットしてきてくれます。べんり。
cy# choose(BrowserController)
[#"<BrowserController: 0x12fe56f50>"]
まとめ
私がよく使っているのは上記程度。詳しくは公式ドキュメントの方が詳しいです。
同梱されているスクリプトをimportする事でsubstrateのMSHookMessageEx()
を呼び出して動的かつインタラクティブにswizzleする事も出来ますが、swizzle部分はtweak側で書いた方が楽な気がします。アドレスとれるし、利用するなら最終的に書かないといけないので。