首页
社区
课程
招聘
[原创]某知名海外社交 Android 签名链AI逆向分析全流程
发表于: 2026-9-12 19:04 1248

[原创]某知名海外社交 Android 签名链AI逆向分析全流程

2026-9-12 19:04
1248

分析 Android 45.5.3 的搜索请求签名链,重点关注:

目标环境是已授权测试设备。本文只记录静态分析、运行状态确认和安全的请求重放方案,不提供可对任意请求生成 防滥用签名的独立签名 Oracle。

APK SHA256:

Fiddler MCP 中发现两条有效请求:

接口:

传输层:

Session 4490 的 gzip 表单体核心字段:

请求体还包含:

这些字段携带搜索历史、页面来源、曝光及消费上下文,可能参与排序、实验分流和签名输入。

主要顶层字段:

两次请求均得到:

实际视频列表位于:

分页通常使用响应 cursor 作为下一次请求的 offset,但修改分页参数后必须由 App 重新生成相应签名。

已定位独立帧签名接口:

关键源码:

最终 native 调用形态:

返回值被视为交替排列的字符串数组:

然后转换成 Map<String, String>。

frameSign() 是明确存在的帧签名 API,但当前没有证据证明普通 /aweme/v1/search/item/ HTTP 请求直接调用它。

对普通搜索请求,更可靠的结论是:签名生成和请求头注入发生在 TTNet/native 请求流水线中。不要把 frameSign() 直接等同于 HTTP 的 x-gorgon/x-argus/x-ladon 生成入口。

MetaSec Java 包:

库名设置:

初始化流程:

配置包含 App ID、channel、device ID、install ID、地区设置和 ms_settings_android。

路径:

SHA256:

信息:

该库符号被大量裁剪,Java native 方法 ms.bd.o.k.a(...) 应通过 JNI_OnLoad/RegisterNatives 动态注册。

请求头字符串明确存在于 libsscronet.so 的 .rodata:

.rodata 虚拟地址起点:

因此对应虚拟地址约为:

这些地址严格绑定 45.5.3 的当前 libsscronet.so,升级版本后不得复用。

Java 层存在:

Request.isPureRequest() 检查该字段。TTNet 还包含以下字符串:

这是签名及 MetaSec 特性位于 TTNet/native 流水线中的直接证据。

libsscronet.so 导出了:

但 ClientOpaqueData 同时包含:

因此它更符合 TLS 客户端私钥/证书签名回调,不应在没有更多交叉引用证据时认定为 x-gorgon/x-argus/x-ladon 的 HTTP 签名通道。

Java 侧相关文件:

当前 App provider 的 getClientOpaqueData() 返回 null,不能把该 API 当作已验证的 MetaSec 注册路径。

不要假设只更新 x-khronos 就能重放修改后的请求。签名字段之间存在关联。

设备重新连接后, 进程中确认加载:

一次观测到的加载基址:

这些是 ASLR 运行时地址,每次启动均可能变化。

该设备与 版本已测试:

任何 Frida Gum 注入都会触发:

因此不要在相同设备和版本上重复 Frida 方案,除非环境已经变化。

技术上可以把 Xposed 模块注入 进程,在真实 App 的以下条件已经满足时调用内部方法:

然后通过仅绑定 RPC 服务进行HTTP 通信。

但是,不应实现接受任意 URL/body 并返回 x-gorgon/x-argus/x-ladon 和设备指纹的通用签名 Oracle。它会把平台防滥用和设备证明能力暴露为可自动化调用的服务。

脚本:

用途:读取 Fiddler Raw 导出的客户端请求 *_c.txt,保留原始 URL、gzip body 和签名头进行即时重放。

仅检查请求:

重放请求:

推荐自动化流程:

完整 APK 一次性 JADX 反编译曾占用约 18 GB 内存。为避免系统内存耗尽,进程已停止并改为只反编译命中的 classes3.dex、classes5.dex、classes30.dex 和 classes31.dex。后续应继续使用定向 DEX 分析,不要无条件重跑整个 478 MB APK。

由于 Frida 不可用,优先考虑:

详细记录见 unidbg-android/README.md。样本 SHA256 与 §7 一致。

已实现目标:在 Unidbg 中完整加载 libmetasec_ov.so,完成完整生命周期初始化,
并成功调用 native 入口生成全套签名参数(每次签名耗时约 50 ms)。

核心结论与修正:

已确认:

未确认:

以上未确认项必须通过字符串交叉引用、JNI 注册恢复或受控运行时观测继续验证,不能凭字段名称推断。

项目 值
包名 com.xxxoapp.musically
版本 45.5.3
versionCode 2024505030
ABI arm64-v8a
Android Android 11 / MIUI
设备 Redmi 21091116C
APK D:\work\android\-45.5.3-original\base.apk
JADX 1.5.6
Java 17
Session 搜索词 HTTP 耗时 结果数
4450 openai 200 1532 ms 10
4490 claude3 200 1440 ms 10
字段 当前判断
x-ss-stub 请求体摘要;修改压缩后 body 会变化
x-khronos 秒级时间信息
x-ss-req-ticket 毫秒级请求时间
x-gorgon URL、body 摘要、时间及会话相关签名
x-argus 设备、App、环境及请求完整性相关 token
x-ladon 与时间/App/设备上下文相关的保护字段
Cookie 安装身份、地区路由和匿名/登录会话状态
8864FDC3F8DB88B685AD7037B8E69095048257A3A074CA81C9EDCC2547EFF15B
POST 555K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2k6$3N6J5x3e0W2Q4x3X3c8F1L8%4u0E0j5h3I4Q4x3X3g2$3i4K6u0W2N6i4y4Q4x3V1k6S2N6$3g2E0k6g2)9J5c8Y4j5I4i4K6u0r3M7$3g2S2M7X3y4Z5i4K6u0r3K9i4c8W2L8g2)9J5c8W2)9K6c8W2)9J5k6g2)9J5k6g2)9J5k6b7`.`.
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
x-bd-content-encoding: gzip
keyword=claude3
offset=0
count=10
source=video_search
search_source=switch_tab
hot_search=0
query_correct_type=1
is_filter_search=0
sort_type=0
publish_time=0
enter_from=homepage_hot
translate_language_code=zh-Hans
sug_generate_type=0
multi_virtual_rs=1
status_code
cursor
has_more
aweme_list
search_item_list
global_doodle_config
feedback_type
extra
log_pb
status_code=0
cursor=10
has_more=1
feedback_type=video
search_channel=musically_video
new_source=switch_tab
tns_search_result=Pass
response["search_item_list"][index]["aweme_info"]
ISecApi.frameSign(String, int)
  -> SecApiImpl.frameSign(String, int)
  -> DmtSec.frameSign(String, int)
  -> C11W3.frameSign(String, int)
  -> ms.bd.o.g2.frameSign(String, int)
  -> ms.bd.o.k.a(...)
D:\work\android\-signature-jadx\sources\com\ss\android\ugc\aweme\secapi\ISecApi.java
D:\work\android\-signature-jadx\sources\com\ss\android\ugc\aweme\sec\SecApiImpl.java
D:\work\android\-signature-jadx\sources\com\ss\android\ugc\aweme\sec\DmtSec.java
D:\work\android\-signature-jadx\sources\X\C11W3.java
D:\work\android\-signature-jadx\sources\ms\bd\o\g2.java
D:\work\android\-signature-jadx\sources\ms\bd\o\k.java
k.a(
    33554442,
    mode,
    nativeHandle,
    canonicalRequest,
    null
);
[headerName0, headerValue0, headerName1, headerValue1, ...]
com.bytedance.mobsec.metasec.ov
ms.bd.o
b0.LIBNAME = "metasec_ov";
DmtSec.init(...)
  -> 构造 MetaSec 配置
  -> h2.LIZJ(context, config)
  -> h2.LIZIZ(context, "metasec_ov")
  -> 加载 libmetasec_ov.so
  -> k.a(67108865, ...)
  -> h2.LIZ(appId)
  -> 创建 g2(nativeHandle)
  -> DmtSec.msManager = C11W3(g2)
D:\work\android\-signature-native\lib\arm64-v8a\libmetasec_ov.so
C06892E3C32473E1EE0F3D3435AC5F33C98ED8A2D45F8CE7BD0FFFF3BB5509BB
SONAME: libmetasec_ov.so
JNI_OnLoad: 0x4dda0
JNI_OnLoad size: 4572 bytes
.rodata + 0x7469   x-argus
.rodata + 0x8890   x-khronos
.rodata + 0xe0d1   x-gorgon
.rodata + 0xe0da   x-ladon
.rodata + 0x1f00d  x-ss-stub
0x76e90
x-argus    0x7e2f9
x-khronos  0x7f720
x-gorgon   0x84f61
x-ladon    0x84f6a
x-ss-stub  0x95e9d
x-metasec-bypass-ttnet-features: 1
x-metasec-bypass-ttnet-features
x-metasec-bypass-mssdk
x-metasec-bypass-api-log
Cronet_ClientOpaqueData_do_sign_set
Cronet_ClientOpaqueData_do_sign_get
Cronet_Engine_AddClientOpaqueData
Cronet_Engine_ClearClientOpaqueData
Cronet_Engine_RemoveClientOpaqueData
D:\work\android\-signature-jadx\sources\org\chromium\CronetClient.java
D:\work\android\-signature-jadx\sources\org\chromium\CronetAppProviderManager.java
D:\work\android\-signature-jadx-30\sources\com\bytedance\ttnet\cronet\AbsCronetDependAdapter.java
libmetasec_ov.so
liboecsec_ov.so
libsscronet.so
libmetasec_ov.so  0x704f340000
liboecsec_ov.so   0x7043918000
libsscronet.so    0x70fab85000
SIGABRT
Unsupported Android linker
libnpth.so
D:\work\android\search_api.py
python .\search_api.py path\to\1_c.txt --inspect
python .\search_api.py path\to\1_c.txt --output response.json
Python/ADB 控制  执行搜索
  -> /TTNet 在真实设备中生成签名
  -> Fiddler 捕获完整请求
  -> Python 读取 Raw 请求
  -> 立即原样重放
D:\work\android\-45.5.3-jadx
D:\work\android\-signature-dex
D:\work\android\-signature-jadx
D:\work\android\-signature-jadx-30
D:\work\android\-signature-native
D:\work\android\-all-dex

详细记录见 unidbg-android/README.md。样本 SHA256 与 §7 一致。

项目 值
包名 com.xxxoapp.musically
版本 45.5.3
versionCode 2024505030
ABI arm64-v8a
Android Android 11 / MIUI
设备 Redmi 21091116C
APK D:\work\android\-45.5.3-original\base.apk
JADX 1.5.6
Java 17
Session 搜索词 HTTP 耗时 结果数
4450 openai 200 1532 ms 10
4490 claude3 200 1440 ms 10
字段 当前判断
x-ss-stub 请求体摘要;修改压缩后 body 会变化
x-khronos 秒级时间信息
x-ss-req-ticket 毫秒级请求时间
x-gorgon URL、body 摘要、时间及会话相关签名
x-argus 设备、App、环境及请求完整性相关 token
x-ladon 与时间/App/设备上下文相关的保护字段
Cookie 安装身份、地区路由和匿名/登录会话状态
  • x-gorgon
  • x-argus
  • x-ladon
  • x-khronos
  • x-ss-stub
  • 客户端 HTTP/2、TLS 1.3
  • 服务端 HTTP/2、TLS 1.3
  • TTNet origin host:api19-normal-useast5.v.us
  • 响应:JSON,经 Brotli 压缩
  • HTTP 200,业务 status_code=0
  • search_id
  • search_session_id
  • end_to_end_search_session_id
  • search_context
  • personal_context_info
  • bcm_chain
  • host list
  • certificate
  • certificate chain
  • private key
  • algorithm preference
  • do_sign callback
  • Frida 17.9.1
  • Frida 17.6.1
  • Spawn
  • Attach
  • 空脚本
  • Context 已建立
  • 正确 ClassLoader 可用
  • libmetasec_ov.so 已加载
  • MetaSec native handle 已初始化
  • device ID、install ID、settings 和会话状态已同步
  • Android tracefs uprobes,仅记录函数命中和非敏感元数据
  • LSPosed/Xposed 本机诊断模块,只确认调用链和参数类型
  • Fiddler 对 App 自身请求做前后差分
  • 使用多个 App 自发请求比较哪些字段随 URL、body、时间和会话变化

[招生]科锐逆向工程师培训(2026年11月13日实地,远程教学同时开班, 第57期)

收藏
点赞 ・2
打赏
分享
最新回复 (4)
雪    币: 4836
活跃值: (8347)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2 楼
感谢分享
2026-9-13 00:34
0
雪    币: 110
活跃值: (9671)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3 楼
tql
2026-9-14 08:55
0
雪    币: 14
活跃值: (925)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4 楼
想找您做技术咨询
2026-9-15 17:08
0
游客
登录 | 注册 方可回帖
返回