MP4 Downloader Pro 6.3.11许可证验证算法分析报告
软件官方已经更新到了6.3.12版本https://www.tomabo.com/mp4-downloader-pro/purchase.html,
调试地址有变化,算法和类型无变化
分析工具:IDA Pro 9.3, x64dbg, Python
一、核心加密参数(完全确认)✅
1.1 AES-256参数
| 参数 |
值 |
| 算法 |
AES-256-CBC |
| 密钥长度 |
256位 (32字节) |
| 块大小 |
128位 (16字节) |
| 密钥值 |
0b5c74f63dac82171b236e65e8c95dd6144f207962ac5ed0fc611a2973a3bcbe |
密钥来源:
地址: 7FF72F7FFB30
数据: 0b5c74f6 3dac8217 1b236e65 e8c95dd6 144f2079 62ac5ed0 fc611a29 73a3bcbe
来源: MD5数组的第1和第2个值拼接
1.2 Base60字符集(确认)
字符集: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
长度: 58字符
缺失: y, z
用途: 字段9(序列号)编码
字符预处理:
z → l
y → O
1.3 Base64字符集
字符集: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
长度: 64字符
用途: 许可证整体编码
二、许可证格式(完全确认)✅
2.1 格式字符串
L"%X\n%I64X\n%I64X\n%I64X\n%I64X\n%I64X\n%I64X\n%s\n%s\n%I64X\n"
字段分隔符:换行符 \n
2.2 字段结构(10字段)
| 字段 |
格式 |
示例值 |
说明 |
状态 |
| 1 |
%X |
2 |
许可证类型(2=专业版) |
✅ 固定 |
| 2 |
%I64X |
44A4D |
用户ID标识 |
✅ 固定 |
| 3 |
%I64X |
22041E33 |
特征码1 |
✅ 固定 |
| 4 |
%I64X |
3423CFC5 |
特征码2 |
✅ 固定 |
| 5 |
%I64X |
7E24 |
版本标识 |
✅ 固定 |
| 6 |
%I64X |
204CFA8F9B |
时间戳 |
✅ 算法已知 |
| 7 |
%I64X |
57A97D694D |
特征码3 |
✅ 固定 |
| 8 |
%s |
text@qq.com |
用户邮箱 |
✅ 用户输入 |
| 9 |
%s |
60字符Base60 |
RSA签名 |
⚠️ 验证已知 |
| 10 |
%I64X |
1173FD4E |
校验和 |
⚠️ 公式已知 |
2.3 许可证编码流程
许可证明文(10字段,换行分隔)
↓
AES-256-CBC加密(密钥已知)
↓
组合:IV(16字节) + 密文
↓
Base64编码
↓
许可证文件
三、字段详细分析
3.1 字段1-8(完全确定)
| 字段 |
值/算法 |
说明 |
| 1 |
2 (固定) |
专业版标识 |
| 2 |
44A4D (固定) |
用户ID |
| 3 |
22041E33 (固定) |
特征码 |
| 4 |
3423CFC5 (固定) |
特征码 |
| 5 |
7E24 (固定) |
版本标识 |
| 6 |
日期算法 |
见下文 |
| 7 |
57A97D694D (固定) |
特征码 |
| 8 |
用户输入 |
邮箱地址 |
3.2 字段6时间戳算法(已确认)
字节结构:[字节0][字节1][字节2-4]
from datetime import datetime
import ctypes
today = datetime.now()
day = today.day
# 字节构造
byte0 = 0x20 # 固定
byte1 = day + 63 # 日期相关
uptime = ctypes.windll.kernel32.GetTickCount64()
# 组合
high_word = (byte0 << 8) | byte1
low_dword = uptime & 0xFFFFFFFF
field6 = (high_word << 24) | (low_dword >> 8)
验证:
- 5月13日:
204CFA8F9B → 字节1=0x4C=76=13+63 ✓
- 5月14日:
204DA8B7EB → 字节1=0x4D=77=14+63 ✓
3.3 字段9 RSA验证(完全理解)
RSA参数
公钥指数 e = 86579 (0x15233)
= Base60Decode("O2x")
模数 n = 9450238404903523290300083310366510149016278680321531423065722358517591045242789454573269042670570498033990165394386183833537938662242327254905711559316108061546474776231056774976648005429348668839370097214371725158447415156515692381691867259968864429185945334849764263903145999519603631064909626758846933819155367019803917533404036537596885614334313672689
= Base60Decode(DH43)
位数: 1180 bits
长度: 200字符(Base60编码)
DH43字符串: DH43Ydl65IZsIncKnCukuUZgGk8lLSBiC9JlaO5pxiioSXtl5iLTQEU1tnJMBYYUrjePIG9E6J210QFgWwjuRdsc2aw53GqaZ8NZn1itpwvhl52sBgi1RnIdSZhoMh5HDsHKqfILDCZFv6v28cEprsePAMJDPZRYkcZfO67eOCB7Nl66mjqbMZxkieIbqO773J8Qt94n
验证公式
result = field9^e mod n
其中:
- field9 = 用户输入的序列号(Base60解码为大整数)
- e = 86579
- n = DH43模数
- result = Base60编码的60字符输出
验证条件:
- result长度必须 == 60字符
- result必须等于预期值
验证流程
字段9(用户输入)
↓
sub_14000B92C 或 sub_140014A98(验证入口)
↓
sub_1400046A4(线程同步包装)
↓
sub_140004468(核心RSA计算)
│
├── Base60解码(输入 → 大整数)
├── 模幂运算(input^e mod n)
└── Base60编码(结果 → 60字符)
↓
检查结果长度 == 60
↓
验证通过/失败
3.4 字段10校验和(已确认)
公式: checksum = 718931 * v9 + 292814158
当 v9 = 0 时:
checksum = 292814158 = 0x1173FD4E
四、验证流程(完整版)
4.1 完整调用链
用户输入 (邮箱 + 许可证)
↓
许可证解析 (按换行符分割10个字段)
↓
字段验证
│
├── 字段1-8验证 (简单验证,已确定)
│
└── 字段9验证 (RSA验证)
│
├── sub_14000B92C / sub_140014A98
│ 输入: 字段9字符串
│ 输出: 60字符结果
│
└── 检查: 输出长度 == 60
↓
验证通过: "Registered successfully!"
验证失败: "Failed to register: invalid user ID or license key!"
4.2 RSA验证函数调用关系
验证入口层(4个):
├─ sub_140006AB8 → sub_14000B92C
├─ sub_140006D90 → sub_14000B92C
├─ sub_140007164 → sub_14000B92C
└─ sub_140012D14 → sub_140014A98
RSA验证函数层(2个):
├─ sub_14000B92C ──┐
│ ├─→ sub_1400046A4
└─ sub_140014A98 ──┘
↓
sub_140004468 (核心RSA计算)
4.3 关键函数地址
| 地址(静态) |
函数名 |
功能 |
| 0x14000B92C |
RSA验证入口1 |
字段9验证 |
| 0x140014A98 |
RSA验证入口2 |
字段9验证(备用) |
| 0x1400046A4 |
线程同步包装 |
调用核心算法 |
| 0x140004468 |
核心RSA算法 |
Base60+模幂运算 |
| 0x1400047B4 |
Base60检查 |
字符验证 |
| 0x14008EF70 |
字符串→大数 |
Base60解码 |
| 0x14008F49C |
模幂运算 |
核心计算 |
| 0x14008E590 |
大数→字符串 |
Base60编码 |
4.4 关键字符串地址
| 地址 |
字符串 |
用途 |
| 0x1402BF1B0 |
DH43Ydl65IZs... |
RSA模数n |
| 0x1402BF1A4 |
O2x |
RSA公钥指数e |
| 0x14000B46C+A5 |
%X\n%I64X\n... |
许可证格式 |
| 0x1402BDE28 |
0-9A-Z...uvwx |
Base60字符集 |
| 0x1402BDCD0 |
A-Za-z0-9+/ |
Base64字符集 |
五、产品架构分析
5.1 产品组成
Tomabo发布的三款MP4相关产品:
| 产品 |
功能 |
许可证格式 |
| MP4 Downloader Pro |
视频下载 |
10字段(主格式) |
| MP4 Converter |
视频转换 |
10字段(主格式) |
| MP4 Player |
视频播放 |
7字段(辅格式) |
产品关系
主产品(需要完整授权):
├─ MP4 Downloader Pro
│ └─ 功能:从视频网站下载视频
│ └─ 授权:专业版授权
│ └─ 验证:RSA验证(字段9)
│
└─ MP4 Converter
└─ 功能:视频格式转换
└─ 授权:专业版授权
└─ 验证:RSA验证(字段9)
辅助产品(简化授权):
└─ MP4 Player
└─ 功能:视频播放
└─ 授权:基础授权
└─ 验证:简化验证(无RSA)
5.2 许可证格式系统
5.2.1 主格式(10字段)
用途:MP4 Downloader Pro / MP4 Converter(详细字段说明请参考第二章)
验证特点:
- ✅ 完整的产品授权
- ✅ RSA签名验证(字段9)
- ✅ 防伪机制强
5.2.2 辅格式(7字段)
用途:MP4 Player / 其他功能模块
格式字符串:
L"%X\n%X\n%s\n%s\n%I64X\n%I64X\n%X\n"
字段结构:
| 字段 |
格式 |
说明 |
| 1 |
%X |
类型标识 |
| 2 |
%X |
子类型标识 |
| 3 |
%s |
字符串A |
| 4 |
%s |
字符串B |
| 5 |
%I64X |
64位数据1 |
| 6 |
%I64X |
64位数据2 |
| 7 |
%X |
校验值 |
验证特点:
- ⚠️ 简化的授权结构
- ⚠️ 无RSA验证
- ⚠️ 防伪机制弱
5.3 验证函数对应关系
5.3.1 主格式验证函数
| 函数地址 |
函数名 |
功能 |
产品 |
| 0x14000B46C |
sub_14000B46C |
解析10字段 |
Downloader/Converter |
| 0x140014280 |
sub_140014280 |
解析10字段 |
Downloader/Converter |
| 0x14000AF98 |
sub_14000AF98 |
生成10字段 |
Downloader/Converter |
| 0x140013D8C |
sub_140013D8C |
生成10字段 |
Downloader/Converter |
| 0x14000B92C |
sub_14000B92C |
RSA验证 |
Downloader/Converter |
| 0x140014A98 |
sub_140014A98 |
RSA验证 |
Downloader/Converter |
| 0x1400046A4 |
sub_1400046A4 |
RSA核心 |
Downloader/Converter |
| 0x140004468 |
sub_140004468 |
RSA算法 |
Downloader/Converter |
5.3.2 辅格式验证函数
| 函数地址 |
函数名 |
功能 |
产品 |
| 0x14000B2BC |
sub_14000B2BC |
解析7字段 |
Player |
| 0x1400140BC |
sub_1400140BC |
解析7字段 |
Player |
5.3.3 通用工具函数
| 函数地址 |
函数名 |
功能 |
| 0x14000BAAC |
sub_14000BAAC |
字段格式化(通用) |
5.4 产品共用机制
5.4.1 共用许可证验证模块
形式A:共享DLL
mp4_downloader.exe
mp4_converter.exe
mp4_player.exe
↓
共用验证模块(DLL)
└─ license_verify.dll
├─ RSA验证函数
├─ 10字段解析
└─ 7字段解析
形式B:静态链接库
每个EXE包含相同的验证代码
├─ 代码相同
├─ 函数地址相同
└─ 可统一补丁
形式C:单一EXE多功能
一个主EXE包含所有功能
├─ 通过参数/界面切换功能
└─ 共用验证逻辑
5.5 产品授权机制总结
主产品授权(强保护):
├─ MP4 Downloader Pro
├─ MP4 Converter
├─ 使用10字段许可证
├─ RSA签名验证
└─ 难以伪造
辅助产品授权(弱保护):
├─ MP4 Player
├─ 使用7字段许可证
├─ 无RSA验证
└─ 较易伪造
六、加密解密完整流程详解
6.1 概览图
┌─────────────────────────────────────────────────────────────────┐
│ 许可证生成流程(开发者) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤1: 构造许可证纯文本数据 │
│ 格式: 10个字段,换行符分隔 │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤2: 字段9 RSA签名 │
│ field9 = RSA_sign(data, private_key) │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤3: 转换为XML格式 │
│ <License>...</License> │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤4: AES-256加密 │
│ ciphertext = AES_encrypt(xml, key) │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤5: Base64编码 │
│ license_file = Base64(IV + ciphertext)│
└──────────────────────────────────────┘
│
▼
[许可证文件]
┌─────────────────────────────────────────────────────────────────┐
│ 许可证验证流程(程序) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤1: Base64解码 │
│ IV + ciphertext = Base64_decode(file)│
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤2: AES-256解密 │
│ xml = AES_decrypt(ciphertext, key, IV)│
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤3: 解析XML,提取10个字段 │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤4: 验证字段9 RSA签名 │
│ RSA_verify(field9, public_key) │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 步骤5: 验证其他字段 │
│ 时间戳、校验和、固定值等 │
└──────────────────────────────────────┘
│
▼
[验证通过/失败]
6.2 AES-256加密详解(AES参数请参考第一章)
6.2.1 AES加密流程(生成许可证时)
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import os
# 准备明文数据(XML格式)
xml_data = """<?xml version="1.0"?>
<License>
<Type>2</Type>
<UserID>44A4D</UserID>
<Feature1>22041E33</Feature1>
<Feature2>3423CFC5</Feature2>
<Version>7E24</Version>
<Timestamp>43BF3E5C</Timestamp>
<Feature3>57A97D694D</Feature3>
<Email>user@example.com</Email>
<SerialNumber>[100字符]</SerialNumber>
<Checksum>[值]</Checksum>
</License>"""
# 生成随机IV(每次不同)
iv = os.urandom(16)
# 创建AES加密器
cipher = AES.new(AES_KEY, AES.MODE_CBC, iv)
# PKCS7填充
padded_data = pad(xml_data.encode('utf-8'), 16)
# 加密
ciphertext = cipher.encrypt(padded_data)
# 组合:IV + 密文
encrypted_data = iv + ciphertext
6.2.4 AES解密流程(验证许可证时)
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64
# 从许可证文件读取Base64编码的数据
license_file_content = open('license.key', 'r').read()
# Base64解码
encrypted_data = base64.b64decode(license_file_content)
# 分离IV和密文(IV是前16字节)
iv = encrypted_data[:16]
ciphertext = encrypted_data[16:]
# 创建AES解密器
cipher = AES.new(AES_KEY, AES.MODE_CBC, iv)
# 解密
padded_data = cipher.decrypt(ciphertext)
# 去除PKCS7填充
xml_data = unpad(padded_data, 16).decode('utf-8')
6.3 RSA签名详解
6.3.1 RSA参数
# 公钥参数
e = 86579 # 公钥指数
n = 9450238404903523290300083310366510149016278680321531423065722358517591045242789454573269042670570498033990165394386183833537938662242327254905711559316108061546474776231056774976648005429348668839370097214371725158447415156515692381691867259968864429185945334849764263903145999519603631064909626758846933819155367019803917533404036537596885614334313672689
6.3.2 RSA验证流程(Base60字符集请参考第一章)
def verify_serial_number(serial_number, e, n):
"""验证序列号(字段9)"""
# 字符预处理(z→l, y→O)
processed = ''
for c in serial_number:
if c == 'z':
processed += 'l'
elif c == 'y':
processed += 'O'
else:
processed += c
# Base60解码
m = 0
for c in processed:
if c in BASE60:
m = m * 60 + BASE60.index(c)
# RSA验证
result = pow(m, e, n)
# 编码回Base60
verified = ''
temp = result
for _ in range(60):
verified += BASE60[temp % 60]
temp //= 60
verified = verified[::-1]
return len(verified) == 60
6.4 各加密算法的协作关系
6.4.1 层次结构
┌─────────────────────────────────────────┐
│ 最外层: Base64 │
│ 作用: 编码转换,二进制 → ASCII │
│ 强度: 无加密,仅编码 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 中间层: AES-256 │
│ 作用: 对称加密,保护数据机密性 │
│ 强度: 强,但密钥硬编码可被提取 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 最内层: RSA │
│ 作用: 非对称签名,防止伪造 │
│ 强度: 最强,依赖大数分解难题 │
└─────────────────────────────────────────┘
6.4.2 各层的弱点
| 层次 |
算法 |
弱点 |
攻击方法 |
| 外层 |
Base64 |
无加密 |
直接解码 |
| 中层 |
AES-256 |
密钥硬编码 |
从程序提取密钥 |
| 内层 |
RSA |
依赖n的分解难度 |
分解n得到私钥 |
七、产品信息
产品名: MP4 Downloader Pro
版本: 6.3.11
GUID: {9FE2EB1A-5BED-4a53-9548-2C56662FF958}
注册表: HKEY_CURRENT_USER\Software\Tomabo\MP4 Downloader Pro
八、当前状态总结
8.1 已完成 ✅
- [√] AES-256密钥提取
- [√] 许可证格式完全解析(10字段)
- [√] Base60字符集确认
- [√] Base64字符集确认
- [√] 字段1-8完全确定
- [√] 字段6时间戳算法破解
- [√] 字段10校验和公式确认
- [√] 字段9 RSA验证流程完全理解
- [√] RSA参数提取(e, n)
- [√] 所有关键函数定位
- [√] 函数调用关系分析
- [√] 验证函数交叉引用分析
8.2 未完成 ❌
- [ ] 字段9生成(需要RSA私钥d)
- [ ] DH43模数n的分解
- [ ] 完整的注册机实现