首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Android安全
发新帖
6
56
[原创]python纯协议实现亿级短视频app的直播间弹幕采集
发表于: 1天前
974
[原创]python纯协议实现亿级短视频app的直播间弹幕采集
程序员小潘
1天前
974
# 背景 版本:20260923,40.6.0 测试需求:纯协议获取直播间弹幕等信息 ## 最终效果 随机抓包找的10个直播间id,随机注册10台设备信息监控上并且持续接收弹幕等信息  # 从直播间 X-Cylons 到6神设备注册的逆向分析 最开始,我想做的事情很简单:输入一个直播间 ID,在电脑上建立连接,把收到的弹幕解析出来。抓到 WebSocket 握手后,首先遇到的是 `X-Cylons`。它的算法还原出来了,但把 URL 里的 `iid` 随手换成另一个数,连接依然不能用。 问题于是从“这个请求头怎么算”变成了“这组身份从哪里来”。顺着 `iid` 往前查,会到设备注册接口;注册请求又带着六个安全头,其中 `X-Medusa` 包含请求摘要、设备信息和 SDK 的运行状态。整个项目就是沿着这条依赖关系逐步展开的。 这篇文章按分析时遇到问题的顺序写:先定位并还原直播握手的 `X-Cylons` 算法,再说明为什么需要注册,接着拆开注册 body 和六个安全头,最后回到 WebSocket 与弹幕解析。本文保留定位思路、数据关系和验证范围;关键计算公式、常量、完整实现及原始测试向量暂不公开。 ## 1 分析对象与最终执行链 最终脚本的执行方向,与分析时回溯依赖的方向相反:  本版首次注册观察到的 6 神分别是: ```text X-Khronos X-Argus X-Gorgon X-Helios X-Ladon X-Medusa ``` 注册样本没有 `X-Perseus`;当前直播握手使用的是 `X-Cylons`。因此不能把不同请求上观察到的 X 头汇总后,机械地给所有接口都加一遍。 目前,这条流程所需的七个 X 字段已经接通:注册时的六个安全头,加上直播握手使用的 `X-Cylons`。其中,Medusa 的 mode 5 已完成内部 16 种摘要核心、摘要尾部状态和 4 种外层封装分支的还原。Python 脚本可以自己生成一套新的设备信息,算出注册所需的六个安全头,再用注册成功后服务器返回的设备 ID 和安装 ID 连接直播间。 这里的“七个”指这条流程用到的字段,不代表所有版本、所有签名模式都已还原。脚本中的设备与进程状态仍是模拟数据,真实 Android 后台采集和更新这些信息的流程尚未完整复现;mode 7、Perseus 的剩余部分也不计入上述完成范围。`X-Cylons` 已验证的取时范围在后文单独说明。 ## 2 从直播握手定位 X-Cylons ### 2.1 先找请求头进入网络栈的位置 抓包定位:  抓包中直播连接的路径是: ```text wss://webcast100-ws-c-hl.amemv.com/webcast/im/push/v3/?... ``` 从 Java 层找同名字符串不一定能直接找到计算代码。这个头是在底层网络回调中加入握手的,因此我先沿着“最终请求头在哪里被添加”往回追。 在这份 `libsscronet.so` 中,建立连接时会通过全局函数指针调用 MetaSec 的回调,传入 URL 和已有请求头。回调返回后,Cronet 再将新头加入握手。 这把“网络层添加请求头的位置”和“安全库计算结果的位置”连了起来。返回缓冲区也有相应的释放约定,主动调用做对照时需要遵守。精确偏移与调用参数细节暂不展开。 这一步得到的是一个原生对照入口:给定 URL,能够取得当前进程计算的结果。它可以帮助定位算法,却还不是独立实现,因为 SDK 状态仍然来自手机进程。 ### 2.2 固定时间后逐个改变输入 接下来需要确定回调究竟用了什么。我让 AI 辅助整理重放与对照实验,逐项检查哪些输入变化会影响计算结果。直接连续请求时,URL 和时间一起变化,很容易把时间变化误认成随机数。为此我固定原生 `CLOCK_REALTIME`,采用 A/B/A 对照:先计算输入 A,再只改一项得到 B,最后还原 A。 已保存的同进程对照结果如下: | 控制变量 | 观察结果 | | --- | --- | | 改 query 中的一个值 | 结果改变 | | 调换 query 参数顺序 | 结果改变 | | 把字符改成语义等价的百分号编码 | 结果改变 | | 只改 Host 或 path | 结果不变 | | 只改已测试的已有 Host、User-Agent 头 | 结果不变 | | 同 query、固定时钟,在 A/B/A 中恢复 A | 恢复原来的结果 | | 保留应用数据,重启进程,再使用同 query 与固定时钟 | 在这套安装中仍然一致 | 另外,已测试的 `ws://`、`https://` 输入没有产生 `X-Cylons`。也就是说,scheme 参与选择处理分支;进入这个 WSS 分支以后,已确认参与计算的是原始 query 和时间。 这里的“原始 query”很关键:它是问号之后、fragment 之前的字节串,不先 URL decode,不排序,也不经过字典重建。`a=hello+world` 与 `a=hello%20world` 在业务含义上接近,参与摘要的字节却不同。 ### 2.3 从十八字节结果看内部结构 这个版本的 `X-Cylons` 固定为 24 个标准 Base64 字符,解码后是 18 字节。不过,Base64 解码只去掉了最外面一层编码,得到的字节还经过内部变换,不能直接当成原始数据来看。 结合前面的固定时间和单变量对照,可以把内部数据大致分成三部分: | 组成 | 作用 | | --- | --- | | 固定数据 | 在已测试的同版本样本中保持一致 | | query 相关数据 | 对原始 query 做摘要,再取其中一部分参与计算 | | 时间相关数据 | 由本次取时结果计算得到 | 这些数据组合后,还会经过校验和字节混合,最后才编码成 `X-Cylons`。本文先介绍这层结构,具体字节位置、固定常量、摘要截取规则和混合公式暂不展开,也不放出完整生成代码。 分析时有一个容易误判的现象:只改 query 中的一个字符,最终解码出来的很多字节都会变化。这并不说明每个字节都直接保存了 query 的信息;后续的混合操作也会让变化扩散到其他位置。因此,要结合固定输入、逐项修改和原生执行结果来判断,不能只比较最终结果的外观。 还原后的实现已与保存的 154 组受控原生 URL/时间测试数据核对一致。这些测试把时间固定在整秒,也就是纳秒部分设为零。真实运行时还观察到不足一秒内结果发生变化的情况,这部分取时细节尚未完全还原;当前脚本采用的是已验证的整秒计算方案。 ## 3 算出 X-Cylons 后为什么还要注册 拿到本地算法后,一个自然的想法是:既然签名可以重新生成,直接生成任意 `device_id`、`iid`,再重签一次是否就够了?保存的实验表明,至少对当时的握手样本,这样做不成立。 这个实验必须在每次改 URL 后重新计算 `X-Cylons`。如果只改 `iid`,却沿用原来的签名,那么失败同时混入了“身份变化”和“摘要不匹配”两个因素,不能据此判断 `iid` 的用途。 | 每组都重新签名后的变化 | HTTP 状态 | Handshake-Status | | --- | ---: | ---: | | 原始完整 query | 101 | 0 | | 改成另一套已注册的 DID/IID | 101 | 0 | | 把 iid 改为未注册数字,或者删除 iid | 200 | 415 | | 删除 device_id | 200 | 417 | | 仅保留 room_id、rid、device_id、iid | 200 | 415 | 这里的 `415`、`417` 是响应头里的业务握手状态,并不是这几次响应的 HTTP 状态码。 这组结果支持的结论是:`iid` 不必等于计算签名的那台手机当时的 iid,但需要服务器认可的注册身份;完整 query 还有其他约束。实验没有暴露服务端判定代码,因此不能把某一个失败码解释成某个字段的唯一错误原因,也不能从中推出所有直播参数的最小必填集合。 于是问题转向注册接口: ```text POST https://klink.amemv.com/service/2/device_register/ ``` 注册响应中的 `device_id` 进入直播 URL 的同名字段,`install_id` 进入直播 URL 的 `iid`。这就是直播连接对注册流程的直接依赖。 ## 4 把注册请求分成三层 ### 4.1 Java 层先准备设备注册明文 JADX 中可追到这条调用链: ```text DeviceRegisterManager.LJI() → 安排注册任务 → C0AHP.LJIJI() 构造 JSON → C0AHP.LJIJ() 编码并尝试注册 URL → NetUtil.LJII() 压缩与加密 → NetworkClient / AppLogNetworkClient → 网络层补公共参数及安全头 ``` `LJI()` 是触发入口,并不直接同步返回最终 HTTP 请求。清除数据、启动应用、同意隐私协议能够稳定触发首次注册;已有注册状态时主动调用同一个入口,也可能进入另一种签名模式。后面会看到,决定 mode 5/7 的是 SDK 状态位,不能只看 URL。 注册明文的结构是: ```json { "magic_tag": "ss_app_log", "header": { "aid": 1128, "device_platform": "android", "device_model": "示例机型", "device_brand": "示例品牌" }, "_gen_time": 1790701218000 } ``` 上面只展示结构,省略了其他字段,不能作为完整注册请求直接发送。当前代码使用 UTF-8、紧凑 JSON,并固定构造顺序。 这些字段大致来自五类输入: | 类别 | 代表字段与来源 | | --- | --- | | 应用配置 | aid、package、app_version、version_code、manifest_version_code、SDK 版本与签名证书信息 | | 机型与系统 | device_model、device_brand、device_manufacturer、os_api、os_version、cpu_abi、分辨率、DPI、ROM | | 本次安装 | openudid、clientudid、cdid、apk_first_install_time、first_launch_timestamp | | 网络与运行状态 | access、mcc_mnc、语言时区、guest_mode、custom、可选的 IPv6 等采集结果 | | 本次请求 | req_id、_gen_time、_rticket,以及独立采样的请求活动时间 | 当前代码默认构造 `header` 49 项、注册 query 39 项;最初抓包截图里的真机样本是 `header` 51 项、query 40 项,包含额外采集结果和来源尚未定位的 `md=0`。两组数量对应不同的实际报文,不能把截图字段数当成代码每次输出的固定值。 同一条数据在不同位置还可能使用不同表示。例如 body 中的分辨率为高乘宽形式 `H x W`,query 中转换为 `W*H`。注册 URL 的空格使用 `+` 编码,当前直播 URL 则使用 `%20`。签名前必须先得到最终要发送的字节。 篇幅原因,这里不展示所有设备指纹信息。 ### 4.2 ttEncrypt 保护 HTTP body 抓包中的注册 body 是二进制。解开后可以恢复前面的 JSON,这一层与 `X-Medusa` 的 protobuf 是两套数据流。 顺着明文进入网络层的过程,可以确认它先经过压缩,再结合随机材料进行密钥派生和加密,最后加上协议需要的封装信息。这里先说明处理关系,不展开派生公式、固定前缀、密钥截取位置和最终字节布局。 对照时还有一个容易忽略的变量:gzip 本身也有头部信息。如果压缩库自动加入当前时间,那么即使 JSON 不变,中间字节也可能不同。因此需要分开检查序列化、压缩、加密和封装各阶段,不能把所有差异都归到加密算法上。 验证也不能停留在“解出了可读文本”。项目中还对照了各阶段的输入输出,并检查解密、解压后的内容是否与原始 JSON 一致。 ### 4.3 X-SS-STUB 绑定最终密文 body `X-SS-STUB` 与最终 HTTP body 的摘要有关。这里参与计算的是已经完成加密封装、实际要发出的字节,而不是最开始的 JSON 明文。 后续安全头也会引用 body 的摘要。如果几个位置使用的不是同一份 body,即使各自算法算对了,同一条请求内部仍然对不上。 因此实际构造顺序是:先确定 JSON、完成压缩和加密,拿到最终 body,再生成与之绑定的安全头。具体摘要表示方式在本文中省略。 ## 5 六个安全头中的五个短头 先把各个头依赖哪些信息分清楚,比一开始就猜算法名更有帮助: | 请求头 | 本版本中已确认的数据关系 | | --- | --- | | X-Khronos | 与 SDK 的取时和校时状态有关 | | X-Argus | 与同次签名使用的时间有关,当前版本采用短格式 | | X-Gorgon | 结合请求摘要、时间及部分运行状态进行变换 | | X-Helios | 结合应用身份、时间和随机材料进行分组处理 | | X-Ladon | 与请求内容、启动状态和请求上下文有关 | | X-Medusa | 将请求摘要、设备与 SDK 状态组织成 protobuf,再做多层封装 | 这些头虽然常被统称为“签名”,内部操作却不同。编码、校验、摘要和加密需要分别辨认,同名头在不同版本的格式也不能直接互套。下面只展开分析中容易判断错的地方,不给出完整生成步骤。 ### 5.1 Khronos 与 Argus:先确认时间来源 这两个头需要放在同一次签名调用中对照。原生取时会受到 SDK 保存的校时状态影响,还存在回退路径,因此不能把抓包里的时间值简单理解为系统时钟的直接输出。 当前版本的 Argus 是短格式。看到这个字段名就套用其他版本的大型加密 protobuf 实现,会从一开始走错方向。这里保留它与时间的关联,具体编码方式不展开。 URL 的 `ts`、设备采样时间和签名时间来自不同读取位置,不要求数值机械相等。当前代码尚未复现完整的服务端校时更新过程。 ### 5.2 Gorgon:相似的状态表不代表标准算法 这一段有初始化状态表、更新索引、取出字节流等操作,外观上很像常见的流密码。但逐条对照写表指令后,可以看到关键更新行为与标准实现不同,直接换成现成库会得到另一套结果。 后续字节变换还有顺序依赖:某些位置读取的是前面已经写回的值。因此,将循环改成同时处理全部位置,也可能改变结果。 这里的收获是先确认每次读写的真实语义,再给算法命名。输入排列、状态表更新细节、位变换顺序和输出前缀暂不公开。部分输入还与运行时对象有关,不能长期沿用一条抓包里的固定值。 ### 5.3 Helios:数据的表示方式也是输入的一部分 Helios 的输入涉及应用身份、时间和随机材料。继续往下追,会遇到摘要、密钥准备和分组运算。 其中一个容易忽略的问题,是二进制摘要与摘要的文本表示并不是同一份字节。只确认“这里用到了某种摘要算法”还不够,还要核对交给下一步的是哪一种表示。 分组结构也需要逐层确认,包括密钥扩展、轮运算和分组之间是否存在依赖。本文保留这些分析要点,省略明文拼接方式、派生规则、轮数、旋转参数和最终封装公式。 ### 5.4 Ladon:同一请求内的状态必须一致 Ladon 不只作为独立请求头出现,还会影响 Medusa 内的 `fl`、`lp`。如果分别生成这些位置,就可能让一条请求携带互相矛盾的状态。 继续追上游,可以看到请求内容、SDK 启动状态、时间和请求上下文都参与了计算。部分状态保存在 TLS 中;这里指的是 **thread-local storage,线程局部存储**,与 WebSocket 外层的 TLS 加密传输不是一回事。 代码为每次请求建立状态快照,让 Ladon 与 Medusa 从同一份快照取值,避免并发时互相串用。本文不展开校验多项式、种子生成、地址混合以及各字段之间的换算公式。 还原这一部分时,整数位宽也是验证重点。在错误的位置提前截断,会让表面相同的公式产生不同结果。除此之外,两处看起来都叫“启动时间”的数据,也可能来自两次独立读取。 ## 6 Medusa 从哪里来 ### 6.1 先分清 mode 5 与 mode 7 最初容易混淆的地方,是认为“请求路径是 device_register,所以一定使用 mode 5”。实际观察中,同一注册入口主动触发以后,也出现过 mode 7。 顺着签名对象的构造往前追,可以看到模式由 SDK 的配置状态决定,上游还涉及 Java 配置缓存和持久化配置。主动调用注册方法只保证请求发生,不保证签名对象重新以某个模式创建。 对对象工厂做了 24 组原生对照后,才把两种模式与配置变化对应起来。具体状态位、构造入口和抓包识别公式在这里省略。分析时应先确认当前样本实际走了哪种模式,再讨论它的算法。 ### 6.2 应用密钥来自 license 追 Medusa 输入时,曾遇到一组解密和 protobuf 处理代码。它看起来也像在还原“Medusa 明文”,实际处理的却是应用 license。 这条链得到的是应用身份、应用配置和签名所需材料。它发生在取得新设备 ID 之前,因此不能把 Medusa 的应用密钥误认为由注册响应中的 DID/IID 推导而来。 本文只保留这一来源关系,省略 license 原文、内部字段布局、多层解包顺序和密钥派生规则。项目中还原的是已定位的解包流程,不等于原生 license 的全部有效性检查;部分字段的业务含义仍未确认。 ### 6.3 Medusa 的明文是 protobuf 字节 Medusa 解开后是 protobuf。为了阅读方便,可以把它展开成 JSON,但 JSON 只是展示格式,不是原生算法直接接收的明文字符串。 分析中需要同时区分三份数据:注册接口的 JSON、Medusa 内部的设备与环境消息,以及计算请求摘要时使用的输入。它们互相有关联,却不是同一份内容。 恢复出可解析的 protobuf 只是第一步。还需要使用同一份输入和状态重新封装,与原始请求头逐字节核对,才能证明解包过程没有漏掉某层处理。完整样本和中间字节串不在本文展开。 ### 6.4 请求摘要的输入怎样确认 Medusa 中有一个字段保存请求摘要。最初仅从长度猜测某个常见哈希算法,但与原生输出比对后无法解释样本,说明长度只能提供线索,不能作为算法结论。 最后通过返回值与目标字段的完整匹配,定位到真正的计算入口。再把入口数据与同一次 Charles 请求对齐,确认输入同时涉及原始 query、最终密文 body 和本次签名时间。 这里省略具体摘要算法组合、字节长度、拼接顺序和调用参数布局。需要保留的方法是:必须对齐同一次请求,不能把不同采样时刻的 URL、body 和时间凑在一起。 ### 6.5 找到分支还不够,还要追选择规则 最初通过固定输入、枚举分支,可以找到与抓包一致的结果。但这只回答了“这一支能否算对”,还没有回答“调用方为什么选它”。 继续追上游,才能确认选择值由输入经过运算得到。摘要核心的选择与外层封装的选择是两件事,不能拿一个阶段的条件去代替另一个阶段。 目前 mode 5 的选择规则已经纳入独立实现。本文不列出种子、移位方式、取值规则和可复算的输入输出样例。 ### 6.6 十六个摘要核心怎样从 trace 变成独立代码 不同核心存在各自的常量、表和运算组合,不能用某个标准摘要库统一替换。分析经历了三个层次: 1. 主动调用手机原生函数,保存不同输入、时间和分支的对照结果。 2. 在模拟环境中执行原 ARM64 代码,建立可以离线重复的计算边界。 3. 根据指令中的数据依赖恢复计算,再整理成独立实现。 第三步最容易误判:一条 trace 可以展开成代码,不代表换输入、换时间后仍然正确。如果把采样现场里的某个中间值误当成常量,其他测试就会失败。因此还要主动改变条件,回到原 ARM64 结果核对。 保存的核心验证包括 48 组手机原生向量和 1024 组原 ARM64 向量,十六个分支都有覆盖。正式生成路径已经不需要调用手机或执行 SO;完整核心、常量表和提取代码暂不随文公开。 ### 6.7 摘要尾部还包含运行状态 只还原摘要核心,仍然不能解释完整字段。尾部还与检测结果、JNI 相关状态及 SDK 保存的状态有关。 改变这些状态,有时不仅改变一个标志,还会影响参与校验的数据范围。因此不能把尾部当成一个固定后缀,也不能认为 URL、body 和时间相同就一定得到相同结果。 这部分来源已分别追到 Java/JNI 调用、加载器环境和 SDK 状态读写。状态缺省值与后续事件写入的值,也需要区分,不能把另一模式才发生的更新当成首次签名必经流程。 完整摘要有 92 组受控原生向量对照。具体检测条件、环境标记、缓存值、校验公式和标志位位置暂不展开。 ## 7 Medusa 怎样把 protobuf 封装成请求头 摘要计算完以后,还要把应用、设备和 SDK 状态组织成 protobuf,再执行外层封装。下面只展示各层的关系: ```text 本次请求信息 → 请求摘要处理 ← SDK 运行状态 ↓ 与应用、设备和环境信息一起组织为 protobuf ↓ 载荷混合与外层保护 ← 应用材料和本次随机材料 ↓ 协议封装与编码 ↓ X-Medusa ``` 这张示意只说明数据关系,省略了各阶段的具体计算。 ### 7.1 不同阶段使用不同材料 封装过程中会使用来自应用配置的材料,以及本次计算产生的随机材料。它们经过处理后,分别供不同阶段使用。 多处随机数来自不同抽取位置,不能因为都叫“随机数”就合并成一次调用。验证时需要分别控制这些输入,才能判断输出差异来自哪里。具体密钥派生公式和材料布局在这里省略。 ### 7.2 长字段混合存在前后依赖 protobuf 并不是直接交给一个标准加密函数。它先经过多步字节变换,其中后面的计算还会读取前面已经更新的结果。 因此,调整遍历方向或者把某些步骤改成并行处理,都可能改变输出。还原时需要保持读写顺序,再通过不同长度和不同内容的输入做对照。 这里不展开每一步的旋转、异或、索引和掩码规则,只保留“存在顺序依赖”这个分析结论。 ### 7.3 外层保护不等于整段标准加密 继续拆解后,可以看到外层并不是把整段数据直接交给标准分组密码。它还包含数据抽取、局部变换和结果回填,不同分支的处理也有差异。 这解释了为什么只对整段密文猜测标准算法和填充方式,很难得到一致结果。需要先确认分组函数实际处理了哪一部分,再向前追输入、向后追输出。 具体抽取位置、位排列、分组参数、分支条件和回填布局暂不公开。 ### 7.4 用重新封装验证完整链路 最后还要添加协议元信息并编码成请求头。长度和结构检查可以帮助排除错误,但不能单独证明算法正确。 项目中保存了覆盖四个外层分支的 20 组原生向量,并对八份实际样本完成解密、重新封装和逐字节比较。本文只保留这些验证结果,不展示完整二进制布局、时间混合常量和样本中间值。 mode 7 在外层结构和分派上也有差异,所以“mode 7 能解开”不能当作“mode 5 已经解开”的证据。 ## 8 Medusa 里面到底传了什么 ### 8.1 先把编码后的值与业务原值分开 protobuf 的底层编码只能告诉我们某处保存的是整数或一段字节,并不能自动确定它在业务上代表什么。还要结合原生类型描述和写入代码,区分有符号整数、浮点数、字符串和子消息。 例如样本中反复出现的较大整数,有些其实是有符号哨兵经过编码后的表示,并不是设备真的采集到了那个数。浮点哨兵则使用另一种表示,不能套用整数的解码方法。 SDK 在状态缺失时返回的默认值,也不能直接解释成计数器的实际次数。本文保留这种判断方法,具体转换代码和样本数值对照不再展开。 ### 8.2 根消息的字段 下表里的数值意义按类型解码后描述。样本缺省的字段也单独列出,避免把“抓包没出现”和“协议没有这个字段”混为一谈。 | 字段 | 来源或含义 | | --- | --- | | 1 | 当前 mode 5 的固定标记,具体字节省略 | | 2 | 签名模式标记 | | 3 | 独立抽取的随机值,与外层随机材料不同 | | 4 | 应用 aid | | 5 | device_id;首次注册样本尚未绑定,所以缺省 | | 6 | license 中的 identity | | 7 | 应用 versionName | | 8 | MetaSec SDK 版本字符串 | | 9 | SDK 版本状态字 | | 10 | 八字节检测位图,与设备子消息字段 39 共用状态 | | 12、17 | 同次签名秒 T;协议为何保留两处尚无额外语义证据 | | 13 | 请求相关摘要与运行状态校验 | | 14 | 原始 query 的摘要片段,截取方式省略 | | 15 | SDK 事件子消息,包括签名入口、上报、配置更新与上次上报随机数 | | 16 | SDI token 文本;空值在本次样本中不编码 | | 20 | 与相关请求头状态有关的文本,受条件控制 | | 21 | 包装器写入的固定值;更具体的业务名称未确认 | | 23 | 运行环境与设备子消息 | | 24 | 环境 JSON 文本,展示工具将其展开成对象 | 根字段 15 的子字段 1 是签名 VM 入口计数;2 是风控上报前递增的状态;3 是配置更新前递增的状态;5 保存上一次风控上报抽取的随机数。字段 4 对应上报失败状态,在最初这份样本中没有编码。后台签名也可能推进入口计数,不能把它等同于用户点击次数。 八字节位图为 0,只能说明读取时没有已提交的命中。提供者会异步采集,某些位只做 OR 累积;不能把某一时刻的零值解释为设备不存在所有相关特征。 ### 8.3 设备子消息的构造初值与采集值 设备子消息位于 `23.12`。构造上下文时先写入哨兵,执行采集后才覆盖。采集通过任务排队进行,存在未开始、开始、完成的状态变化。原截图未保存全部调度状态,因此不能断言具体哪一次任务没有完成。 以下列出已经定位来源的字段。这里描述的是槽位含义及采集规则,不代表原截图中每项已经具有有效采集值: | 完整路径 | 采集结果或生成规则 | | --- | --- | | 23.12.1 | 由当前 URL 和 SDK 策略配置共同决定的状态 | | 23.12.3、23.12.4 | aid、device_id;后者首注册缺省 | | 23.12.7 | 电量相关采集结果 | | 23.12.8 | 与本次和历史电量采集结果有关的状态 | | 23.12.9 | BATTERY_CHANGED 的 health 枚举 | | 23.12.10 | 充电状态相关采集结果,经过内部转换 | | 23.12.14 | `/sys/devices/system/cpu/` 下匹配 `cpu[0-9]` 的目录数 | | 23.12.16、23.12.17 | `/sdcard` 总容量、空闲容量,单位 GiB;空闲取 `f_bfree` | | 23.12.18、23.12.19 | sysinfo 的总 RAM、空闲 RAM,单位 GiB | | 23.12.20、23.12.21 | 存储容量相关汇总值,具体组合方式省略 | | 23.12.22 | 系统版本;其他样本已对应到值,原始采集 API 与时机未完全确认 | | 23.12.23 | Settings.System 的 SCREEN_BRIGHTNESS 整数 | | 23.12.24 | AudioManager 的 STREAM_SYSTEM 音量 | | 23.12.25 | 持久化键 fltk 的首次记录毫秒,不直接等同安装时间 | | 23.12.27 | 根据系统时间信息估计的开机时间;存在异常回退 | | 23.12.28 | 组装本消息时独立取得的当前毫秒 | | 23.12.29 | USB_STATE 粘性广播的 connected 状态 | | 23.12.30、23.12.31 | 机型、品牌;原始采集 API 与时机未完全确认 | | 23.12.38 | 蓝牙、定位等系统功能的特性位图,具体位映射省略 | | 23.12.39 | 共用八字节检测状态;原截图中未编码 | | 23.12.40 | 设备上下文保存的 SDK 启动毫秒 | 字段 7 和 10 还存在本 SO 的特殊返回分支,不能无条件把 Java API 的正常值代入。采集差值、首次记录时间、失败返回值也各有自己的规则,单纯按字段名随机造数会丢掉这些条件。 其余值为 `!notset!` 的字符串中,`23.12.5/6/11/12/13/15/32/33/34/35/36/37` 的具体设备属性仍未确认;环境层 `23.14` 也未确认。加上上表只部分确认的 OS/机型/品牌三项,原样本共有 16 个此前约定跳过的 `!notset!` 叶字段。 按原先的计数口径,其余 62 个叶字段均已给出来源或生成规则。但这不等于 78 个字段全部得到完整业务命名,更不等于所有设备采集时序已经模拟完成。完整原值与逐项证据保留在本地研究记录中,不随本文展开。 ### 8.4 环境子消息包含进程信息 `23` 里面不只有设备型号,还包含 PID、PPID、SDK 事件,以及装载地址和 JNI 布局参与计算的整数: | 字段 | 来源 | | --- | --- | | 23.1 | SDK 已运行时间相关值,原生独立取时 | | 23.6 | 环境消息使用的 SDK 内部版本字符串 | | 23.7、23.15 | getpid、getppid | | 23.12 | 上述设备子消息 | | 23.13 | 风控上报状态子消息 | | 23.14 | 尚未确认业务含义的字符串哨兵 | | 23.17 | 最近一次已提交的抽样耗时,经过内部转换 | | 23.18 | 由模块入口、线程状态和签名时间组合得到 | | 23.19 | 由 JNI 方法布局与签名时间组合得到 | | 23.20 | 由模块入口与签名时间组合得到 | 相关地址和线程状态在初始化及后续调用中取得,具体组合公式省略。这些地址相关值属于进程环境,不是手机硬件序列号,也不是任意一个“设备随机数”。 `23.13` 内部有六项:完成秒数、阶段、文本、HTTP 状态、传输状态、错误码。部分阶段进入后不再更新,但传输层进入成功分支,不能进一步推成响应业务一定成功。这个状态机有 133 组原 setter 对照。 ### 8.5 字段 24 的 JSON 与其他头的关联 字段 24 实际存的是 JSON 字符串。它内部的数字按 JSON 数字解释,不再做 protobuf ZigZag。 | JSON 键 | 来源与需要保留的约束 | | --- | --- | | cmr | Camera 方法的入口与标志检测位图 | | cmr2 | 同组 Camera 方法的另一组访问标志检测 | | un_h | 包名查询相关的运行时方法标识,并非包名字符串的摘要 | | vpn | 活动网络的 VPN transport 检测结果;已命中后该路径不清零 | | sts | 多个 SDK 事件的累积标记,并非次数 | | kd | 状态树中的 CLIENT-KEY 摘要,启动时还可能从缓存恢复 | | fkd | 由进程标识与缓存状态共同派生,具体公式省略 | | pd | 由进程内缓存标识派生,具体公式省略 | | lp | flags、Ladon、种子毫秒和 SDI 缓冲区地址的组合文本 | | fl | 十个 uint32 文本槽,包括种子链中间值和本次 Ladon | | dyn | SDK 字符串树保留键,缺键为空串;存在时按字节复制 | | do | 普通/备用 DID 设置路径的标记,不能单独证明 DID 有效 | | tk | SDI 文本的本地格式判断,不代表服务器认证成功 | `sts` 表示多个事件的组合,不能直接当成“成功上报次数”。`lp`、`fl` 中则有多项共享状态,包含启动信息、请求状态和 Ladon 的关联值;这里不展示位置排列和换算公式。 部分槽位在已审计的构造、写入和初始化路径中保持默认值。这一结论来自代码与对照验证,不是仅凭几次抓包都一样;也不代表其他版本永远无法改变它们。 `dyn` 是另一个例子:本版已审计路径没有产生这个键,缺键读取为空;显式注入值时原生会复制它。因此准确的描述是“本版保留键的缺省行为”,不是“它永远等于空串”。 ### 8.6 kd 的写入者藏在第二套 VM `kd` 是收尾时需要继续追的字段。只看到 mode 5 读取状态树,不足以解释状态从哪里更新。后来顺着另一模式的对象虚表进入第二套 VM,才找到处理客户端状态并写入缓存的路径。 这条路径会对相关输入做多步摘要和转换,再保存到共享状态中。输入缺失、存在但为空、带特殊字节等情况,需要分别对照;不能为了得到某个值,就假定首次注册之前一定发生过后续模式的更新。 持久化也不是简单保存一个明文整数。它包含名称派生、内容编码和异常输入处理,另有不同的状态提供者。这里省略派生公式、存储密钥、文件命名规则和完整编解码过程。 这一部分有 44 组原 VM 对照,存储编解码另有 96 组对照及 20 组十进制边界。其他安全头回调在这些测试中作为边界替换,因此这些数字不能宣称为“整个七头原生仿真通过”。 ### 8.7 Perseus 在这条流程中的位置 分析共用环境结构时也涉及 `X-Perseus`。它对环境消息另做封装,与 Medusa 存在共享材料和状态关联,但又有自己的随机材料、分支和编码处理。 具体材料派生、位保护、分组参数和编码映射在这里省略。部分环境状态的上游及完整采集生命周期仍有缺口,不能把外层可解包等同于整个来源链已经完成。 当前 mode 5 注册样本和本文 WSS 入口均不要求生成 Perseus。另外,mode 7 Medusa 的摘要目前只完成部分分支,不能把 mode 5 十六分支完成的结论挪到 mode 7。 ## 9 从原生对照入口改成每次新安装的代码入口 早期手机上的签名服务能够主动生成这些头,但调用仍共享手机进程中的 PID、地址、缓存、事件状态。即使 URL 改成另一品牌,只要 Medusa 环境还是旧手机那一份,就不能称为独立新设备。 因此正式入口把“安装”与“SDK 进程”变成显式对象: ```text new_installation() → 本次机型画像、openudid、clientudid、cdid → 本次独立 DeviceSigningContext → 最终注册 URL/body → 请求快照 → 六头 → 发送前绑定检查 ``` 目前有 Xiaomi、HUAWEI、OPPO、vivo、samsung 五组机型配置。它们是测试画像;同型号的品牌、系统/API、分辨率、DPI、ROM、ABI 应按组合保持一致。可以变化的是本次安装标识、首次记录时间、进程 UUID、模拟进程地址和请求随机数等,不是把所有字段分别随意随机。 | 生命周期 | 保持或更新的规则 | | --- | --- | | 应用版本 | aid、identity、SDK 版本、license 密钥应与同一版本配置一致 | | 本次安装 | openudid、clientudid、cdid 建立后,注册和直播共同使用 | | 本次 SDK 进程 | 独立 UUID、PID/PPID、地址基址、种子和事件表,不能让 50 个 worker 共用一个对象 | | 本次请求 | 先确定 URL/body,再取本次时间与随机材料,生成所有关联字段 | | 注册成功后 | 用服务器返回的 DID/IID 绑定当前上下文,继续构造直播 URL | 当前 openudid 使用源码已知的本地随机回退,不能称为采集到了真实 Android ID。模拟地址只是参与整数运算,不会访问手机内存;模拟的 PID、ART 布局等也明确保留其来源标记。 发送之前还要反过来检查本次实际生成的 Medusa:解开头部,重新计算 query/body 摘要,核对机型、品牌、系统、时间及 Ladon 的三处表示。发现不一致时直接阻止发送,避免用服务器返回值去掩盖本地已经可以发现的错误。 这里有一个实际的工程遗漏:算法补齐后,最早只有传 `--experimental-mode5` 才走完整 Medusa 路径,无参数入口仍然报“缺少 X-Medusa”。后续修复把 `sign_mode5()` 和摘要绑定检查接到默认路径;旧参数只保留兼容作用。算法完成与用户真正点击启动的入口接通,是两个需要分别检查的环节。 当前代码仍区分: ```text mode5_ready = True native_initialization_verified = False ``` 前者表示已经生成完整 mode 5 签名,后者记录完整 Android 初始化和后台采集时序尚未验收。生成器可以工作,不需要把后一个标记改成未经验证的成功。 ## 10 注册完成后怎样解析直播消息 ### 10.1 注册成功先验证响应 HTTP 200 并不够。当前入口要求 `new_user == 1`,并检查 `device_id`、`install_id`、`server_time` 为正的十进制数。得到 DID/IID 为零的响应时,该 worker 停止,不会继续拿零身份连接直播。 `device_id_str`、`install_id_str` 是相应 ID 的字符串表示。`device_token`、`klink_egdi` 等是服务器返回的不透明状态,本流程没有完整还原它们的内容,也没有把它们当作必须由本地签发的材料。 ### 10.2 直播 query 要保留顺序和重复键 当前直播 query 共 81 项、77 个不同键。其中 `aid`、`device_id`、`iid`、`version_code` 各出现两次。构造时按 `LIVE_QUERY_ORDER` 输出,不能先变成字典后把重复键去掉。 房间号进入 `room_id`、`rid`;DID/IID 来自刚才的注册;机型、openudid、cdid 和首启时间来自同一安装。当前入口显式请求: ```text compress=gzip resp_content_type=protobuf ``` 等整个 URL 构造完成后,再计算 X-Cylons。签完名又重新 urlencode、调整参数顺序或补参数,都可能改变参与摘要的字节。 ### 10.3 握手与帧缓存 TLS 连接使用主机名验证及 SNI。WebSocket 握手发送 Host、Upgrade、Connection、Sec-WebSocket-Key、Sec-WebSocket-Version 和 X-Cylons。注册阶段的六个安全头不会自动复制到这一步。 成功升级需要 HTTP 101,并按标准校验服务器返回的握手结果;当前入口还检查业务握手状态。标准协议可参考 <a href="elink@1d6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2J5k6X3y4Q4x3X3c8W2k6r3W2@1L8%4u0Q4x3X3g2G2M7X3N6Q4x3V1k6J5k6X3y4Q4x3V1k6J5k6X3x3$3y4o6f1#2i4K6u0W2K9s2c8E0L8l9`.`.">RFC 6455</a>,这里不重复展开计算公式。 读到 HTTP 头部结束时,一次 socket read 可能已经带回首个 WebSocket 帧。必须保留 `\r\n\r\n` 后的剩余字节继续解析,否则会静默丢掉第一帧。 帧层还要处理 7/16/64 位长度、mask、二进制分片与 continuation。收到 ping 返回 pong,客户端控制帧按协议带掩码;代码每 15 秒发送一次空 ping。WebSocket ping/pong 与业务协议的 ACK 是不同层次。 ### 10.4 压缩与 protobuf 的层次 收到二进制数据后,当前入口按以下顺序解包: ```text WebSocket 二进制帧重组 → 从外层 protobuf 取出压缩 payload → gzip 解压 → 读取响应中的消息列表 → 按每条消息的类型和内容继续解析 ``` 再按 method 解释 body: | 消息 | 当前已消费字段 | | --- | --- | | WebcastChatMessage | 提取用户昵称与评论正文,具体字段编号省略 | | WebcastMemberMessage | 结合用户信息与行为状态识别进场,具体判定规则省略 | | 其他 method | 统计类型与数量,尚未逐项解释全部业务字段 | 其中 `ChatLike` 是另一种消息类型,不能因为名称里带 Chat 就计入弹幕。只看到二进制帧也不能证明已经解析出评论,还要确认 method 和评论正文。 历史脚本曾使用抓包 query 与 zstd 字典收到实际弹幕;当前新设备入口选择 gzip,不依赖那份字典。两条路径的能力与测试证据要分别记录。当前解析器遇到非 gzip 的 payload 不输出业务消息,尚未实现完整 schema、业务 ACK、断线重连与历史补拉。 ## 11 闲聊与总结 这次最费时间的地方,是把几个看起来独立的请求串起来。最初只是想拿到直播间评论,追着 X-Cylons 往下看,才发现签名算对了还不够,DID/IID 也得来自有效注册。继续分析注册接口,又遇到 Medusa 里的设备信息、进程状态和其他请求头之间的关联。很多值单独看都能算出来,放到同一条请求里却未必能对上。 Medusa 的难点也不只是算法本身。找到计算入口、匹配上一份样本,只是开始;后面还要追分支怎么选、状态从哪里来、哪些值会随请求变化。中间 trace 出过问题,也走过把现场值误当成固定值的弯路,最后还是靠不同输入、不同时间和原生结果反复对照,才把这些地方逐步确认下来。 对我来说,这个项目最有价值的部分,是把“抓到一条能用的请求”推进到了“知道这条请求为什么能用”。从设备注册、身份获取,到直播握手和消息解析,各层的输入、输出和依赖关系都有了依据。以后遇到版本变化或者请求失败,也能沿着这条链定位,而不是重新换一套抓包参数碰运气。 注:文中数据均来自本次分析和测试记录,仅对应所分析的版本。protobuf 编码规则可参考官方文档 (<mark class="encrypted">dc2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3M7X3!0@1L8$3u0#2k6W2)9J5k6h3c8W2N6W2)9J5c8Y4m8J5L8$3N6J5j5h3#2E0K9h3&6Y4i4K6u0V1k6%4g2A6k6r3g2K6i4K6u0r3k6h3&6U0L8$3c8A6L8X3N6Q4x3V1k6Q4x3U0W2Q4c8e0y4Q4z5o6m8Q4z5o6t1`.</mark>
回复或点赞可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
6
点赞
・
56
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
红皮西瓜
这个讨论对我很有帮助,谢谢!
1小时前
快乐的小跳蛙
感谢你的积极参与,期待更多精彩内容!
1小时前
mb_njkgqdad
感谢你分享这么好的资源!
1小时前
wx_funcrever
这个讨论对我很有帮助,谢谢!
1小时前
王叔叔
感谢你的贡献,论坛因你而更加精彩!
2小时前
x1a0f3n9
非常支持你的观点!
3小时前
zhczf
这个讨论对我很有帮助,谢谢!
5小时前
ooww
你的帖子非常有用,感谢分享!
10小时前
bluegatar
为你点赞!
14小时前
mb_hzfcelhs
感谢你的贡献,论坛因你而更加精彩!
18小时前
clz3216
感谢你分享这么好的资源!
18小时前
mb_wspiyiep
为你点赞!
19小时前
chickenfit
感谢你分享这么好的资源!
19小时前
mb_axnyspcg
感谢你的贡献,论坛因你而更加精彩!
19小时前
jjjo
谢谢你的细致分析,受益匪浅!
19小时前
mb_wdhsjycl
非常支持你的观点!
20小时前
REPE
非常支持你的观点!
20小时前
对你何止爱
+1
感谢你的贡献,论坛因你而更加精彩!
20小时前
blue_sky
非常支持你的观点!
20小时前
乐子人
为你点赞!
20小时前
呆呆呆呆
感谢你分享这么好的资源!
21小时前
git_94536luohuaweishui
你的帖子非常有用,感谢分享!
22小时前
Yves Luo
+1
非常支持你的观点!
22小时前
Aar0n
为你点赞!
22小时前
千屈
你的分享对大家帮助很大,非常感谢!
23小时前
mb_cfjwplfo
非常支持你的观点!
23小时前
烬奇小云
这个讨论对我很有帮助,谢谢!
23小时前
Wika
为你点赞!
1天前
wx_大表哥_160292
这个讨论对我很有帮助,谢谢!
1天前
小傲骨
感谢你的积极参与,期待更多精彩内容!
1天前
xuanzee
谢谢你的细致分析,受益匪浅!
1天前
qqizai
期待更多优质内容的分享,论坛有你更精彩!
1天前
LLeaves
这个讨论对我很有帮助,谢谢!
1天前
jpacg
你的帖子非常有用,感谢分享!
1天前
Python成长路
为你点赞!
1天前
Yangser
感谢你分享这么好的资源!
1天前
mb_qtvylfog
这个讨论对我很有帮助,谢谢!
1天前
Je2em1ah
为你点赞!
1天前
doduhuang
你的帖子非常有用,感谢分享!
1天前
Ms135
这个讨论对我很有帮助,谢谢!
1天前
77H
这个讨论对我很有帮助,谢谢!
1天前
酋knave
你的帖子非常有用,感谢分享!
1天前
sun-shine
你的帖子非常有用,感谢分享!
1天前
教教我吧~
感谢你的贡献,论坛因你而更加精彩!
1天前
停舟观鱼
期待更多优质内容的分享,论坛有你更精彩!
1天前
mb_kgfqphsx
这个讨论对我很有帮助,谢谢!
1天前
mb_hhiypuwp
感谢你分享这么好的资源!
1天前
zxhk
期待更多优质内容的分享,论坛有你更精彩!
1天前
KanXue_NG
期待更多优质内容的分享,论坛有你更精彩!
1天前
mb_asiwnxyv
感谢你的贡献,论坛因你而更加精彩!
1天前
wx_byte
非常支持你的观点!
1天前
顽劣
非常支持你的观点!
1天前
mb_rjdrqvpa
感谢你的积极参与,期待更多精彩内容!
1天前
mb_bvvcoitr
+1
感谢你的积极参与,期待更多精彩内容!
1天前
wx_Mark_449
为你点赞!
1天前
梧桐生
感谢你分享这么好的资源!
1天前
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
25
)
1
2
▶
mb_ykavguun
雪 币:
1307
活跃值:
(1825)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
166
粉丝
0
关注
私信
mb_ykavguun
2
楼
1
1天前
0
mb_ldbucrik
雪 币:
6
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
707
粉丝
7
关注
私信
mb_ldbucrik
3
楼
感谢分享
1天前
0
mb_sqetvntx
雪 币:
0
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
53
粉丝
0
关注
私信
mb_sqetvntx
4
楼
学习
1天前
0
iBa0
雪 币:
1901
活跃值:
(5918)
能力值:
( LV4,RANK:40 )
在线值:
发帖
6
回帖
490
粉丝
37
关注
私信
iBa0
5
楼
111
1天前
0
错过
雪 币:
86
活跃值:
(1552)
能力值:
( LV2,RANK:10 )
在线值:
发帖
12
回帖
70
粉丝
0
关注
私信
错过
6
楼
感谢分享
1天前
0
黑屏
雪 币:
5501
活跃值:
(5834)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
149
粉丝
2
关注
私信
黑屏
7
楼
66
1天前
0
啦啦啦哈哈
雪 币:
27
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
10
粉丝
0
关注
私信
啦啦啦哈哈
8
楼
6666
1天前
0
Yangser
雪 币:
1954
活跃值:
(4253)
能力值:
( LV4,RANK:50 )
在线值:
发帖
11
回帖
130
粉丝
220
关注
私信
Yangser
9
楼
666
1天前
0
mb_xjdhrmck
雪 币:
78
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
154
粉丝
0
关注
私信
mb_xjdhrmck
10
楼
6566
1天前
0
gamehack
雪 币:
1787
活跃值:
(9369)
能力值:
( LV5,RANK:65 )
在线值:
发帖
5
回帖
464
粉丝
23
关注
私信
gamehack
11
楼
感谢分享!
1天前
0
大魔头
雪 币:
178
活跃值:
(3911)
能力值:
( LV6,RANK:80 )
在线值:
发帖
18
回帖
167
粉丝
80
关注
私信
大魔头
12
楼
666
1天前
0
sorely
雪 币:
939
能力值:
( LV1,RANK:0 )
在线值:
发帖
1
回帖
31
粉丝
0
关注
私信
sorely
13
楼
66
1天前
0
mb_jnmxfjku
雪 币:
109
活跃值:
(810)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
148
粉丝
0
关注
私信
mb_jnmxfjku
14
楼
66
1天前
0
mb_jggmsmza
雪 币:
44
活跃值:
(25)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
3
粉丝
0
关注
私信
mb_jggmsmza
15
楼
感谢分享
22小时前
0
mb_ortywcvp
雪 币:
200
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
6
粉丝
0
关注
私信
mb_ortywcvp
16
楼
谢谢分享
22小时前
0
呼吸24K纯氧
雪 币:
28
活跃值:
(1736)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
94
粉丝
2
关注
私信
呼吸24K纯氧
17
楼
感谢分享
22小时前
0
mb_xhffcknf
雪 币:
240
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
9
粉丝
0
关注
私信
mb_xhffcknf
18
楼
666
21小时前
0
lrhtony
雪 币:
1418
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
19
粉丝
1
关注
私信
lrhtony
19
楼
666
21小时前
0
Imxz
雪 币:
110
活跃值:
(9556)
能力值:
( LV2,RANK:10 )
在线值:
发帖
6
回帖
773
粉丝
9
关注
私信
Imxz
20
楼
666
21小时前
0
八嘎boy
雪 币:
230
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
9
粉丝
0
关注
私信
八嘎boy
21
楼
没有遇到Google的Android KeyStore(TEE) 硬件证明链问题吗,直接提取真机的序列号用的?
20小时前
0
xpc666
雪 币:
19
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
10
粉丝
0
关注
私信
xpc666
22
楼
666
10小时前
0
信心风暴
雪 币:
223
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
16
粉丝
0
关注
私信
信心风暴
23
楼
多谢大佬分享
4小时前
0
我不是卷王
雪 币:
547
能力值:
( LV1,RANK:0 )
在线值:
发帖
5
回帖
123
粉丝
36
关注
私信
我不是卷王
24
楼
66
3小时前
0
五彩斑斓的黑
雪 币:
153
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
54
粉丝
0
关注
私信
五彩斑斓的黑
25
楼
666
1小时前
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
1
2
▶
返回
程序员小潘
6
发帖
22
回帖
10
RANK
关注
私信
他的文章
[原创]python纯协议实现亿级短视频app的直播间弹幕采集
960
[原创]AI手撕AVMP,实现四神脱机python纯算
8228
[原创]part暴力美学完成某商业app的vmp壳完成重打包案例(2)
4558
[原创][原创]part脱壳重打包案例系列(1)
3701
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部