现在AI是真的发达,一直想试着通过某视频反推获取无水印的视频,一直限于技术无法成功获取,找人利用ai进行逆向出来了,虽然没啥用,放出来吧
1. 算法概述
双重MD5哈希 + 双密钥签名,仅基于URL查询参数计算,与请求路径(path)和Headers无关。
2. 密钥
从APK原生库 libkrandroid.so 中提取:
| 名称 | 值 |
|---|---|
| KEY1 | 3656297b4c572595cc6bbd64a694e122 |
| KEY2 | 32e99970c3e666ee09014927b88b730d |
密钥在 .so 中通过 GOT(全局偏移表)间接引用逐字符拼接构建,用于对抗静态分析。
getKey函数位于偏移0x338c9,构建 KEY1getKey2函数位于偏移0x33ca9,构建 KEY2getSign函数位于偏移0x340cc(3620 字节),实现完整签名逻辑
3. 计算步骤
以请求 /show?materiel_id=1034:4749754517880883&appkey=1543205014 为例:
第一步:参数按 key 名字母升序排序
原始参数: { materiel_id: "1034:4749754517880883", appkey: "1543205014" }
排序后: { appkey: "1543205014", materiel_id: "1034:4749754517880883" }
第二步:紧密拼接 key + value(无任何分隔符)
appkey1543205014materiel_id1034:4749754517880883
注意:不用
=连接键值,不用&分隔参数,直接拼接。
第三步:末尾追加 KEY1,计算第一次 MD5
输入: "appkey1543205014materiel_id1034:47497545178808833656297b4c572595cc6bbd64a694e122"
MD5: "5765e38b1aa391098c6538cd0e1a68b6"
第四步:上一步结果末尾追加 KEY2,计算第二次 MD5
输入: "5765e38b1aa391098c6538cd0e1a68b632e99970c3e666ee09014927b88b730d"
MD5: "262e86d821c74e2c98185c2602c4c709" ← 最终 SIGN
4. 流程图
URL查询参数 (key-value pairs)
│
▼
按 key 名字母排序 (ASCII 字典序)
│
▼
紧密拼接: key1+val1+key2+val2+... (无分隔符)
│
▼
末尾追加 KEY1
│
▼
MD5 哈希 → hexdigest1
│
▼
末尾追加 KEY2
│
▼
MD5 哈希 → 最终 SIGN (32位小写hex)
5. Python 实现
import hashlib
KEY1 = "3656297b4c572595cc6bbd64a694e122"
KEY2 = "32e99970c3e666ee09014927b88b730d"
def compute_sign(params: dict) -> str:
"""计算 CIBN API 的 SIGN 值"""
# 1. 按 key 名字母升序排序
sorted_items = sorted(params.items())
# 2. 紧密拼接 key+value(无分隔符)
concat = "".join(k + v for k, v in sorted_items)
# 3. 追加 KEY1 → 第一次 MD5
hexdigest1 = hashlib.md5((concat + KEY1).encode("utf-8")).hexdigest()
# 4. 追加 KEY2 → 第二次 MD5
sign = hashlib.md5((hexdigest1 + KEY2).encode("utf-8")).hexdigest()
return sign
6. 验证结果
| 参数 | 计算结果 | 抓包值 | 匹配 |
|---|---|---|---|
appkey=1543205014 |
8769e6f2f67776fba4f1ca2d75ef4f85 |
8769e6f2f67776fba4f1ca2d75ef4f85 |
✅ |
appkey=...&materiel_id=1034:4749754517880883 |
262e86d821c74e2c98185c2602c4c709 |
262e86d821c74e2c98185c2602c4c709 |
✅ |
appkey=...&category_id=4514586333151463 |
36157a5ce4e732b0085e7cf3ba32a520 |
36157a5ce4e732b0085e7cf3ba32a520 |
✅ |
appkey=...&category_id=4361745538918837 |
25934ef3a230ea306a1a57a23abdea27 |
25934ef3a230ea306a1a57a23abdea27 |
✅ |
4 组 HAR 抓包样本全部匹配,算法验证通过。
7. API 请求结构
请求格式
GET http://tapi.cp63.ott.cibntv.net{path}?{params}
必要 Headers
| Header | 值 | 说明 |
|---|---|---|
SIGN |
计算值 | 签名(本文档算法) |
User-Agent |
okhttp/3.10.0 |
HTTP客户端标识 |
resolution |
2297*1080 |
设备屏幕分辨率 |
device_name |
LE2100 |
设备型号 |
app_version |
0.1.0 |
应用版本 |
app_channel |
dangbei |
分发渠道 |
aid |
01A3SOMfbw... |
设备唯一标识 |
cpu |
arm64-v8a |
CPU架构 |
brand |
OnePlus |
设备品牌 |
os_version |
Android+14 |
操作系统版本 |
androidId |
1e045da16be84679 |
Android设备ID |
已知 API 端点
| 端点 | 参数 | 说明 |
|---|---|---|
/init |
appkey |
初始化配置 |
/home |
appkey |
首页数据 |
/allcategory |
appkey |
全部分类 |
/category/detail |
category_id, appkey |
分类详情 |
/show |
materiel_id, appkey |
视频详情(含播放地址) |
8. 清晰度控制
API 返回的 resolution_ratio 数组已包含所有可用分辨率,无需额外参数控制:
| 标签 | 分辨率 | 描述 |
|---|---|---|
1080p |
1920×1080 | 高清(最高) |
720p |
1280×720 | 高清 |
480p |
852×480 | 标清 |
360p |
640×360 | 流畅 |
请求头中的 resolution: 2297*1080 是设备屏幕信息,不影响返回的视频分辨率列表。1080p 是该 API 返回的最高分辨率。
9. 设计特点分析
| 特点 | 说明 |
|---|---|
| 双重 MD5 | 增加逆向难度,单次碰撞无法直接得到密钥 |
| 密钥藏于 Native 层 | .so 库中通过 GOT 间接引用逐字符构建,对抗静态分析 |
| 无时间戳/随机数 | 签名确定性,相同参数永远产生相同 SIGN |
| 路径无关 | SIGN 不依赖 URL path,仅依赖查询参数 |
| 包名校验 | getSign 中包含 cn.krcom.video.sdk 包名验证 |
10. 使用示例
# 验证算法
python cibn_api.py verify
# 获取视频详情(含所有清晰度播放地址)
python cibn_api.py show 1034:4749754517880883
# 计算任意参数的 SIGN
python cibn_api.py sign appkey=1543205014 materiel_id=1034:4749754517880883
# 浏览首页
python cibn_api.py home
# 查看全部分类
python cibn_api.py allcategory
# 查看分类详情
python cibn_api.py category 4514586333151463
