本系列文章,将全貌的讲解App安全中常见的一些内容,包含了逆向分析,正向防护等的相关工具和处理思路,涉及抓包、脱壳、分析等多个环节。

本系列文章共2篇。第一篇可前往:App逆向安全(一)抓包与脱壳

1、调试/分析源码,获取核心算法

通过脱壳,我们基本已经得到了具备可读性的代码了,但是如何将代码和实际app运行流程关联起来呢?这时,我们可以借助Frida强大的调试与Hook能力了。

1.1 Frida的”反调试”与”过反调试”

所谓反调试,即App为了防止被第三方调试,所采取的防护手段。在很多场景下,单纯的通过对反编译代码的静态分析,很难高效的找到目标算法和逻辑,因此借助动态调试工具,可以达到事半功倍的效果,甚至对样本App的行为进行定制。而“过反调试”顾名思义,即绕过反调试的限制,继续达到调试app的目的。常见的反调试策略包含如下多种:

1.1.1 模拟器检测

905443_TEQRCAWTTAENQ42

1.1.2 Root检测

root检测逐渐成为现在的APP防护的一种方式,而我们要进行hook等更多操作,必须要获得root权限。root检测目前一般分为下面的一些方法

1.1.3 Hook检测

(1)Xposed检测

Xposed是一个动态插桩的hook框架,通过替换app_process原始进程,将java函数注册为native函数,从而获得更早的运行时机。Xposed检测详细的特征点可以参考下图,特征修改点就是我们可以进行检测的地方。

(2)Frida检测

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

过反调试

总体看,绕过反调试的限制,要么是基于app源码修改反调试代码逻辑后,重新打包运行,要么对app进行动态hook。前者并不一定能保证打包成功。我们重点关注后者,即通过静态代码分析,找到源码中反调试逻辑的核心检测点,通过frida js hook的方式,在启动app时,注入指定的js代码,使app原先的反调试检测失效,这样便可以继续对app进行调试。

比如,反调试的检测逻辑如下:

相应的frida hook脚本使用如下:

905443_S4SZ3WQQQS8KFKY

除了上述的方式外,过反调试也有一些其他通用做法,但大都针对相应的反调试策略才能有效。

(1)使用调试工具时,采用自定义配置

比如frida server在启动时,会采用默认端口27047,如果样本app采用的反调试策略是检测27047端口是否被占用,那么我们可以启用其他端口以绕开检测限制,相应的frida server的启动命令修改为:

./frida_server -l 0.0.0.0:21000
(2)采用去特征化的调试工具

为什么要特征化,因为去特征化之后,样本App中的反调试逻辑就无法通过特征信息识别到你了。frida server对应的比较常用且有效的去特征化替代,即hluwa大神发布的 hluda-server系列,该修改版本去除了大部分常见的frida特征信息(如frida关键字、端口等),而且该版本会跟随frida官方最新版本升级。如果社区的主流去特征版本仍然无法满足你的要求,那么你可以手动编译一个专属于自己的去特征版本,相关教程也可以参考文中:手动编译Hluda Frida Server

Xposed的去特征化版本也是类似思路,相关教程可参考:Xposed定制

(3)frida hook js绕过反调试检测

上文已提到,不再赘述。

1.2 Objection

比较常用的即 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

1.3 Frida + Hook JS

自定义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-fridafrida-all-in-one

2、二次打包

二次打包主要依赖 apktool,完成后,需要对应用进行重新签名。

3、常用命令

## 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

4、推荐阅读

实用 FRIDA 进阶 — objection :内存漫游、hook anywhere、抓包

Android APP漏洞之战(10)——调试与反调试详解

Https防抓包机制