首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Android安全
发新帖
23
27
[原创]沙箱对抗某商业安全 SDK 检测
发表于: 2026-2-5 19:03
4286
[原创]沙箱对抗某商业安全 SDK 检测
alds
2026-2-5 19:03
4286
分析一个竞品的app的时候发现手机打开就闪退,按照以往的经验直接用apatch开启内核root,然后app基本上就能过,这次是碰到个狠的,发现开启lite模式都不行,还是能检测到并闪退,于是研究了一番它的检测最终成功在手机上实现魔改的框架进行hook,下边是整理的文档 --- ## 1. 概述 某商业安全 SDK 采用 SaaS 加固模式,在运行时执行多层环境检测。检测到异常后通过信号终止进程并上报检测结果。本文还原其客户端检测的完整技术原理。 --- ## 2. 检测架构 该 SDK 的检测分为两个独立层面,采用完全不同的技术路线: ``` ┌────────────────────────────────────────────────────────┐ │ 第一层: Java/JNI 检测 │ │ 通信方式: Binder IPC │ │ 检测目标: 已安装应用、开发者选项、PM 代理 │ │ 特点: 不走文件系统 syscall,seccomp 无法拦截 │ ├────────────────────────────────────────────────────────┤ │ 第二层: Native syscall 检测 │ │ 通信方式: 内联 SVC #0 直接 syscall (非 libc 封装) │ │ 检测目标: root 文件路径、/proc 虚拟文件、fd 映射 │ │ 特点: PLT/GOT hook 无效,仅 seccomp-bpf 可拦截 │ ├────────────────────────────────────────────────────────┤ │ 自杀机制: SIGALRM 定时器 │ │ 上报机制: 后台 Service 上传检测结果 │ └────────────────────────────────────────────────────────┘ ``` 两层检测独立运行、互不依赖,分别由不同的 native SO 执行: | SO 文件 | 大小 | 职责 | |---------|------|------| | `libcovault-appsec.so` | ~1.7M | 第一层:Java/JNI 检测(全量包扫描、PM 代理、开发者选项) | | `libtoolChecker.so` | ~5.4K | 第二层:Native syscall 检测(路径扫描、/proc 读取、fd 遍历) | | `libSecureComponent.so` | ~1.2M | 辅助安全组件 | --- ## 3. 第一层: Java/JNI 检测 (`libcovault-appsec.so`) ### 3.1 整体流程 在 `Application.onCreate` 后立即通过 JNI 调用 Android Java API 执行检测,整个流程约 2 秒。 ``` Application.onCreate ├── SDK 初始化 ├── PackageManager 代理检测 ├── 全量已安装应用扫描 (核心) ├── DevicePolicyManager 检测 ├── USB 调试 / 开发者选项检测 ├── JSON 组装检测结果 └── 启动 Service 上报 ``` ### 3.2 全量包扫描 核心检测手段。通过 native 层 JNI 调用 `PackageManager` API: ``` // 第一轮:获取所有已安装包(含元数据) PackageManager.getInstalledPackages(GET_META_DATA) // 第二轮:获取所有已安装应用信息 PackageManager.getInstalledApplications(GET_META_DATA) ``` 对每个应用提取多维度特征: | 特征 | API | 用途 | |------|-----|------| | 包名 | `ApplicationInfo.packageName` | 黑名单比对 | | APK 路径 | `ApplicationInfo.sourceDir` | 安装位置识别 | | 应用名称 | `getApplicationLabel()` | 辅助识别 | | 权限列表 | `getPackageInfo(GET_PERMISSIONS)` | 敏感权限检测 | | Xposed 元数据 | `Bundle.getString("xposeddescription")` | Xposed 模块检测 | | ContentProvider | `ProviderInfo.authority` | 特定 Provider 检测 | **关键特点**: - **全量扫描**:不是只查特定包名,而是遍历设备上全部已安装应用,扫描结果上传服务端判定 - **通过 JNI 执行**:native 层直接调用 JNI 的 `CallObjectMethodV`,绕过了 Java 层 Method Hook - **Xposed 模块识别**:检查每个应用的 `AndroidManifest.xml` 是否包含 `xposeddescription` 元数据 ### 3.3 PackageManager 代理检测 ```java // 原理 Object sPackageManager = ActivityThread.sPackageManager; Proxy.getInvocationHandler(sPackageManager); // 如果 sPackageManager 是 Proxy 实例 → PM 被 hook // 如果抛出 IllegalArgumentException → 正常 ``` 检测通过 `java.lang.reflect.Proxy` 动态代理 `IPackageManager` 的 hook 方案。 ### 3.4 开发者选项检测 ``` Settings.Secure.getString("adb_enabled") Settings.Global.getString("development_settings_enabled") ``` 值为 "1" 则标记为异常。 ### 3.5 为什么 seccomp 拦截不到 `getInstalledPackages` 走 Binder IPC: ``` app 进程 → ioctl(binder_fd, BINDER_WRITE_READ) → system_server → 包数据库 → Binder → app 进程 ``` 数据流走 ioctl(Binder 底层),不涉及 openat/faccessat 等文件系统 syscall。seccomp-bpf 只能拦截特定 syscall,无法干预 Binder 通信内容。 --- ## 4. 第二层: Native syscall 检测 (`libtoolChecker.so`) ### 4.1 整体流程 由独立的轻量级 SO(仅 5.4K)在后台线程中执行: ``` 后台线程 ├── [1] faccessat 路径扫描 (70+ 条) ├── [2] statx 二次验证 (关键路径) ├── [3] /proc 虚拟文件读取 (maps/status/mounts) └── [4] fd 遍历 (newfstatat + readlinkat) ``` ### 4.2 文件路径扫描 **直接内联 SVC 指令**:检测 SO 不通过 libc 封装函数(如 `access()`、`stat()`、`open()`)发起系统调用,而是在代码中直接使用内联汇编 `SVC #0` 指令。这意味着 PLT hook(如 xhook/bhook 等基于 GOT/PLT 表修改的方案)完全无法拦截这些调用,因为执行路径根本不经过 libc 的函数入口。 ```asm // 伪代码示意 (arm64) MOV X8, #48 // __NR_faccessat MOV X0, #-100 // AT_FDCWD LDR X1, =path_str // 文件路径 MOV X2, #0 // F_OK SVC #0 // 直接陷入内核,不经过 libc ``` 这是一种常见的反 hook 技术:绕过用户态所有函数级 hook(PLT hook、GOT hook、inline hook libc),只有内核级拦截(seccomp-bpf)才能干预。 通过 `faccessat(AT_FDCWD, path, F_OK, 0)` 检测 root 相关文件,覆盖 70+ 条路径: **su 二进制** (~24 条): 遍历所有常见 su 安装位置,包括 `/system/bin/su`、`/system/xbin/su`、`/sbin/su`、`/vendor/bin/su`、`/apex/com.android.runtime/bin/su` 等。 **Magisk** (~29 条): 覆盖 Magisk 的全部可能存在路径,包括 `/sbin/magisk`、`/data/adb/magisk`、`/cache/magisk.log`、`/system/addon.d/99-magisk.sh` 等。 **SuperSU / daemonsu** (~12 条): 包括 `/.subackup`、`/data/.supersu`、`/su/bin/daemonsu` 等。 **Xposed / Substrate** (~6 条): 包括 `/system/lib/libsubstrate.so`、`/magisk/xposed/system/lib/libart.so` 等。 ### 4.3 statx 二次验证 在 faccessat 扫描之后,使用 `statx`(syscall 291)对关键路径进行二次验证。 `statx` 是 Linux 4.11 引入的新 syscall,功能类似 `stat` 但 syscall 编号不同。如果 seccomp 过滤器只覆盖了 `faccessat` (48) 和 `newfstatat` (79),没有覆盖 `statx` (291),检测就能绕过拦截。 同理,`faccessat2`(syscall 439,Linux 5.8 引入)也可能被用于绕过不完整的 syscall 过滤。 **原理**: ``` // 同一个文件,两个不同 syscall 编号 faccessat(AT_FDCWD, "/system/bin/su", F_OK) // syscall 48 statx(AT_FDCWD, "/system/bin/su", 0, 0, buf) // syscall 291 // 如果 seccomp 只拦截了 48,291 就漏过去了 ``` ### 4.4 /proc 虚拟文件检测 | 文件 | 检测内容 | 异常指标 | |------|----------|----------| | `/proc/self/maps` | 内存映射中的 SO 文件名 | 存在 hook 框架相关 SO | | `/proc/self/status` | `Seccomp:` 字段 | 值为 2 说明安装了 seccomp 过滤器 | | `/proc/self/status` | `TracerPid:` 字段 | 非 0 说明正在被调试 | | `/proc/self/mounts` | 挂载点列表 | 存在 Magisk overlay 等异常挂载 | 正常应用的 `Seccomp:` 值为 0,安装了 seccomp 过滤器的进程值为 2。检测 SDK 利用这一点反过来识别使用 seccomp 进行对抗的沙箱。 ### 4.5 fd 遍历 遍历 `/proc/self/fd/` 下的所有文件描述符: ``` 对每个 fd N: newfstatat(AT_FDCWD, "/proc/self/fd/N", &stat, 0) readlinkat(AT_FDCWD, "/proc/self/fd/N", buf, size) → 获取 fd 指向的文件路径 → 检查路径是否包含敏感关键词 ``` 此方法可以发现通过 `dlopen` 加载但已从 maps 中删除的 SO — 即使 `/proc/self/maps` 被过滤,已打开的 fd 仍然指向原始文件。 --- ## 5. 自杀与上报机制 ### 5.1 SIGALRM 自杀 ``` 启动时: alarm(N) 设置定时器 检测完成: ├── 全部通过 → 取消定时器,正常运行 └── 发现异常 → 定时器到期 → SIGALRM → 进程死亡 ``` 选择 SIGALRM 而非 SIGKILL 的原因: - 日志中显示为 "Alarm clock" 而非 "Killed",更隐蔽 - Java 层的 `UncaughtExceptionHandler` 无法捕获信号级进程终止 - 应用看起来像正常超时退出 ### 5.2 多进程架构 ``` 主进程 ← seccomp 已安装 隔离进程 1 ← 后台服务,上报检测结果 隔离进程 2 ← 看门狗,监控主进程 ``` 看门狗进程运行在独立进程空间,不受主进程 seccomp 影响。它可以从外部读取主进程的 `/proc/PID/status` 和 `/proc/PID/maps`,理论上可以检测主进程是否安装了 seccomp 或被注入了 SO。 --- ## 6. Inline Hook 检测 SDK 会校验关键函数(如 `pthread_create`)的入口指令: ```c // 原理 void *func = dlsym(libc, "pthread_create"); uint32_t first_insn = *(uint32_t *)func; // 如果为跳转指令 (B/BL/BR/LDR PC 等) → 被 inline hook 篡改 ``` Dobby 等 inline hook 框架会修改函数前几个字节为跳转指令。此检测会导致使用 inline hook 修改 libc 函数的方案失效。 --- ## 7. 检测使用的 syscall 汇总 | syscall | 编号 (arm64) | 用途 | |---------|-------------|------| | `faccessat` | 48 | 文件存在性检查 (主要) | | `statx` | 291 | 文件状态扩展查询 (二次验证) | | `faccessat2` | 439 | 文件访问检查 v2 | | `openat` | 56 | 打开文件 | | `read` | 63 | 读取 /proc 虚拟文件 | | `newfstatat` | 79 | fd 状态查询 | | `readlinkat` | 78 | 读取 fd 链接目标 | | `fstat` | 80 | fd 状态查询 | | `statfs` | 43 | 文件系统状态 | --- ## 8. 数据收集行为 SDK 在检测过程中收集并上报以下数据: | 数据类型 | 收集方式 | |----------|----------| | 设备全部已安装应用列表(包名、路径、权限、Provider) | PackageManager API | | 每个应用的完整权限列表 | getPackageInfo(GET_PERMISSIONS) | | Xposed 模块标识 | Bundle.getString("xposeddescription") | | USB 调试状态 | Settings.Secure | | 进程内存映射 | /proc/self/maps | | 进程挂载信息 | /proc/self/mounts | | 进程文件描述符列表 | /proc/self/fd 遍历 | 全量应用扫描(遍历设备所有已安装应用并提取详细信息)超出了安全检测的合理最小范围。Android 11 引入<a href="elink@61cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3N6s2u0S2K9h3&6A6L8X3N6Q4x3V1k6H3j5h3y4C8j5h3N6W2i4K6u0V1N6X3W2K6K9h3u0A6L8r3W2@1P5b7`.`.">包可见性限制</a>正是为了限制此类行为。 --- ## 9. 检测局限性 ### 架构层面 - **权限不对等**:检测 SDK 运行在用户态,kernel root 运行在内核态,检测者权限低于被检测者 - **syscall 可被拦截**:所有文件系统检测通过标准 syscall 执行,seccomp-bpf 是内核级拦截机制 - **Binder 返回值可被修改**:PM 查询走 Binder,返回值经过 Java 层可被过滤 - **单次检测**:启动时一次性执行,无持续监控 ### 实现层面 - **内联 SVC 仍可被拦截**:虽然使用 `SVC #0` 绕过了 PLT/GOT hook,但 seccomp-bpf 工作在内核层面,在 syscall 进入内核时拦截,与用户态调用方式无关。无论是 libc 封装还是内联 SVC,最终都要通过 `SVC #0` 陷入内核,seccomp 都能拦截 - **路径硬编码**:su/magisk 路径列表固定在 SO 中 - **未校验拦截行为**:只看结果(文件存在/不存在),不验证 syscall 是否被拦截 - **SIGALRM 依赖检测结果**:全部通过就不触发自杀 - **看门狗进程未充分利用**:理论上可从外部检测主进程异常,实际未观察到充分利用 ### 与更强方案的对比 | 方案 | 检测层面 | 绕过难度 | |------|----------|----------| | 本 SDK (文件扫描) | 用户态 syscall | 低 (seccomp) | | 本 SDK (包扫描) | 用户态 Binder | 低 (Java hook) | | Play Integrity API | 硬件 TEE + 服务端 | 极高 | | 服务端行为分析 | 服务端 | 视实现而定 | | 内核级检测 | 内核 | 极高 | 纯客户端用户态检测方案的根本局限在于:检测代码和被检测环境运行在同一权限层级(甚至更低),无法建立可信的信任根。真正有效的检测需要将信任根转移到硬件(TEE)或服务端。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
#逆向分析
上传的附件:
libSecureComponent.so
(1.15MB,27次下载)
libcovault-appsec.so
(1.69MB,28次下载)
libtoolChecker.so
(5.38kb,27次下载)
收藏
・
23
点赞
・
27
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
sinker_
你的帖子非常有用,感谢分享!
2026-6-12 19:28
mb_xrhmetpo
为你点赞!
2026-5-10 00:01
trackL
你的帖子非常有用,感谢分享!
2026-4-13 17:40
by_Lin
你的帖子非常有用,感谢分享!
2026-3-7 02:01
梧桐生
为你点赞!
2026-3-6 00:11
mb_jkykcuwo
为你点赞!
2026-3-3 14:35
a1rhnoserch
这个讨论对我很有帮助,谢谢!
2026-3-2 15:11
scp000000
期待更多优质内容的分享,论坛有你更精彩!
2026-2-25 15:08
WsttXm
这个讨论对我很有帮助,谢谢!
2026-2-11 14:24
mb_cbgtaveo
感谢你分享这么好的资源!
2026-2-10 09:40
YOLO199393
你的分享对大家帮助很大,非常感谢!
2026-2-9 14:11
灬哈密瓜
你的分享对大家帮助很大,非常感谢!
2026-2-9 09:44
saykao
感谢你的贡献,论坛因你而更加精彩!
2026-2-8 21:07
我的小拇指啊
你的分享对大家帮助很大,非常感谢!
2026-2-8 20:43
lanoche
期待更多优质内容的分享,论坛有你更精彩!
2026-2-8 17:04
东方玻璃
感谢你分享这么好的资源!
2026-2-8 14:13
qqizai
感谢你的积极参与,期待更多精彩内容!
2026-2-8 09:37
Ms135
非常支持你的观点!
2026-2-8 00:11
wx_funcrever
感谢你分享这么好的资源!
2026-2-7 10:33
随风而行aa
+1
感谢你分享这么好的资源!
2026-2-6 22:09
令狐双
非常支持你的观点!
2026-2-6 10:13
fei3ei
非常支持你的观点!
2026-2-6 10:13
ngiokweng
期待更多优质内容的分享,论坛有你更精彩!
2026-2-6 09:26
git_47499test-look
感谢你的贡献,论坛因你而更加精彩!
2026-2-5 23:27
陈可牛
你的帖子非常有用,感谢分享!
2026-2-5 21:30
孤独的街
谢谢你的细致分析,受益匪浅!
2026-2-5 19:34
GhHei
为你点赞!
2026-2-5 19:10
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
11
)
不具名的悲伤
雪 币:
3
活跃值:
(1835)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
126
粉丝
0
关注
私信
不具名的悲伤
2
楼
6
2026-2-6 10:25
0
逆天而行
雪 币:
4725
活跃值:
(7322)
能力值:
( LV6,RANK:90 )
在线值:
发帖
12
回帖
124
粉丝
247
关注
私信
逆天而行
1
3
楼
所以它是如何检测 aptach 的呢?
2026-2-8 13:44
0
Imxz
雪 币:
110
活跃值:
(9571)
能力值:
( LV2,RANK:10 )
在线值:
发帖
6
回帖
775
粉丝
9
关注
私信
Imxz
4
楼
tql
2026-2-8 18:32
0
zylyy
雪 币:
144
活跃值:
(2738)
能力值:
( LV2,RANK:10 )
在线值:
发帖
11
回帖
491
粉丝
3
关注
私信
zylyy
5
楼
666
2026-2-9 01:24
0
lqfcugo
雪 币:
244
活跃值:
(3805)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
53
粉丝
1
关注
私信
lqfcugo
6
楼
逆天而行
所以它是如何检测 aptach 的呢?
可以看看这个 https://bbs.kanxue.com/thread-289811.htm
2026-2-9 14:03
0
alds
雪 币:
136
活跃值:
(1745)
能力值:
( LV3,RANK:20 )
在线值:
发帖
3
回帖
64
粉丝
7
关注
私信
alds
7
楼
逆天而行
所以它是如何检测 aptach 的呢?
上边有写,通过 faccessat(AT_FDCWD, path, F_OK, 0) 检测 root 相关文件,覆盖 70+ 条路径: 这个改的话很简单,把默认su改下位置就行了
2026-2-10 12:17
0
墨穹呢
雪 币:
4770
活跃值:
(8232)
能力值:
( LV3,RANK:20 )
在线值:
发帖
2
回帖
231
粉丝
18
关注
私信
墨穹呢
8
楼
感谢分享
2026-2-10 13:34
0
Hades一KXXY
雪 币:
4837
活跃值:
(2460)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
99
粉丝
2
关注
私信
Hades一KXXY
9
楼
权限天然是不对等的,也没法对等,你的APP总不能要求客户不root不能安装吧,现在主流都是检测root环境
2026-2-11 11:58
0
chenwitch
雪 币:
87
活跃值:
(686)
能力值:
( LV3,RANK:30 )
在线值:
发帖
14
回帖
122
粉丝
2
关注
私信
chenwitch
10
楼
666
2026-2-11 17:19
0
uni7corn
雪 币:
0
活跃值:
(2485)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
182
粉丝
0
关注
私信
uni7corn
11
楼
感谢分享
2026-2-12 11:45
0
mb_deisgjrb
雪 币:
204
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
14
粉丝
0
关注
私信
mb_deisgjrb
12
楼
11
2026-3-9 12:15
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
alds
3
发帖
64
回帖
20
RANK
关注
私信
他的文章
[原创]沙箱对抗某商业安全 SDK 检测
4286
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
谁下载
×
huangyalei
chenwitch
熊趴趴来
Yves Luo
xianhuimin
doduhuang
feige_396505
寻影星尘
墨穹呢
随风而行aa
uni7corn
wx_huhu_859
ONewTach
mb_rjdrqvpa
hanjiefang
逆天而行
iBa0
creek_
孤独的街
mb_ldbucrik
祝今朝
Ms135
npc0vo
mb_xjdhrmck
mb_kujsrqqv
mb_lthgjpwj
谁下载
×
huangyalei
chenwitch
熊趴趴来
Yves Luo
xianhuimin
doduhuang
feige_396505
寻影星尘
墨穹呢
随风而行aa
uni7corn
wx_huhu_859
ONewTach
mb_rjdrqvpa
hanjiefang
逆天而行
iBa0
mb_stzbjchs
孤独的街
mb_ldbucrik
祝今朝
Ms135
npc0vo
mb_xjdhrmck
mb_kujsrqqv
mb_lthgjpwj
谁下载
×
huangyalei
chenwitch
熊趴趴来
Yves Luo
xianhuimin
doduhuang
feige_396505
寻影星尘
墨穹呢
随风而行aa
uni7corn
wx_huhu_859
ONewTach
mb_rjdrqvpa
hanjiefang
逆天而行
iBa0
mb_imnrancw
孤独的街
mb_ldbucrik
祝今朝
Ms135
npc0vo
mb_xjdhrmck
mb_kujsrqqv
mb_lthgjpwj
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部