TA的每日心情 | 开心 2025-1-14 00:25 |
|---|
签到天数: 14 天 [LV.3]偶尔看看II
|
本帖最后由 wx69wx2025 于 2026-5-8 22:45 编辑
【文章标题】: forscan之移花接木
【文章作者】: wxxw
【软件名称】: forscan
【保护方式】: ASProtect 2.xx
【编写语言】: NA
【使用工具】: PEID 0.95 Olldbg1.10
【操作平台】: win7 x86
【软件介绍】: 不用介绍了吧
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
缘起:
最近有点恼火,车启动后有时报失火,于是找了个汽车诊断软件forscan(官网forscan.org), 下载了最新版2.3.70,发现是VMProtect保护,直接放弃,后来想想找个老版本吧,挑挑软柿子捏捏,于是找到一个老版本2.3.19, 查了下发现是ASProtect保护,心里窃喜,但用OD加载ASProtect脚本居然脱壳失败,这下抓瞎了...
于是在KANXUE/52PJ/PYG都搜了下,发现52有道友共享,原帖:https://www.52pojie.cn/forum.php?mod=viewthread&tid=1381906,软件下载:https://wws.lanzouj.com/ioufTmegevc (除了2.3.38安装包,还有forscan_crack.exe /forscan_crack.dll),感谢这位道友“有点颜色的百度”奉献了在某宝上购买的软件。
可安装之后发现无论怎么运行都是未激活状态,它的授权界面如下, 没办法只能在五一假期抽空研究。
非常感谢在研究过程中Sound,Zenix,KuNgBiM等各位大佬的热心帮助!

探析:
注意如下分析是在2.3.19版本下进行的,安装包:https://gofile.io/d/iaQ5CH,操作系统win7 x86(该程序好像对系统敏感?win10 x64下od加载运行后的硬件码和直接运行不一样,且有些断点断不下来)
首先感谢大佬sound帮忙脱了壳,不过脱壳后程序运行硬件码是12345678,与未脱壳前明显不同。后来发现程序是一边解码一边执行,因此猜测硬件码生成,授权验证过程是程序在解码过程中同步完成的,也就是脱壳后的程序不会再次执行生成硬件码,授权验证等逻辑。
没办法只能硬着头皮带壳分析。因为对程序一无所知,基本思路还是逆向思维,一步步倒推。过程如下:
在注册界面有个按钮可以加载授权文件,手动创建个.key文件,内容随便写,od加载对createfile/readfile下断,结果发现读取的内容会与REGEDIT4比较,并且出现HCU/SOFTWARE/ASTECH/FORSCAN以及 key,id等字符串,基本可以判断与注册表信息有关。
然后查看本机注册表,发现已经有key/id, 这个是forscan_crack.exe 生成的,要说这个淘宝老哥也够鸡贼的,卖的并不是通用的破解,而是绑定了硬件码,这份破解文件生成注册表里的硬件码ID固定为226FBFDB-CB5B,而我们的硬件码肯定不同,所以顺理成章的取巧办法就是修改我们的硬件码为226FBFDB-CB5B,根据对比时出现的本机硬件码,一路倒查,发现本机硬件码来自内存块A,该内存块是由00784707 CALL FORScan.00775C08随机分配的,每次运行程序都不一样,硬件码数据在A[20],下内存写入断点,发现是由0078DB28 CALL aaa.0078DA20得来的,重新加载程序发现需要调用多次该call后才会出现硬件码,手动修改它为226FBFDB(后面的CB5B是由226FBFDB计算得来),结果继续运行程序会崩溃,反复多次后得出结论,不能直接替换硬件码,因为根据软件说明,硬件码id=f(硬盘序列号、主板、cpu),猜测程序功能或解码用的密钥=g(注册表key,硬盘序列号、主板、cpu),所以直接替换硬件码ID没用,除非将硬盘序列号,主板,cpu 都替换一样,因为调试需要反复加载运行,断点指令又得在程序部分解码后才能下,所以写了个简单脚本见附件(forscan.osc)。其中弹窗是ECX值(内存块A的起始地址),在ECX右键--数据窗口跟随,如下图
其中位置1为硬盘序列号(怎么知道的?系统cmd窗口执行vol c:得到硬盘序列号,然后在硬件码附近就发现了它,紧跟它的就是主板cpu数据见位置2,硬件码在位置3),

继续跟踪分析由硬盘序列号等信息如何生成硬件码,最后跟踪到算法在00783414
- 00783414 55 PUSH EBP
- 00783415 8BEC MOV EBP,ESP
- 00783417 52 PUSH EDX
- 00783418 56 PUSH ESI
- 00783419 51 PUSH ECX
- 0078341A FC CLD
- 0078341B BA 8E243B9C MOV EDX,9C3B248E
- 00783420 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
- 00783423 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
- 00783426 AC LODS BYTE PTR DS:[ESI]
- 00783427 30C2 XOR DL,AL
- 00783429 B0 08 MOV AL,8
- 0078342B D1EA SHR EDX,1
- 0078342D 73 06 JNB SHORT FORScan.00783435
- 0078342F 81F2 9AF3A7C1 XOR EDX,C1A7F39A
- 00783435 FEC8 DEC AL
- 00783437 ^ 75 F2 JNZ SHORT FORScan.0078342B
- 00783439 49 DEC ECX
- 0078343A 09C9 OR ECX,ECX
- 0078343C ^ 75 E8 JNZ SHORT FORScan.00783426
- 0078343E 92 XCHG EAX,EDX
- 0078343F 59 POP ECX
- 00783440 5E POP ESI
- 00783441 5A POP EDX
- 00783442 5D POP EBP
- 00783443 C2 0800 RETN 8
复制代码
将算法丢给claude code分析,得出如下结论:
这是一个 CRC-32 变体算法(自定义多项式的循环冗余校验)。算法分析
函数签名: 输入为数据指针 a1 +长度 a2,输出为 unsigned int(4字节,非8字节)。
核心流程:
初始值(seed): 0x9C3B248E 多项式(poly):0xC1A7F39A 逐步过程:
1.初始化 CRC 寄存器 v2 = 0x9C3B248E 2.对每个输入字节 循环:
﹣将当前字节 XOR 到 v2 的最低字节
﹣内层循环 8 次(逐 bit 处理):
- 取 v2 的最低位(LSB)
- v2 右移 1 位
﹣若 LSB 为1,则 v2^= 0xC1A7F39A
3.返回 最终的 v2
伪代码简化
uint32_t crc = 0x9C3B248E;
for (int i = 0; i < len; i++) {
crc = (uint8_t)data;
// XOR 到低字节
for (int bit = 0; bit < 8; bit++) {
if (crc & 1)
crc = (crc >> 1) ^ 0xC1A7F39A;
else
crc >>=
~
return crc;
- 这是标准的 LSB-first(反射型)CRC-32
结构,但使用了非标准的多项式和初始值(标准 CRC-32 用 0xEDB88320
和初始值 0xFFFFFFFF)
- 输出是 4 字节(32位)
所以现在的问题变成了怎么修改硬盘序列号,主板,cpu等,使得CRC结果为226FBFDB,因为微软提供了便捷工具volumeid可以修改硬盘序列号,所以问题又简化了,在不变更cpu,主板数据下,硬盘序列号为多少时得到该CRC结果,让AI写了个程序,很快就得到结果。
程序见附件(solve.c)
拿到硬盘序列号,剩下就简单了,volumeid c: aabb-ccdd, 重启电脑检查已生效,执行程序会发现硬件码已更换,执行forscan_crack.exe发现大功告成。

Btw:这个crack只能用于2.3.38,如果用于2.3.19程序会崩溃退出,应该是crack注入forscan后因版本不符修改数据不对. crack本身用vmprotect加密了,没法分析,另外执行crack时,会向如下地址发起连接beec0a904f29.sn.mynetname.net:27000,怀疑淘宝哥是留个破解记录还是C2控制?测试断网使用功能并没影响,通讯数据如下:
POST /api/cx2v.php
HTTP/1.1..Connection: Keep-Alive..Content-Type: application/x-www-form-urlencoded; charset=utf-8..Accept-Encoding: gzip, deflate..Accept-Language: zh-cn..User-Agent: Crack_RSA_Api v2.1..Content-Length: 88..Host: beec0a904f29.sn.mynetname.net:27000
2.3.19版发送
Mode=HerInfo&Data=19tArV627eizEsUOTW2UKwN%2FEg3QSEDhMF2LO%2FgoOX3M%2FIPX......
2.3.38版发送
Mode=HerInfo&Data=ir%2Fc36EOQc1ojctLYKZdM1xvK0XbCrZPoCxk%2FiUJDi%2BLMAADNyya......
有没有不用真实修改硬盘序列号的办法呢?当然有,这就不得不提强大的神器baymax.
对上面的位置1硬盘序列号和位置2主板数据下内存写入断点,很快就发现如下指令
- 0078470E E8 ED13FFFF CALL aaa.00775B00
- 00784713 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
- 00784716 8910 MOV DWORD PTR DS:[EAX],EDX
- 00784718 8BC3 MOV EAX,EBX
- 0078471A E8 E113FFFF CALL aaa.00775B00
- 0078471F 83C0 04 ADD EAX,4
- 00784722 8930 MOV DWORD PTR DS:[EAX],ESI
复制代码
其中00784716处EDX的值就是硬盘序列号,00784722处ESI的值就是主板数据,往上翻翻就发现有调用GetVolumeInformationA.
更改EDX/ESI值为一组满足CRC算法的数据即可,使用AI很快得到一组,如a2b9df8800000000(AI程序见附件forscan2.py)
使用baymax补丁如下:补丁时机hook GetVolumeInformationA, 中断后地址00784716更改EDX为88dFB9A2,00784722更改ESI为0,注意这两个指令用到3次,一次应该是用于生成硬件码,一次用于重复生成硬件码A[80],一次用于注册表里的key解密钥?
执行后会发现硬件码已变为226FBFDB
因为crack是注入方式,猜测是替换了RSA公钥(网络通讯的User-Agent: Crack_RSA_Api),它导入注册表的key是自己的私钥生成的,不是官方合法KEY, 所以必须执行crack启动forscan才有效,这也要求我们的补丁只能使用dll劫持方式。
forscan.zip
(197.74 KB, 下载次数: 5)
|
评分
-
查看全部评分
|