首页
社区
课程
招聘
[原创]TencentPediyKeygenMe2.exe 逆向分析解题报告
发表于: 5小时前 184

[原创]TencentPediyKeygenMe2.exe 逆向分析解题报告

5小时前
184

1. 最终答案

用户名:

KCTF

序列号:

DQF030H7-7X8P0YMA-WHZNQEGF-CFEVXVTA

本地验证结果:输入后点击 Verify,弹出:

Success!
Congratulations!
You will be the keygen machine!

2. 样本信息

文件:

TencentPediyKeygenMe2.exe

PE 信息:

MD5     : 88b071f0935c7474b2859976197f1465
SHA256  : f163b1f14b39b98f8a0dabf300104e7843d83ab55e8085862382faba1db8fe32
ImageBase : 00400000
EntryPoint: 0043BF2F

节区:

.text   VA 00401000
.rdata  VA 00454000
.data   VA 00468000
.rsrc   VA 0046F000

导入表中有:

DialogBoxParamA
GetDlgItem
SendMessageA
MessageBoxA
EndDialog

并且字符串中存在大量 Crypto++ 符号:

CryptoPP
ECDSA
ECP
SHA1
DL_Verifier

说明验证核心确实是椭圆曲线签名验证。


3. 界面资源分析

主对话框资源 ID:

101

标题初始为:

KeygenMe

运行后窗口标题被设置为:

#KeygenMe#

控件:

ID 1    : Verify 按钮
ID 1002 : User Name 输入框
ID 1003 : License Code 输入框

关键代码:

0040816C push 65h
0040816F call dword ptr [45411C] ; DialogBoxParamA

这里 0x65 = 101,即创建资源 ID 101 的对话框。

对话框回调函数:

00408210

点击 Verify 后进入:

CHECK_FN = 00408270

4. 序列号格式

00408270 中:

004083D1 push 0Dh
004083D3 push ecx
004083D4 call esi ; SendMessageA,读取用户名

0040842A push 0Dh
0040842C push eax
0040842D call esi ; SendMessageA,读取注册码
0040842F cmp eax, 23h

注册码长度必须是:

0x23 = 35

注册码格式为:

8-8-8-8

中间 3 个 - 的位置由表控制:

0046A3F8 : 08 11 1A

也就是第 8、17、26 个字符必须是 -

有效字符表:

004579A8 : ABCDEFGHJKMNPQRSTVWXYZ1234567890

所以序列号使用自定义 Base32 字符集:

ABCDEFGHJKMNPQRSTVWXYZ1234567890

5. 验证流程还原

整体流程:

License 35 chars
    ↓ 去掉 3 个 '-'
32 chars
    ↓ 自定义 Base32 解码
20 bytes
    ↓ 16 bytes 数据块 + 4 bytes 校验块
    ↓ Security@Tencent 相关块变换
    ↓ GF(2^8) 逆变换,模多项式 0x11B
    ↓ DEADBEEF 相关 Blowfish/块变换
16-byte 签名块
    ↓ checksum 校验
ECDSA VerifyMessage(username, signature)

关键函数:

0044490B0 : 自定义 Base32 解码
00408060 : 以 "Security@Tencent" 为 key 的块变换
004486D0 : GF(2^8) 字节逆变换,模多项式 0x11B
00407FD0 : 以 "DEADBEEF" 为 key 的块变换
00403210 : 椭圆曲线签名验证
0041DD80 : Crypto++ VerifyMessage

成功路径:

004085AA test al, al
004085AC je   004085C5
004085B4 push 0046A3B8 ; "Success!"
004085B9 push 0046A3C4 ; "Congratulations! ..."
004085BF call MessageBoxA

6. 椭圆曲线部分

样本使用小参数椭圆曲线,私钥实际硬编码在数据区:

0046A54C : 54 65 6E 63 65 6E 74 20

ASCII 为:

Tencent

作为整数:

d = 0x54656E63656E7420

关键参数:

n   = 0xC564EEF19A080B07
rho = 0x6CBF49B72611C49A
r   = 0x0000000000000001

用户名参与 SHA1:

z = SHA1(username)[:8]

对于:

KCTF

有:

SHA1(KCTF)[:8] = 0x0C5E14D370BD9A84

签名计算:

s = rho^-1 * (z + d * r) mod n

代入:

s = 0x120BAA4576344E44

所以 16 字节签名块为:

r || s

即:

0000000000000001120BAA4576344E44

7. ECC 部分可复现脚本

import hashlib

name = b"KCTF"

n   = 0xC564EEF19A080B07
rho = 0x6CBF49B72611C49A
d   = 0x54656E63656E7420
r   = 1

z = int.from_bytes(hashlib.sha1(name).digest()[:8], "big")
s = (pow(rho, -1, n) * (z + d * r)) % n

sig = r.to_bytes(8, "big") + s.to_bytes(8, "big")

print("z   =", f"{z:016X}")
print("r   =", f"{r:016X}")
print("s   =", f"{s:016X}")
print("sig =", sig.hex().upper())

输出:

z   = 0C5E14D370BD9A84
r   = 0000000000000001
s   = 120BAA4576344E44
sig = 0000000000000001120BAA4576344E44

8. 校验块

程序对 16 字节签名块按 little-endian dword 分组后异或:

import struct

sig = bytes.fromhex("0000000000000001120BAA4576344E44")
a, b, c, d = struct.unpack("<4I", sig)

checksum = a ^ b ^ c ^ d

print(hex(checksum))
print(checksum.to_bytes(4, "little").hex())

结果:

checksum = 0x00E43F64
bytes    = 643FE400

9. 最终编码结果

将:

sig      = 0000000000000001120BAA4576344E44
checksum = 643FE400

按程序的逆向编码链处理:

DEADBEEF 块变换逆过程
GF(2^8) 字节逆变换
Security@Tencent 块变换逆过程
自定义 Base32 编码
按 8-8-8-8 插入 '-'

得到最终注册码:

DQF030H7-7X8P0YMA-WHZNQEGF-CFEVXVTA

10. 本地验证

输入:

User Name:
KCTF
License Code:
DQF030H7-7X8P0YMA-WHZNQEGF-CFEVXVTA

点击:

Verify

结果弹窗:

Success!
Congratulations!
You will be the keygen machine!



[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

最后于 5小时前 被mb_dcvvjyqc编辑 ,原因: 隐私泄露
收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回