声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!
逆向这门手艺,真是越学越让人摸不着头脑。最大的感受就是神仙打架凡人遭殃。行业顶端的大佬,一边搞加固,一边搞破解,把需要学习的知识累得高高的。
我们这些小虾米,还能做什么呢,只能适应环境,慢慢学了。
简述
本篇类似学习笔记,具体的APK和版本参考https://mp.weixin.qq.com/s/A4EllU2PxSB91Orpliqkzw 。这里不过多赘述。原文中对如何从混淆的so中找到sign签名,说的比较简单。我打算在此基础上,说一下我是怎么做的。以及IDA插件findhash怎么用,在网上找了半天的资料,才勉强把流程走完。
混淆so
apk采用的是腾讯乐固以及VMP混淆
在so上的体现就是,真是壮观ovo
经过分析,sign生成位置在showstart_net.so ,native中函数名称被混淆了
该apk的sign值是这样子的
如果有经验的,我们一眼可以看出这是md5加密,但不确定有没有进行魔改以及传入的参数是什么。
根据经验fuzz 我们假设这是标准的md5,一般来说,md5加密的携带的可能是md5(str(参数+时间戳))之类的,但这种并不靠谱,因为开发只需要随便加点字符就会导致结果大不一样。
接下来的任务就是判断
-
md5是不是标准的,有没有魔改
-
hash的参数是什么
IDA plugin findhash
下载地址:https://github.com/Pr0214/findhash
下载两个文件,放到ida的plugin目录下
然后打开IDA,等待一阵子,一开始可能不会出现,需要缓一会
会不断反编译弹窗,时间可能比较长,耐心等待
编译完成
查看生成的frida js ,直接运行报错
frida -f
因为直接加载的时候,可能so还没有加载,UF启动不会有这个问题
可以写一个函数,检测到so被加载了的时候执行
// 其中没有过frida的脚本,如果没有尝试使用florida-server-16.1.2
function main() {
hook_dlopen_so();
}
setImmediate(main);
/*
* hook 加载so的函数,
* */
function hook_dlopen_so() {
var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
var so_name = args[0].readCString();
if (so_name.indexOf("libshowstart_net.so") >= 0) this.call_hook = true;
}, onLeave: function (retval) {
if (this.call_hook) demo();
}
});
}
function demo() {
var targetSo = Module.findBaseAddress('libshowstart_net.so');
hook_suspected_function(targetSo);
}
如果报错,把下面这一个删了
加入hook_native_addr(funcPtr);
function print_arg(addr) {
var module = Process.findRangeByAddress(addr);
if (module != null) {
return hexdump(addr) + "n";
} else {
return ptr(addr) + "n";
}
}
function hook_native_addr(funcPtr) {
var module = Process.findModuleByAddress(funcPtr);
Interceptor.attach(funcPtr, {
onEnter: function(args) {
// console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("n"));
this.args0 = args[0];
this.args1 = args[1];
this.args2 = args[2];
this.args3 = args[3];
this.logs = [];
this.logs.push("call " + module.name + "!" + ptr(funcPtr).sub(module.base) + "n");
this.logs.push("this.args0 onEnter: " + print_arg(this.args0));
this.logs.push("this.args1 onEnter: " + print_arg(this.args1));
this.logs.push("this.args2 onEnter: " + print_arg(this.args2));
// this.logs.push("this.args3 onEnter: " + print_arg(this.args3));
},
onLeave: function(retval) {
this.logs.push("this.args0 onLeave: " + print_arg(this.args0));
this.logs.push("this.args1 onLeave: " + print_arg(this.args1));
this.logs.push("this.args2 onLeave: " + print_arg(this.args2));
// this.logs.push("this.args3 onLeave: " + print_arg(this.args3));
this.logs.push("retval onLeave: " + print_arg(retval));
this.logs.push("retval onLeave: " + retval + "n");
console.log(this.logs);
}
});
}
在登陆界面输入账号密码,查看console.log的日志
抓包得到的
完全一致,也就是这里做到的,接下来判断传入的参数
均是从arg1取值,将arg1的所有值拼接起来,然后md5
结果和md5以及抓包得到的一致,是标准的md5
成功根据hook找到了so中sign签名的入口和返回点
参考链接
md5在ida中的识别及使用方法 https://mp.weixin.qq.com/s/QdiLQSV4bOipbhBaIN61EA
记录一次秀动APP的逆向 https://mp.weixin.qq.com/s/A4EllU2PxSB91Orpliqkzw
原文始发于微信公众号(进击的HACK):在混淆的so中寻找sign签名函数
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论