首页
论坛
课程
招聘
[原创]分享一个基本不可能被检测到的hook方案
2021-10-19 19:57 32995

[原创]分享一个基本不可能被检测到的hook方案

2021-10-19 19:57
32995

背景

最近项目里需要通过hook对APP的行为进行监控,需要满足如下几个需求:

  1. 兼容性好,能够兼容99.9%的APP
  2. 不能被APP的安全机制检测到导致APP逻辑不正常或者hook失败
  3. 能够实时地与PC端进行通信,上报监控信息
  4. hook时机要非常早,不能出现漏检的情况
  5. 因为APP量非常大,需要一种通用化方案,不能出现对特定APP进行定制的情况
    因此,考虑了下述几种方案:

Frida Server hook方案

这也是之前在使用的方案。基于frida的hook,是一种常见的hook方案,该方案实现简单,可扩展性强,易于调试和修改,hook代码可以随时修改,还能通过RPC方便地在PC上进行交互,能够绕过大部分hook检测,自然也就成了逆向人员最常见的一种分析手段。
缺点:
该方案虽然有很多优势,但也存在着一些缺陷:

  1. 但是该方案因其过于出名,也导致很多加固厂商对其进行了针对性的检测,在部分保护强度较高的APP上无法正常运行。
  2. frida本身虽然兼容性虽然较好,但在注入过程中,仍会出现在部分APP上无法正常运行的情况。
    因此,该方案虽然在90%的情况下能够满足需求,但是需求1和需求2仍有小概率不满足。

Frida Gadget hook方案

这是Frida Server在部分场景下被检测到,而且在部分APP中无法正常注入,从而萌生的思路。
为了实现持久化,frida给出了Gadget方案,该方案通过对APK进行重打包,向lib目录中添加Gadget的动态链接库,然后反编译dex,在dex中添加加载该动态链接库的代码,以此实现持久化。
缺点:

  1. 重打包方案是Gadget的最原始使用方式。该方案虽然避免了运行时的注入过程,提高了兼容性,但是对APK的重打包,需要绕过APK本身的签名校验和文件校验,虽然可以用自动化脚本实现签名校验和文件校验的绕过,但是如果被检测的APP是使用汇编编写的open()函数,也是绕不过去的。需求2不满足
  2. 除了重打包方案,因为之前自己做过SO的静态注入,所以也考虑过对APP安装后解压出来的so文件进行静态注入,这样就可以避过签名校验和文件校验。但是这种方案比较依赖于so文件的加载时机,虽然加固后的APP,壳so往往都会在最早的时候进行加载,但是也难以保证适用于所有APP。需求4不满足

XPOSED方案

XPOSED方案比较容易被检测,而且在与PC的交互上也不是太好。因此需求3和需求2都不满足

定制ROM方案

定制ROM方案类似于脱壳机,基本上不可能被检测,而且兼容性也非常好。但是该方案基本上只能用于开放源代码的系统机型,而且系统的编译时间非常长,每一点微小的改动都需要重新编译并刷机并重启系统,开发调试费时费力,后续更新极其不方便。而且与PC端的通信也比较麻烦。
该方案属于一种可行方案,但是耗时过长,成本太高,属于最后实在没有其他办法了之后的办法。

基于系统组件替换的定制ROM方案

总结上述几种方案,可以发现,目前的几种方案主要有以下几个问题需要解决:

  1. 对APP或进程的侵入式修改,会在侵入过程中留下痕迹,这些痕迹容易被hook检测机制检测到
  2. 与PC端进行实时通信
  3. 降低开发与维护成本

系统so替换

这是早期的思路,通过对系统so进行静态注入,使得APP在启动时加载系统so,顺带的把我们自定义的so加载起来,因为这个自定义的so名称可以自定义,以及Android的碎片化,APP基本上不可能根据so的名称来对这种hook方式进行检测。
然而,想法很丰满,现实很骨感,实际测试下来发现,Android系统启动时,会先生成Zygote进程,在Zygote进程中加载所有必需的so,后续所有的APP进程都是Zygote fork出来的,因此,替换后的系统so的加载时机并不是在APP启动时
那么,能不能启动一个线程,不断循环检测要hook的APP是否被fork了呢?然而生活又给了我致使一击,Zygote在fork进程之前,会先等待进程中的所有子线程结束,以免某些子线程中的任务还没完成就进行了fork,导致功能异常。因此,如果启动一个线程,就会导致整个系统直接就起不来了(因为还有一些包括Launcher在内的系统APP需要通过Zygote fork出来)
有没有一个so,是在APP启动时进行加载的呢?通过对比Zygote进程和一个简单demo的maps列表,发现/system/lib/hw/gralloc.default.so这个so是在APP启动时加载的,经过一番百度,这个so应该是与APP图形界面渲染有关的so,而根据so的命名可以看出,这个so是有可能根据硬件的不同而变化的。而且经过测试,这个so是在Activity被启动时才加载的,因此,假如APP在Application中进行了一些操作,这种方案是监控不到的。

Riru插件定制

其实Riru的整体思路和系统so替换的思路是很相似的,不过个人感觉系统so替换的思路要比Riru的思路实现起来更简单一些。
Riru相比于系统so替换的强大之处在于他对APP启动时会调用的函数进行了hook,并以插件的形式对外提供了接口,免去了自己再去研究源码,寻找hook点。
接下来编写了一个插件使用Frida Gadget进行尝试,然后再次发现悲催了,Frida Gadget的Listen模式中,需要PC端找到APP进程然后恢复程序运行,但是Riru提供的接口中,进程的相关环境还没有完全初始化好,使用PS命令查找不到进程
最后的最后,在Frida的JS API中找到了网络相关的API,因此采用了Frida Gadget的script的模式,然后在hook接口中实现了一个TCP服务器,将hook信息通过网络通信及adb转发发送到PC端。
整个流程为:

  1. 编写Riru插件gadget_loader:功能为读取配置文件(放置在/data/local/tmp目录下),根据配置文件,若当前APP是需要检测的APP,则加载libgadget.so。
  2. 在插件中添加libgadget.so及其配置文件
  3. 安装gadget_loader插件。
  4. 将libloader.so的配置文件和libgadget.so需要执行的脚本放置到/data/local/tmp目录下
  5. libgadget.so脚本通过hook对应API监控APP接口调用行为,并通过网络连接将监控信息发送至PC

总结

最后总结一下这个方案的几个特点:

  1. 不需要对APK进行修改,也不需要对进程进行注入,因此可以避开APP的检测机制
  2. 方案为了方便,最后采用了Riru插件进行实现,这使得APP有可能检测到存在Riru插件,如果碰到这种情况,完全可以采用系统so替换的方案,然后模仿Riru的思路hook几个API,实现Gadget so的加载,这样就基本上不可能被检测到了。
  3. 因为整个方案只是替换一个系统so,并添加了几个文件到系统中,实现了APK的零侵入,对系统的侵入也非常的小,兼容性会非常好(主要取决于Frida Gadget中是否有bug)
  4. 与PC端的交互采用的是socket通信,这个通信的接口是可自定义的,在保证了与PC端交互的同时又能避免固定端口被检测
  5. 整个方案的实现过程非常简单,低版本的系统上可以直接替换系统so,高版本的系统因为一些Android的安全机制,只能采用Magisk插件的形式进行so的替换,不过高版本系统上的root本来就几乎都是使用Magisk,这点小小的前置要求就也就几近于无了

保密原因,代码就不放了,个人觉得整个流程还是挺简单的,自己整一整就能搞出来了


[2022夏季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞4
打赏
分享
最新回复 (18)
雪    币: 648
活跃值: 活跃值 (1417)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Monkeylord 活跃值 2021-10-19 20:29
2
3
有点复杂,其实只需要把frameworks.jar二次打包一下,在application初始化里加载一下so就可以了。
雪    币: 6778
活跃值: 活跃值 (2856)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
v0id_ 活跃值 2021-10-19 20:30
3
0
思路挺好,但是只要 libgadget.so 加载到 app 的内存中,还是避免不了检测a
雪    币: 179
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_hgrbqfun 活跃值 2021-10-19 23:24
4
0

去检测函数汇编起始是不是

jmp frida的so的代码地址
或 
ldr 寄存器,frida的so的代码地址
br 寄存器

,就知道了。


总归 frida是要动代码段的汇编去hook的。

最后于 2021-10-20 00:55 被mb_hgrbqfun编辑 ,原因:
雪    币: 1015
活跃值: 活跃值 (962)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huangjw 活跃值 2021-10-21 09:42
5
0
先收藏,有空学学习,谢谢分享经验
雪    币: 1154
活跃值: 活跃值 (890)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
奋斗der小鸟 活跃值 2021-10-21 10:53
6
2
自己的写的一个小工具,一直在用,https://github.com/qiang/Riru-ModuleFridaGadget
雪    币: 601
活跃值: 活跃值 (1480)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 活跃值 2021-10-24 17:00
7
0
mark
雪    币: 206
活跃值: 活跃值 (317)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yujincheng08 活跃值 2021-11-12 23:19
8
0
替换 so 是被 riru 淘汰的方案。。。
雪    币: 353
活跃值: 活跃值 (1818)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
whulzz 活跃值 1 2021-11-13 07:36
9
0
请把标题改一下,谢谢
雪    币: 3725
活跃值: 活跃值 (1298)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
梦野间 活跃值 4 2021-11-16 01:15
10
0
统一回复下
1. 说替换so是riru淘汰的方案的人,一定没有认真了解过riru的方案,riru是把一个不常用的so给整个替换掉了,但是部分app还是会用到这个so,所以会有兼容性问题。而我这里是采用的so依赖注入,原so的功能仍然保留着,所以不会有兼容性问题。
2. 说检测汇编特征的。你都不知道我hook了哪些api,你怎么检测,难道把所有接口全部扫描一遍?更何况有些app或者sdk自带了inline hook,对常用接口的检测极容易误伤
3. 说检测Gadget的。Gadget这个so完全可以任意改名,不知道你是想要怎么检测。
雪    币: 162
活跃值: 活跃值 (2083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 活跃值 2021-11-16 10:37
11
1
梦野间 统一回复下 1. 说替换so是riru淘汰的方案的人,一定没有认真了解过riru的方案,riru是把一个不常用的so给整个替换掉了,但是部分app还是会用到这个so,所以会有兼容性问题。而我这里是采 ...

哥哥,看了你这个回复,我认真读了一下你的文章
gadget特征简直不要太多,随便一想就来了
1,内存字符串特征
2,maps 系统库hook特征
3,frida线程特征

检测汇编内心os:人家说的是从frida hook原理去检测呀,哥哥可以看下这篇文章:https://bbs.pediy.com/thread-268586.htm

最后,请哥哥把标题改一下,谢谢

最后于 2021-11-16 11:12 被huaerxiela编辑 ,原因:
雪    币: 3725
活跃值: 活跃值 (1298)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
梦野间 活跃值 4 2021-11-16 12:48
12
0
huaerxiela 梦野间 统一回复下 1. 说替换so是riru淘汰的方案的人,一定没有认真了解过riru的方案,riru是把一个不常用的so给整个替换掉了,但是 ...
你说的这些方案看似很好,实际使用起来其实都没办法商用。究其原因无非是性能消耗和误报问题。
目前这个方案我至少测了100款app了,不管是加固的还是没加固的,目前还没遇到过能离线检测的。
你能说大家都不知道这些方案吗?当然不是。对于一个成熟的产品来说,兼容性才是最重要的,你的防护方案要是把别人app搞崩溃了,你看业务方怼不怼死你
雪    币: 162
活跃值: 活跃值 (2083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 活跃值 2021-11-16 13:19
13
0


最后于 2021-11-16 13:19 被huaerxiela编辑 ,原因:
雪    币: 162
活跃值: 活跃值 (2083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 活跃值 2021-11-16 13:19
14
0
梦野间 你说的这些方案看似很好,实际使用起来其实都没办法商用。究其原因无非是性能消耗和误报问题。 目前这个方案我至少测了100款app了,不管是加固的还是没加固的,目前还没遇到过能离线检测的。 你能说大家 ...
都没办法商用
这个不太认可
但是
就这样吧
我多读会书去
雪    币: 3725
活跃值: 活跃值 (1298)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
梦野间 活跃值 4 2021-11-16 13:37
15
0
huaerxiela 都没办法商用 这个不太认可 但是 就这样吧 我多读会书去 [em_85]
你工作以后就知道了,企业的产品首要考虑的是赚钱,能不能赚到钱才是首位的。要赚钱就要考虑性价比,没人会花那么大的精力去开发一个收益极低的功能
安全,没你想象中那么重要
雪    币: 3725
活跃值: 活跃值 (1298)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
梦野间 活跃值 4 2021-11-16 19:27
16
0
纠正一下我的错误,frida的线程名检测确实属于一种成本很低的检测方案。
不过这点其实很容易规避,重编译frida的so或者换一个hook框架都可以解决。不过这样就陷入到了无尽的攻防对抗中了。
这就和某些脱壳机会有一些明显的特征一样,这种特征其实没有什么检测的价值,因为太容易被修改了。你不能因为脱壳机有一个明显的特征就说脱壳机是容易被检测到的
雪    币: 206
活跃值: 活跃值 (317)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yujincheng08 活跃值 2021-11-16 23:28
17
1
梦野间 统一回复下 1. 说替换so是riru淘汰的方案的人,一定没有认真了解过riru的方案,riru是把一个不常用的so给整个替换掉了,但是部分app还是会用到这个so,所以会有兼容性问题。而我这里是采 ...
我就是 riru 维护者之一,说我不懂 riru 可还行。。。
雪    币: 206
活跃值: 活跃值 (317)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yujincheng08 活跃值 2021-11-16 23:30
18
1
梦野间 统一回复下 1. 说替换so是riru淘汰的方案的人,一定没有认真了解过riru的方案,riru是把一个不常用的so给整个替换掉了,但是部分app还是会用到这个so,所以会有兼容性问题。而我这里是采 ...
你这玩意儿还不如 magisk 新出的 zygisk。虽然 zygisk 也是还没正式发布就就被我瞬间检测出来了
雪    币: 1279
活跃值: 活跃值 (429)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
残页 活跃值 2021-11-16 23:38
19
0
一键检测替换 so:https://github.com/vvb2060/MagiskDetector 检测系统文件修改那项
游客
登录 | 注册 方可回帖
返回