Frida学习笔记
参考链接:https://blog.csdn.net/fly_hps/article/details/87251759
安装与配置见tool-use
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import frida, sys
""" rdev = frida.get_usb_device() front_app = rdev.get_frontmost_application() print(front_app) """
""" rdev = frida.get_usb_device() apps = rdev.enumerate_applications() for app in apps: print(app) """
|
0x00 例题1
以下是一个mainActivity的部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public final void invoke(@NotNull Score arg6) { Intrinsics.checkParameterIsNotNull(arg6, "$receiver"); if(arg6.getScore() > 20000) { Game.access$getView$p(Game.this).setScore(0xFFFFFFFF); } else { Game.access$getView$p(Game.this).setScore(arg6.getScore()); } if(Game.access$getView$p(Game.this).getLevel() < arg6.getLevel() && Game.access$getView$p(Game.this).getLevel() != 0 && (Game.this.getSoundEnabled())) { DefaultImpls.play$default(Game.access$getSoundtrack$p(Game.this), Sound.LEVEL_UP, 0, 2, null); } Game.access$getView$p(Game.this).setLevel(arg6.getLevel()); }
|
反正最后分析得出:setScore方法值置为-1,程序将就会自动为我们解密flag。于是,最后的脚本这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message) jscode = """ Java.perform(function(){ var clz = Java.use("ds.tetris.android.MainActivity"); clz.setScore.overload('int').implementation = function(args){ args = -1; clz.setScore.overload('int').call(this, args); } }); """ process = frida.get_usb_device().attach('ds.tetris.android') script = process.create_script(jscode) script.on('message', on_message) script.load() sys.stdin.read()
|
0x01 例题2
参考链接:https://www.jianshu.com/p/42159644ddc6
主要代码如下:
意思就是,赢CPU 1000次,就可以获得最后的flag。相关的frida代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import frida, sys
def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message)
jscode = """ Java.perform(function () { var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity'); MainActivity.onClick.implementation = function (v) { send("Hook Start...");
# 不改变参数v的情况下,直接调用原方法onClick(v),这样不妨碍程序原本的运行 # 如果想要修改参数,也是在此处直接对v进行修改。 # this指的是MainActivity this.onClick(v);
# 程序中代码的变量可以随意修改 this.n.value = 0; this.m.value = 2; this.cnt.value = 999;
# 以下两种方式都能打印 send("Success!") console.log("Success!") } }); """ process = frida.get_usb_device(1000).attach('com.example.seccon2015.rock_paper_scissors') script = process.create_script(jscode) script.on('message', on_message) script.load() sys.stdin.read()
|
0x02 Native层Hook
也就是hook .so文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| jscode = """ setImmediate(function(){ send("start"); //遍历模块找基址 Process.enumerateModules({ onMatch: function (exp){ if (exp.name == "libpdd_secure.so") { send("enumerateModules find"); send(exp.name + "|"+ exp.base + "|"+ exp.size + "|"+ exp.path); send(exp); return 'stop'; }, onComplete: function(){ send('enumerateModules stop'); } }); // hook .so中的导出函数 var exports = Module.enumerateExportsSync("libpdd_secure.so"); for(var i=0; i<exports.length; i++){ send("name:" + exports[i].name + "address:" + exports[i].address); } """
|