# noob の Frida_study
!! 一眼丁真 鉴定为我是一个纯纯的大摆子 学习不行要挂科 CTF 题做不来 只有睡觉才维持得了生活!!
# 搭建环境
mumu 模拟器搞的 QAQ
不行啊 Frida 过后在模拟器运行 APP 感觉还是有点小问题 得想办法搞一个真机先
# 真机测试
# 搭建 frida 开发环境
git clone git://github.com/oleavr/frida-agent-example.git | |
cd frida-agent-example/ | |
npm install | |
frida -U -f com.example.android --no-pause -l _agent.js 这里我直接VScode了 |
# frida 常用命令
frida-ls-devices # 列出所有设备
frida-ps -U # 列出usb设备的进程
frida-ps -Ua # 列出正在跑的应用
frida-ps -Uai # 列出所有安装的应用
frida-ps -D xxxxx # 连接指定的设备,设备id可以从第一条命令获得
# 启动应用并注入脚本 后面会提到这两者的区别
frida -U -l exploit.js -f com.xxx.yyy
# 应用已经在运行,注入脚本
frida -U -l exploit.js "XXXX"
# 实践
# Frida 对函数的调用
# Frida_Hook
1.attach
对手机最前面的一个进程操作 (或者 frida -UF)
或 frida -U -n 名字
2.spawn
frida -U -f (包名)
# CTF 题
学习在 java 层怎么使用 frida 实现:
- 任意类方法调用。
- 任意类方法重实现。
# rps
使用 jadx 反编译得到
private final Runnable showMessageTask = new Runnable() { | |
public void run() { | |
TextView tv3 = (TextView) MainActivity.this.findViewById(R.id.textView3); | |
MainActivity mainActivity; | |
if (MainActivity.this.n - MainActivity.this.m == 1) { | |
mainActivity = MainActivity.this; | |
mainActivity.cnt++; | |
tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt)); | |
} else if (MainActivity.this.m - MainActivity.this.n == 1) { | |
MainActivity.this.cnt = 0; | |
tv3.setText("LOSE +0"); | |
} else if (MainActivity.this.m == MainActivity.this.n) { | |
tv3.setText("DRAW +" + String.valueOf(MainActivity.this.cnt)); | |
} else if (MainActivity.this.m < MainActivity.this.n) { | |
MainActivity.this.cnt = 0; | |
tv3.setText("LOSE +0"); | |
} else { | |
mainActivity = MainActivity.this; | |
mainActivity.cnt++; | |
tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt)); | |
} | |
// 获胜 1000 次则能够获取 flag | |
if (1000 == MainActivity.this.cnt) { | |
tv3.setText("SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}"); | |
} | |
MainActivity.this.flag = 0; | |
} | |
}; |
可以看到分析 calc () 方法能算出答案,但这个方法在 so 中,得分析汇编代码才行,可以尝试使用 ida
这里我们用 frida hook 解决 让 cnt 的值构造成 1000 即可
frida -U -l test.js -f com.example.seccon2015.rock_paper_scissors
JS 脚本:
Java.perform (() => { | |
// 选择类 | |
const MainActivity = Java.use ('com.example.seccon2015.rock_paper_scissors.MainActivity'); | |
// 选择 onClick 方法 | |
const onClick = MainActivity.onClick; | |
// hook onClick | |
onClick.implementation = function (v) { | |
// 函数被调用的时候打印一条消息 | |
send ('onClick'); | |
// 调用原始的 onClick 方法 | |
onClick.call (this, v); | |
// 调用完之后修改 m,n,cnt 的值 | |
this.m.value = 0; | |
this.n.value = 1; | |
this.cnt.value = 999; | |
//frida 控制台打印结果 | |
//hook 结束 | |
console.log ('Done:' , JSON.stringify (this.cnt)); | |
}; | |
}); |
# WhyShouldIPay
PREMIUM CONETNT 内容需要输入 License 验证后才能看
MainActivity 中看到 xor 加密方法 按 x 查找用例
发现 LauncherActivity 是验证部分,前面有个网络验证,显然需要绕过,后面调用了 xor 方法运算
先 hook 一下看 mac 值
直接构造 Key 再 hook verifyClick 方法 直接 show flag 即可
# 坑
Frida 版本一定不要高!!!
安卓手机版本太高 搞了我 10 个小时 焯!
心态爆炸之又重新换成安卓 10 又 ROOT 之终于成功了