前言
偶然发现使用shamiko模块无法绕过某国外加固厂商的环境检测,那么就需要具体分析一下它检测了哪里。
第一部分:定位检测逻辑的通用思路
都深有感触的便是定位检测代码是个体力活;那么便先尝试用一些常用的定位思路来分析一波
1.通过linux“一切皆文件”思路定位
通过对底层系统库函数诸如openat、readlinkat、fstatat等进行hook监控,结果如下:
看到打开的都是sbin目录的特征文件然而此方式shamiko便能绕过,那么便还有其余的检测点。
2.分析现有检测软件猜测可能检测点
分析momo发现它是通过读取pts/2 下内容的方式发现su进程(此时su进程必须在运行状态下才能检测出来),然而此时su必须是运行方式才能检测出来很明显与分析app检测方式不符合
3.通过正向开发思路定位
通过普遍cv的思想在github查找开源的代码块进行定位,下面代码在检测ld_prlaods符号存在于ro.data段,那么便可以使用gdb的awatch来观察ld_prlaods所在内存是否被读写。
最后发现Shimako对这片进行了隐藏。因此便需要针对app的特定特征进行分析了
4.通过activity及弹窗定位
此app有非常明显的窗口点击事件,通过hook点击事件来定位到是哪个activity进行的活动展示
第二部分:检测结果展示整体流程
1.Jni反射调用doDispath完成广播发送
2.NativeBridge接口完成数据交互
通过这些api接口完成java到native 层的数据交互,native层会根据这些信息拼接发送信息
3.Appdome注册registerAppDomeBroadCastReceiver接受广播
4.LoginActivity将接受事件进行活动展示
第三部分:native流程分析
1.Native层如何分析?
通过Jnitrace后发现以下关键字符串,因为已经知道了整体流程最终都是通过dosidpatch来发送消息,那么对最终dodispatch地址打调用栈就可以分析出完整的检测流程
有了这些调用关系,接下来便是一路调试验证的体力活了,
2.最终检测流程如下:
•0x105704magisk detect: 路径比较,动态链接库符号比较
函数体混淆之后非常庞大,因此只关注关键地方进行分析即可
通过对这些函数查看参数,就可以看到一些对magiks的一些传统检测
然而这里还没有跟开头发出的json字符串有关系,所以需要接着向下分析
•0x284638通过927c0和dbba0设置eventid
•0x24c164:927c0分支读取/data/data/com.mobile.co.th/cached_prefs 的值判断是否设置eventid
这里发现cached_prefs没有任何的写入,删除便可绕过
•0x253a38:dbba0分支以malloc为标志计算0x7f2190偏移处的dladdr是否为0
这里的检测思路可以参考:https://github.com/5ec1cff/my-notes/blob/master/new-idea-detect-zygisk.md#%E6%95%B0%E5%AD%97%E4%B8%AD%E6%9A%97%E8%97%8F%E7%8E%84%E6%9C%BA
•0x20c4f4处通过看参数和结果确定是在构造json字符串
•在0x203ac4的函数 通过eventid发送对应envent
•0x17e8e4反射调用doDispath发送广播
第四部分:绕过方案
1.不让app退出
分析退出流程是需要点击才能退出,于是可以通过lunch到想要的activity来进行绕过
2.使检查线程创建失败
既然是创建线程来检测, 那么就可以将检测线程创建失败进行绕过
3.粒度更小的绕过方式
使线程创建失败,粒度太大。也有许多对线程保护(如:将释放dex与检测放到一起,process_vm_write读取线程等)更多时候往往需要粒度更小的绕过方式,这时便可以对关键判断进行patch。
4.通用绕过方案
第五部分:后记
1.遇到的一些困难
分析时,检测到环境异常会退出严重干扰分析通过动态调试发现检测到环境异常后会执行非法指令进行退出。
使用gdb调试,追踪所有线程可以看到每个线程的行为
查看0x7b8段所属内存为匿名可执行段,将其dump下来可以查看syscall实现(以为在找到了7寸),分析这个可以对所有系统调用全部hook住。因为时机原因每次只hook到nano_sleep,然而真正退出并不是在这里,所以在这里倒推分析流程走了不少弯路。
2.还有很多检测(代码注入检测,adb检测,开发者选项开启检测等)暂时还没有分析
原文始发于微信公众号(安全客):某国外加固环境检测与绕过