Frida を使ってみたメモ
Frida
自分の Script を Inject したり、値を取得したり、色々なことができる Toolkit です。
リバースエンジニアリングとかする時に使うみたいですね。
iOS / Android にも対応しており、今回は Android の話です。
ちなみに日本語の記事もいくつかあります。
もし試す場合は自分のアプリや許可されているものを使用して試してください。
ここからの手順やコマンド、コードによって何が起きても私は責任を取りません。
入れてみる
Rooted device のほうが簡単らしいのですが、持ってないので Without root で試します。
肝心の手順はここに全部書いており、写すことはしないのでこちらを参照してください。
簡単に手順を書くと
1. apk を device から抜く (pm path とかしてから pull する)
2. apktool を用いて apk を decode する
3. 諸々いじった後、libfrida-gadget.so を lib/ に入れる
4. apktool で apk を build
5. jarsigner で署名 / 検証
6. zipalign で最適化
という感じです。
3 での諸々いじる工程もすべて上記の記事に書いてあります。
使ってみる
試したコードとアプリはここにあります。以降はこのデモ app を使用しています。
準備
Frida の install が終わっていない場合は
$ pip install frida-tools
さて、Frida は Python で書くのですが、Inject する Sctipt は JavaScript です。
ということでまずはベースとなる Python の Script が必要になります。
こちらをベースにして、
import sys import frida def on_message(message, data): print(message) js = """ Java.perform(function() { }); """ process = frida.get_usb_device().attach('Gadget') script = process.create_script(js) script.on('message', on_message) script.load() sys.stdin.read()
こんな感じです。今回は Gadget を使っているので attach('Gadget') となります。
アプリが待ち受けている状態等で、
$ python example.py
を実行すると何も起きないはずです。
エラーが出る場合はおそらくどこか間違えています。
Detector の返す値を変更する
Repository を見てもらうと分かりますが jp.cordea.fridademo.Detector という Class があり、Detector#detect が false を返しています。
Detector#detect が true だと Button を click した際に toast が表示されます。ということで toast が表示されるようにします。
var detector = Java.use('jp.cordea.fridademo.Detector'); detector.detect.overload().implementation = function() { return true; }
Button を click すると toast が表示されるはずです。
fab の click を上書きする
続いて fab の click を上書きします。まず fab を取得する必要があります。
var fabId = activity.findViewById(0x7f080069); var fab = Java.cast( fabId.$handle, Java.use('com.google.android.material.floatingactionbutton.FloatingActionButton') );
findViewById で fab を取得し、FloatingActionButton に cast しています。
なお、この ID はデモ app の場合は smali/jp/cordea/fridademo/R\$id.smali を検索することで取得できます。
Listener も必要です。
var listener = Java.use('android.view.View$OnClickListener');
そして Listener をセットします。
fab.setOnClickListener(Java.registerClass({ name: 'jp.cordea.fridademo.OnClickListener', implements: [listener], methods: { onClick: function(v) { } } }).$new());
TextView の count を上書きする
さて、先程 fab の click を上書きしたので今まで click 毎に +1 されていた TextView の count が動かなくなりました。
これを *2 するようにしてみましょう。
var textViewId = activity.findViewById(0x7f0800de); var textView = Java.cast( textViewId.$handle, Java.use('android.widget.TextView') );
そしてさきほどの onClick の中に *2 する実装を入れます
var count = 1; fab.setOnClickListener(Java.registerClass({ name: 'jp.cordea.fridademo.OnClickListener', implements: [listener], methods: { onClick: function(v) { count *= 2; } } }).$new());
そして上書きしますが、java.lang.String としてセットする必要があります。
なので、以下のようにセットします。
var count = 1; fab.setOnClickListener(Java.registerClass({ name: 'jp.cordea.fridademo.OnClickListener', implements: [listener], methods: { onClick: function(v) { count *= 2; var string = Java.use('java.lang.String'); textView.setText(string.$new(count.toString())); } } }).$new());
これで fab を click すると +1 ではなく *2 で値が増えていく様子が見られると思います。
詳しくは Repository の example.py を見てください。