玄知安全实验室
- 关注

第六关
又是熟悉的套路,get_flag()中传入Checker参数,
而满足if (1234 == A.num1 && 4321 == A.num2) 的时候,就能得到答案
let Checker = Java.use("com.ad2001.frida0x6.Checker");
let Checkobj = Checker.$new();
Checkobj.num1.value=1234
Checkobj.num2.value=4321
先实现了if判断,因为要调用的类是MainActivity,还得用上一关的方法去找实例
Java.performNow(function() {
Java.choose('com.ad2001.frida0x6.MainActivity', {
onMatch: function(instance) {
console.log("Instance found");
最后再去用找到的MainActivity实例去执行get_flag(Checker A)
instance.get_flag(checker_obj);
第七关
还是直接看代码,也是在MainActivity中的flag()传参Checker
这次在Checker中有构造方法,需要在实例化Checker的时候传参,并且满足
if (A.num1 > 512 && 512 < A.num2) {
Java.performNow(function() {
Java.choose('com.ad2001.frida0x7.MainActivity', {
onMatch: function(instance) {
console.log("Instance found");
var Checker = Java.use("com.ad2001.frida0x7.Checker");
var Checker_obj = Checker.$new(5000,5000);
instance.flag(Checker_obj);
},
onComplete: function() {}
})
})
这关学的是frida实例化类并调用构造方法传参
第八关
APP终于有输入框了,是这样的
打开发现MainActivity中提交的值会传入cmpstr()中,而cmpstr()会载入一个so文件,在资源文件中找到了这个so文件
用AndroidKiller或者直接APKtool提取so文件
在这个界面按x,跳到真正处理的位置
伪代码读着大概是传入一个s1,for循环产生一个s2,然后比较s1和s2
因为cmpstr是native函数,就需要使用相应的方法,方法模板是这样的
Interceptor.attach(targetAddress, {
onEnter: function (args) {
console.log('Entering ' + functionName);
// Modify or log arguments if needed
},
onLeave: function (retval) {
console.log('Leaving ' + functionName);
// Modify or log return value if needed
}
});
获取导入和导出内存地址的方法Module.enumerateImports()
Module.enumerateExports()
这里查到所有导出中最像的是Java_com_ad2001_frida0x8_MainActivity_cmpstr,
并且发现so文件中strcmp的导入文件是libc.so
现在就尝试获取strcmp的两个参数,其中第一个参数是我们输入的,第二个就是要和我们输入比对的字符串,获取它应该就能得到最终答案。
这里使用Memory.readUtf8String用来获取内存中参数的值
var strcmp_adr = Module.findExportByName("libc.so", "strcmp");
Interceptor.attach(strcmp_adr, {
onEnter: function (args) {
var arg0 = Memory.readUtf8String(args[0]);
var flag = Memory.readUtf8String(args[1]);
if (arg0.includes("tttttttttt")) {
console.log("Hookin the strcmp function");
console.log("Input " + arg0);
console.log("The flag is "+ flag);
}
},
onLeave: function (retval) {
}
});
第九关
看源码。。。
看IDA。。。
源码中判断check_flag()的返回值是不是1337,so文件中的check_flag()直接就返回一个值。看样子这关要学会改返回值,改返回值可以用retval.replace(1337)方法
启动APP报错。。。frida-ps -Uai可以看到这关的包名有点变化
var check_flag_addr = Module.enumerateExports("liba0x9.so")[0]['address']
Interceptor.attach(check_flag_addr, {
onEnter: function () {
},
onLeave: function (retval) {
console.log("retval is " + retval);
retval.replace(1337) //主要是这句
}
});
第十关
开局就是这样的,通过后缀名是.KT可以猜测是Kotlin编写的,并且关键代码都没在这里
载入.so文件,用IDA搜索一下关键字,找到一个
Java_com_ad2001_frida0xa_MainActivity_stringFromJNI函数
这里还能看到一个get_flag函数,是这关的关键
或者用Ghidra来找
可以发现就是要找到get_flag()的地址然后给他传参使两个参数加起来等于3,本关的难点是调用Native function
frida 中调用原生函数,要创建一个NativePointer
对象,构造他有三个参数(NativePointer对象,返回值类型,参数类型),而构造NativePointer对象又有一个参数就是get_flag()函数的指针
那么首先要找到get_flag()的BaseAddress和偏移
偏移=get_flag()函数的内存地址-逆向工具的载入初始地址
get_flag()函数的内存地址用鼠标点击黄色函数名就可以查看
逆向工具的载入初始地址可以点击这里查看
偏移=0x001206b0-00100000=0x206b0
然后就可以写代码了
var get_flag_addr = Module.findBaseAddress("libfrida0xa.so").add(0x206b0) //baseaddr+偏移
var get_flag_obj = new NativePointer(get_flag_addr); //创建NativePointer对象来给NativeFunction传参
const get_flag = new NativeFunction(get_flag_obj, 'void', ['int', 'int']); //关键,
get_flag(1,2);
最后用adb logcat命令获取app运行的日志就可以看到答案了
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)