本系列文章,将全貌的讲解App安全中常见的一些内容,包含了逆向分析,正向防护等的相关工具和处理思路,涉及抓包、脱壳、分析等多个环节。
本系列文章共2篇。第一篇可前往:App逆向安全(一)抓包与脱壳
通过脱壳,我们基本已经得到了具备可读性的代码了,但是如何将代码和实际app运行流程关联起来呢?这时,我们可以借助Frida强大的调试与Hook能力了。
所谓反调试,即App为了防止被第三方调试,所采取的防护手段。在很多场景下,单纯的通过对反编译代码的静态分析,很难高效的找到目标算法和逻辑,因此借助动态调试工具,可以达到事半功倍的效果,甚至对样本App的行为进行定制。而“过反调试”顾名思义,即绕过反调试的限制,继续达到调试app的目的。常见的反调试策略包含如下多种:
root检测逐渐成为现在的APP防护的一种方式,而我们要进行hook等更多操作,必须要获得root权限。root检测目前一般分为下面的一些方法
Xposed是一个动态插桩的hook框架,通过替换app_process原始进程,将java函数注册为native函数,从而获得更早的运行时机。Xposed检测详细的特征点可以参考下图,特征修改点就是我们可以进行检测的地方。
1)端口和frida_server检测:
最简单的一种检测方式,厂商通过检测端口是否为固定的27047,还可以检测运行的frida_server名称。
2)so层系统API检测:
直接调用openat的syscall的检测在text节表中搜索frida-gadget*.so / frida-agent*.so字符串,避免了hook libc来anti-anti的方法;
内存中存在frida rpc字符串,则认为有frida-server;
3)so层非系统API检测:
遍历连接手机所有端口发送D-bus消息,如果返回"REJECT"这个特征则认为存在frida-server。
/*
* Mini-portscan to detect frida-server on any local port.
*/
for(i = 0 ; i <= 65535 ; i++) {
sock = socket(AF_INET , SOCK_STREAM , 0);
sa.sin_port = htons(i);
if (connect(sock , (struct sockaddr*)&sa , sizeof sa) != -1) {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "FRIDA DETECTION [1]: Open Port: %d", i);
memset(res, 0 , 7);
// send a D-Bus AUTH message. Expected answer is “REJECT"
send(sock, "\x00", 1, NULL);
send(sock, "AUTH\r\n", 6, NULL);
usleep(100);
if (ret = recv(sock, res, 6, MSG_DONTWAIT) != -1) {
if (strcmp(res, "REJECT") == 0) {
/* Frida server detected. Do something… */
}
}
}
close(sock);
}
4)检测内存库来检测:
Frida 的各个模式都是用来注入的,我们可以利用的点就是 frida 运行时映射到内存的库,最直接的是挨个检查加载的库。
char line[512];
FILE* fp;
fp = fopen("/proc/self/maps", "r");
if (fp) {
while (fgets(line, 512, fp)) {
if (strstr(line, "frida")) {
/* Evil library is loaded. Do something… */
}
}
fclose(fp);
} else {
/* Error opening /proc/self/maps. If this happens, something is off. */
}
}
5)inlinehook检测frida:
frida实现hook一定实现了inlinehook技术,所以我们还可以通过inlinehook库来检测,参考文章:从inlinehook角度检测frida[2]
总体看,绕过反调试的限制,要么是基于app源码修改反调试代码逻辑后,重新打包运行,要么对app进行动态hook。前者并不一定能保证打包成功。我们重点关注后者,即通过静态代码分析,找到源码中反调试逻辑的核心检测点,通过frida js hook的方式,在启动app时,注入指定的js代码,使app原先的反调试检测失效,这样便可以继续对app进行调试。
比如,反调试的检测逻辑如下:
相应的frida hook脚本使用如下:
除了上述的方式外,过反调试也有一些其他通用做法,但大都针对相应的反调试策略才能有效。
比如frida server在启动时,会采用默认端口27047,如果样本app采用的反调试策略是检测27047端口是否被占用,那么我们可以启用其他端口以绕开检测限制,相应的frida server的启动命令修改为:
./frida_server -l 0.0.0.0:21000
为什么要特征化,因为去特征化之后,样本App中的反调试逻辑就无法通过特征信息识别到你了。frida server对应的比较常用且有效的去特征化替代,即hluwa大神发布的 hluda-server系列[3],该修改版本去除了大部分常见的frida特征信息(如frida关键字、端口等),而且该版本会跟随frida官方最新版本升级。如果社区的主流去特征版本仍然无法满足你的要求,那么你可以手动编译一个专属于自己的去特征版本,相关教程也可以参考文中:手动编译Hluda Frida Server[4]。
Xposed的去特征化版本也是类似思路,相关教程可参考:Xposed定制[5]。
上文已提到,不再赘述。
比较常用的即 watch 指令了。通过watch指令可以hook
任意方法的参数、返回值和调用栈,并打印到控制台方便分析,如
android hooking watch class_method android.bluetooth.BluetoothDevice.getName --dump-args --dump-return --dump-backtrace
比较详细的用法可以参考官网,或以下博文:https://www.cnblogs.com/lxh2cwl/p/14842544.html
自定义js脚本,完成我们想达到的目的。通常,frida注入并执行js的命令如下:
# hook_xxx_demo.js 即为注入的js文件
$ frida -U -f com.example.app -l hook_xxx_demo.js --no-pause
hook_xxx_demo.js
文件内容可如下:
setTimeout(
function () {
Java.perform(function () {
console.log("Hello world!")
})
})
一些通用的frida js,可以参考:awesome-frida[6]、frida-all-in-one[7]
二次打包主要依赖 apktool
,完成后,需要对应用进行重新签名。
## Objection
# 启动并注入到指定的app中
objection -d -g com.xxx.yyy explore
android hooking search classes display
android hooking search methods display
android hooking list class_methods com.android.settings.DisplaySettings
# 跟踪出入参、堆栈
android hooking watch class_method android.bluetooth.BluetoothDevice.getName --dump-args --dump-return --dump-backtrace
## frida
pip3 install frida-tools==10.6.2
pip3 install frida==15.2.2
frida -U -f com.xxx.yyy -l ./frida-hook-scripts/http-proxy-bypass.js --no-pause
# frida自定义端口转发
./frida-server -l 0.0.0.0:1234
adb forward tcp:1234 tcp:1234
frida -H 127.0.0.1:1234 <packageName> -l script-xxx.js
实用 FRIDA 进阶 --- objection :内存漫游、hook anywhere、抓包[8]
Android APP漏洞之战(10)——调试与反调试详解[9]
Https防抓包机制[10]
[1]
App逆向安全(一)抓包与脱壳: https://blog.fh6766.com/2023/10/16/app-security-01/[2]
从inlinehook角度检测frida: https://bbs.pediy.com/thread-269862.htm[3]
hluda-server系列: https://github.com/hzzheyang/strongR-frida-android/releases[4]
手动编译Hluda Frida Server: https://bbs.kanxue.com/thread-269889.htm[5]
Xposed定制: https://bbs.pediy.com/thread-269627.htm[6]
awesome-frida: https://github.com/dweinstein/awesome-frida[7]
frida-all-in-one: https://github.com/hookmaster/frida-all-in-one[8]
实用 FRIDA 进阶 --- objection :内存漫游、hook anywhere、抓包: https://blog.csdn.net/lyshark_lyshark/article/details/125848170[9]
Android APP漏洞之战(10)——调试与反调试详解: https://bbs.kanxue.com/thread-272452.htm[10]
Https防抓包机制: https://www.jianshu.com/p/a004f081d8aa