Frida与Android CTF
TideSec
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
Frida与Android CTF
Frida与Android CTF
前言
最近练习了下CTF中Android相关题目,发现三题分别考察了三个点: 1、Frida Java Hook与静态函数的主动调用 2、Frida遍历ClassLoader从而Hook动态加载的Ddex的函数 3、Frida Native Hook去反调试
第一题 Frida静态函数的主动调用
首先安装第一款APP运行发现提示说需要输入纯数字,另外当输入错误时会调试”请继续加油“。





var CONTEXT = null;
function getObjClassName(obj) {
if (!jclazz) {
var jclazz = Java.use("java.lang.Class");
}
if (!jobj) {
var jobj = Java.use("java.lang.Object");
}
return jclazz.getName.call(jobj.getClass.call(obj));
}
function hookReturn() {
Java.perform(function () {
Java.use("com.kanxue.pediy1.VVVVV").VVVV.implementation = function (context, str) {
var result = this.VVVV(context, str)
console.log("context,str,result => ", context, str, result);
console.log("context className is => ", getObjClassName(context));
CONTEXT = context;
return true;
}
})
}
function invoke() {
Java.perform(function () {
//console.log("CONTEXT IS => ",CONTEXT)
var MainActivity = null;
Java.choose("com.kanxue.pediy1.MainActivity", {
onMatch: function (instance) {
MainActivity = instance;
},
onComplete: function () { }
})
var CONTEXT2 = Java.use("com.kanxue.pediy1.MainActivity$1").$new(MainActivity);
var javaString = Java.use("java.lang.String").$new("12345");
for (var x = 0; x < (99999 + 1); x++) {
var result = Java.use("com.kanxue.pediy1.VVVVV").VVVV(CONTEXT2, String(x));
console.log("now x is => ", String(x))
if (result) {
console.log("found result is => ", String(x))
break;
}
}
})
}
function main() {
hookReturn()
}
验证成功
第二题 Frida Hook动态加载Dex
通过Jadx分析发现了Dex的动态加载以及Native函数的引入。


function invoke2() {
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass("com.kanxue.pediy1.VVVVV")) {
console.log("Successfully found loader")
console.log(loader);
Java.classFactory.loader = loader;
}
}
catch (error) {
console.log("find error:" + error)
}
},
onComplete: function () {
console.log("end1")
}
})
var javaString = Java.use("java.lang.String").$new("12345");
for (var x = 0; x < (99999 + 1); x++) {
var result = Java.use("com.kanxue.pediy1.VVVVV").VVVV(String(x));
console.log("now x is => ", String(x))
if (result) {
console.log("found result is => ", String(x))
break;
}
}
})
}
function main() {
}
setImmediate(main)
不过测试发现flag不对

function invoke2() {
Java.perform(function () {
var MainActivity = null;
Java.choose("com.kanxue.pediy1.MainActivity",{
onMatch:function(instance){
MainActivity = instance;
},
onComplete:function(){}
})
var loader1 = null;
var loader2 = null;
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass("com.kanxue.pediy1.VVVVV")) {
console.log("Successfully found loader")
console.log(loader);
loader2 = loader;
Java.classFactory.loader = loader2;
}else if(loader.findClass("com.kanxue.pediy1.MainActivity")){console.log("Successfully found loader")
console.log(loader);
loader1 = loader;
}else{
}
}
catch (error) {
console.log("find error:" + error)
}
},
onComplete: function () {
console.log("end1")
}
})
var javaString = Java.use("java.lang.String").$new("12345");
for (var x = 0; x < (99999 + 1); x++) {
var result1 = MainActivity.stringFromJNI(String(100000 - x));
var result2 = Java.use("com.kanxue.pediy1.VVVVV").VVVV(String(result1));
console.log("now x is => ", String(x))
if (result2) {
console.log("found result2 is => ", String(100000 - x))
break;
}
}
})
}
function main() {
}
setImmediate(main)
测试发现flag66998时正确

第三题 Native层去反调试
该题在第二题的基础上加入了native层对Frida的反调试。 反调试逻辑: 通过一直循环创建Socket连接,遍历端口,检查端口是否被占用,收到“REJECT”时,说明frida-server正在运行,然后直接kill掉进程。 测试也发现当通过frida进行hook时,APP会崩掉。
frida -U -f com.kanxue.pediy1 -l /Users/tale/Downloads/20220317/111.js --no-pause

function replaceKill(){
var kill_addr = Module.findExportByName("libc.so", "kill");
Interceptor.replace(kill_addr,new NativeCallback(function(arg0,arg1){
console.log("arg0=> ",arg0)
console.log("arg1=> ",arg1)
},"int",['int','int']))
}
function main() {
replaceKill();
}
发现frida-server和APP正常运行,从而成功绕过了对frida的反调试。 接下来将反调试代码加入到题目二中进行爆破可成功得到该题目flag99998。

总结
这三道题主要逻辑就是输入flag验证对错,并且flag的求解都是通过爆破长度为5位的数字,程序本身利用hash加密后与程序已有密文进行对比,总体来说可以使用Frida爆破一把梭。
参考资料
https://bbs.pediy.com/thread-260550.htm
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 TideSec 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
某次攻防演练中对任意文件读取漏洞的利用
2023-07-05
记一次对某企业的渗透测试
2023-07-05
用户名密码加密的页面爆破学习
2023-07-05
文章目录