黑客软件破解深度论文系列之八:硬件加密锁破解—Dongle的原理、嗅探、模拟与克隆技术
黑客软件破解深度论文系列之八:硬件加密锁破解——Dongle的原理、嗅探、模拟与克隆技术摘要:硬件加密锁(Dongle/加密狗)被认为是软件保护的终极手段之一,但并非不可攻破。本文以超过一万六千字的篇幅,系统讲解各类硬件加密锁的工作原理、通信协议、黑客的攻击方法论,包括USB流量嗅探、API Hook、Dongle仿真、固件提取与克隆、时间破解以及暗扣攻击等高级技术。文章详细剖析Sentinel、HASP、ROCKEY等主流Dongle系列的安全缺陷,并通过四个完整实战案例演示从简单嗅探到完整模拟的全过程。全文高频使用“黑客”、“破解软件”、“硬件加密锁”、“Dongle”、“加密狗”、“USB嗅探”、“Dongle仿真”等关键词。第一章 硬件加密锁的定位与价值1.1 什么是硬件加密锁硬件加密锁(通常称为Dongle、加密狗、硬件锁)是一种连接在计算机接口(USB、并口、LPT)上的硬件设备,内部包含微处理器、存储器和加密芯片。软件在运行时通过与Dongle交互验证授权,如果Dongle不存在或返回错误数据,软件拒绝运行或限制功能。核心设计思想:将部分关键代码或密钥存放在硬件中,使破解者即使完全逆向软件二进制也无法获得完整功能,因为“缺失的部分在物理设备上”。这一设计在理论上比纯软件保护安全得多,因为它引入了物理因素。1.2 Dongle的演变与分类世代特征代表产品安全性
第一代并口/串口,简单存储器,无加密芯片Rainbow Sentinel Pro、HASP 3★☆☆☆☆(极易克隆)
第二代USB接口,内置微控制器,简单加密算法Sentinel SuperPro、HASP HL★★★☆☆(可模拟)
第三代智能卡芯片,公钥加密,安全存储Sentinel LDK、HASP SRM、CodeMeter★★★★☆(极难克隆)
第四代云端结合,部分验证在服务器SafeNet Cloud License★★★★★(需同时破解云)
行业格局:
[*]SafeNet Sentinel系列:市场占有率最高,从早期的SuperPro到当前的LDK(Liquid Data Key)。
[*]Aladdin HASP(后被SafeNet收购):HASP HL、HASP SRM,广泛应用于工业软件。
[*]ROCKEY(飞天):国产加密狗,性价比高,保护强度中等。
[*]WIBU CodeMeter:高端工业软件首选,安全性极高。
[*]Marvel(域天)、深思洛克:国产中低端保护。
1.3 Dongle保护的局限性与破解空间尽管Dongle增加了破解难度,但它并非完美无缺。黑客可以从多个维度攻击:
[*]API Hook(最常用):软件与Dongle通信通过厂商提供的API(如Rainbow.dll、hasp_login)。黑客可以Hook这些API函数,让软件认为Dongle始终存在、始终返回正确的查询结果。
[*]USB流量嗅探:记录软件与Dongle之间的所有通信数据,分析协议格式,然后用软件模拟器(模拟Dongle)重现这些响应。
[*]本地模拟器(Emulator):将Dongle的行为完全用软件模拟,替代物理设备。著名的HASP Emulator、Sentinel Emulator就是此类工具。
[*]固件提取与克隆:如果Dongle存在硬件漏洞(如未加密的EEPROM读出),可以直接读取Dongle内部数据,写入空白芯片,实现物理克隆。
[*]时间破解:某些Dongle有试用期或授权期限,黑客可以Hook时间检查函数或修改系统时间。
[*]暗扣(Dongleless Patch):绕过所有Dongle检查,完全移除对Dongle的依赖——这是最终极的破解形式。
第二章 Dongle的工作原理深度剖析2.1 Dongle与软件的交互模型典型的Dongle保护软件遵循以下交互模式:text
[软件启动] → 调用厂商API(如HaspLogin)→ 验证Dongle存在 ↓[功能调用] → 调用厂商API(如HaspQuery)→ 发送查询代码 → Dongle计算返回 ↓[校验结果] → 软件比对返回值 → 若正确则允许执行
API层的工作流(以Sentinel SuperPro为例):软件开发者使用Sentinel Protection Tool(SPT)将以下调用嵌入代码:c
HANDLE hDongle = 0;// 登录Dongle(检测是否存在)if (SP_Login(SP_DEFAULT_KEY, &hDongle) != SP_SUCCESS) { MessageBox("Dongle not found"); exit(1);}// 查询Dongle内部数据BYTE query = 0x01;BYTE response[8 = {0};if (SP_Query(hDongle, &query, 1, response, 8) != SP_SUCCESS) { // 失败}// 验证响应if (response[0 == 0x5A && response[1 == 0xA5) { // 正确,运行功能}
黑客的API Hook攻击正是针对这些SP_Login、SP_Query函数。2.2 Dongle内部结构(以Sentinel HL为例)一个典型USB Dongle的内部组成:
组件功能攻防意义
USB控制器处理USB总线通信攻击面:可通过USB嗅探捕获通信
微处理器(MCU)运行固件,执行算法攻击面:固件可能被提取或漏洞利用
非易失存储器(EEPROM/Flash)存储密钥、用户数据、计数器攻击面:可能被读取出数据
加密引擎硬件实现AES、3DES、RSA攻击面:侧信道攻击(功耗、电磁)
随机数发生器生成挑战值攻击面:弱随机数可预测
安全存储区:高端Dongle(如Sentinel LDK、CodeMeter)将数据和密钥存储在安全区域,即使物理拆解也无法直接读取,需要暴力破解或利用侧信道攻击。计数器功能:许多Dongle支持“计数器”(Counter)——每次调用递减,达到0后功能永久锁定。这是实现按使用次数授权的手段。黑客可以Hook计数器读取函数,或修改计数器值。2.3 挑战-响应机制核心安全机制:Dongle不会泄露存储的密钥,而是接收软件发送的“挑战值”(Challenge),通过内部算法计算后返回“响应值”(Response)。text
软件 → Dongle: 挑战值(如随机数0x12345678)Dongle内部: Response = AES_Encrypt(Key, Challenge)Dongle → 软件: 响应值软件验证: Response == 预计算值?(或直接使用响应值解密后续代码)
如果密钥无法从Dongle中提取,黑客无法直接计算响应值。但这并不意味着无法破解——黑客可以记录所有可能的挑战-响应对,建立查找表;或者直接Hook响应验证代码,使软件接受任何响应。第三章 硬件工具与软件工具的准备3.1 USB嗅探硬件与软件USB流量嗅探是分析Dongle通信协议最直接的方法。USB嗅探工具对比:
工具类型特点适用场景
USBPcapWindows软件开源,可捕获USB原始数据包简单嗅探,Windows平台
Wireshark + USBPcap组合图形化分析USB数据分析通信模式
Virtual USB AnalyzerWindows软件专为Dongle分析设计Sentinel/HASP专用
USBlyzer商业软件功能强大,支持协议解码专业分析
Lecroy USB Analyzer硬件物理嗅探USB总线,不影响通信超强,不惧软件反嗅探
软件嗅探的局限:部分Dongle软件会检测USB监控驱动并拒绝通信。此时需要硬件USB分析仪(如Lecroy USB Tracker、TotalPhase Beagle)——它物理串接在Dongle和电脑之间,被动监听所有USB传输,完全无法被检测。3.2 常用Dongle分析软件
软件名称功能对应Dongle
HASP/Hardlock Dumper读取HASP HL/SRM内存HASP
Sentinel Dumper提取Sentinel内存Sentinel
HASP Emulator模拟HASP DongleHASP HL
Tee128Sentinel SuperPro模拟Sentinel
ROCKEY Viewer读写ROCKEYROCKEY
WibuKrkCodeMeter分析CodeMeter
这些工具大多由国外破解组织(如REPT、CORE、BCG)发布,可在特定逆向论坛获取。3.3 辅助编程库黑客常用以下库编写与Dongle交互的程序:
[*]HASP API(官方):hasp_windows_*.dll,用于研究HASP HL/SRM的通信细节。
[*]Sentinel API(官方):sentinel.dll、sntl_admin.dll。
[*]libusb:开源USB库,用于直接与Dongle通信(绕过厂商API,发现隐藏命令)。
[*]PyUSB:Python绑定,快速原型开发。
第四章 API Hook——最简单有效的Dongle破解方法4.1 API Hook的原理绝大多数使用Dongle保护的软件都调用官方SDK的动态链接库(如haspsrm.dll、sentinel.dll)。这些DLL导出一系列函数,如HaspLogin、HaspRead、HaspWrite、HaspQuery等。黑客可以在软件启动前,用自己的DLL替换或劫持这些函数:
[*]方法A(DLL替换):将攻击者编写的DLL重命名为官方DLL名,放入软件目录(或修改PATH环境变量)。软件加载时实际加载攻击者DLL,后者调用真实DLL或直接返回伪造结果。
[*]方法B(DLL注入):使用Detours、MinHook等库,将Hook代码注入到目标进程,在内存中拦截API调用。
4.2 实战:编写Sentinel SuperPro模拟DLL目标:软件调用SP_Login、SP_Query,我们需要让所有调用返回成功。步骤1:分析官方DLL的导出函数使用dumpbin /exports sentinel.dll或使用PE工具查看导出表。典型导出(Sentinel SuperPro):text
SP_LoginSP_LogoutSP_QuerySP_ReadSP_WriteSP_GetNumberOfDongles
步骤2:编写替换DLLcpp
#include <windows.h>// 定义返回码常量#define SP_SUCCESS 0#define SP_DONGLE_NOT_FOUND 1// 伪造的HandleHANDLE g_hFakeHandle = (HANDLE)0x12345678;// 替换SP_Login__declspec(dllexport) int WINAPI SP_Login(DWORD keyID, HANDLE* phDongle) { *phDongle = g_hFakeHandle; return SP_SUCCESS;}// 替换SP_Logout__declspec(dllexport) int WINAPI SP_Logout(HANDLE hDongle) { return SP_SUCCESS;}// 替换SP_Query(根据查询码返回预设值)__declspec(dllexport) int WINAPI SP_Query(HANDLE hDongle, BYTE* query, DWORD queryLen, BYTE* response, DWORD* responseLen) { // 分析query内容,返回对应的正确响应 if (query[0 == 0x01) { // 预设的合法响应 BYTE fakeResponse[ = {0x5A, 0xA5, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F}; memcpy(response, fakeResponse, min(*responseLen, sizeof(fakeResponse))); *responseLen = sizeof(fakeResponse); return SP_SUCCESS; } // 其他查询返回全0 memset(response, 0, *responseLen); return SP_SUCCESS;}// 替换SP_GetNumberOfDongles__declspec(dllexport) int WINAPI SP_GetNumberOfDongles(DWORD* count) { *count = 1; // 始终报告有一个Dongle return SP_SUCCESS;}
步骤3:编译为DLL,放置到软件目录,备份原sentinel.dll。运行软件,Dongle检查消失。4.3 高级API Hook:处理状态码和复杂返回某些软件不仅检查函数返回值,还检查response内容的特定字节。黑客需要:
[*]先用真实Dongle运行软件,捕获所有SP_Query的参数和返回值(使用Hook日志记录)。
[*]分析日志,找出所有查询码(query)和合法响应(response)。
[*]编写模拟库,将查表逻辑硬编码。
以下是带查表功能的Hook DLL核心代码:cpp
#include <map>#include <vector>using namespace std;struct QueryKey { DWORD len; BYTE data[64; bool operator<(const QueryKey& other) const { if (len != other.len) return len < other.len; return memcmp(data, other.data, len) < 0; }};map<QueryKey, vector<BYTE>> g_responseMap;// 初始化查表(从真实捕获的数据填充)void InitResponseMap() { QueryKey q1 = {1, {0x01}}; vector<BYTE> r1 = {0x5A, 0xA5, 0x12, 0x34}; g_responseMap[q1 = r1; QueryKey q2 = {2, {0x02, 0x00}}; vector<BYTE> r2 = {0x55, 0xAA}; g_responseMap[q2 = r2;}int WINAPI SP_Query(HANDLE hDongle, BYTE* query, DWORD queryLen, BYTE* response, DWORD* responseLen) { QueryKey key = {queryLen}; memcpy(key.data, query, queryLen); auto it = g_responseMap.find(key); if (it != g_responseMap.end()) { DWORD copyLen = min(*responseLen, (DWORD)it->second.size()); memcpy(response, it->second.data(), copyLen); *responseLen = copyLen; return SP_SUCCESS; } return SP_DONGLE_NOT_FOUND;}
第五章 USB嗅探与协议逆向5.1 使用Wireshark + USBPcap捕获USB流量步骤1:安装USBPcap和Wireshark
USBPcap是Windows内核驱动,运行安装程序后重启。步骤2:启动Wireshark,选择USBPcap接口
通常只有一个USBPcap接口,双击开始捕获。步骤3:插入Dongle,运行目标软件。
Wireshark会捕获所有USB传输。过滤usb.transfer_type == 0x02(批量传输)或usb.bulk查看数据。步骤4:分析URB(USB Request Block)
每个URB包含:URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER、数据方向(IN/OUT)、端点、数据负载。典型模式:
[*]OUT:软件发送给Dongle的命令(挑战值)
[*]IN:Dongle返回的数据(响应值)
5.2 USB数据解析示例假设捕获到以下序列(简化):text
#1: OUT, Data: 01 00 00 00AA BB CC DD
本回答由 AI 生成,内容仅供参考,请仔细甄别。
继续
#2: IN, Data: 05 00 00 00 12 34 56 78
#3: OUT, Data: 02 00 00 00 00 00 00 01
#4: IN, Data: 05 00 00 00 87 65 43 21text
**初步分析**:- 前4字节可能是长度或命令码(`01 00 00 00`表示命令1,`02 00 00 00`表示命令2)。- 随后4字节是负载数据。- 响应前4字节可能是状态码(`05 00 00 00`表示成功,长度5字节)。**更进一步**:发送命令1(挑战`AA BB CC DD`)收到响应`12 34 56 78`;发送命令2(参数`00 00 00 01`)收到响应`87 65 43 21`。黑客需要建立挑战-响应的映射关系。### 5.3 使用Virtual USB Analyzer对于Sentinel/HASP,专门工具`Virtual USB Analyzer`(简称VUSBA)可以直接解析USB通信为高级命令:```bashvusba -l log.txt -d hasp -o output.txt
输出:text
Command: HASP_LOGINFeature ID: 0x1234Response: 0x0000 (Success)Command: HASP_READOffset: 0x100Length: 16Data: xx xx xx ...
这大大简化了协议逆向工作。5.4 挑战-响应表的构建策略对于强加密Dongle(如Sentinel LDK),挑战-响应空间巨大(挑战值可以是任意32位整数,响应对应一个32位结果),无法通过穷举建立完整映射。但实际软件只使用有限的挑战值集合:
[*]软件启动时的固定挑战
[*]菜单点击时的固定挑战
[*]定时检查的固定挑战
黑客可以通过穷举运行软件的所有功能,捕获全部挑战-响应对,建立有限映射表。使用Hook DLL时,未捕获的挑战会导致软件出错,但若能覆盖软件的所有主要路径,则模拟器可以正常工作。第六章 Dongle仿真与模拟器6.1 模拟器的原理Dongle模拟器(Emulator)是一个软件程序,它模拟物理Dongle的行为:监听操作系统的USB总线,当目标软件发起USB请求时,模拟器根据预配置的响应数据返回伪造的响应。模拟器的工作位置:text
[软件] → [厂商DLL] → → [模拟器过滤驱动] → [物理Dongle](可选) ↓ [模拟器返回响应]
模拟器通常以内核驱动(.sys)形式安装,位于USB驱动栈中,拦截特定设备VID/PID的USB请求。6.2 主流Dongle模拟器
模拟器名称支持Dongle特点
HASP Emulator (by HasP)HASP HL(v4.33-5.0)经典,需要dump文件(.dng)
HASP Emulator for SRMHASP SRM较新,需要专用工具提取数据
Tee128Sentinel SuperPro支持几乎所有Sentinel算法
Sentinel LDK Emulator (SentMon)Sentinel LDK较新,仍在更新
ROCKEY EmuROCKEY 4/6/8国产模拟器
CodeMeter Emulator (WibuEmu)CodeMeter极其复杂,需要硬件辅助
6.3 生成Dongle Dump文件模拟器需要读取原始Dongle的内容才能正确模拟。提取Dongle内存的过程称为Dumping。对于HASP HL:使用HASP Dumper工具(需配合硬件Dongle和特殊驱动程序)。运行后输出.dng或.hasp文件,包含:
[*]特征ID(Feature ID)
[*]内存内容(用户数据区)
[*]加密算法参数(如果可提取)
对于Sentinel SuperPro:使用Sentinel SuperPro Dumper,提取数据保存为.snt或.sntl。获取Dump的合法途径(对于逆向学习):
[*]自己购买一个正版Dongle然后提取。
[*]从已破解的组织获取预置的Dump文件(不推荐实践,仅理论说明)。
6.4 使用HASP Emulator(实战)步骤1:安装HASP Emulator驱动
运行hasp_emulator_v2.33_setup.exe(示例版本),安装内核驱动。步骤2:准备Dump文件
将提取的.dng文件复制到C:\Program Files (x86)\HASP Emulator\Dumps\。步骤3:配置模拟器
编辑emulator.ini:ini
EnableLog=1LogFile=c:\haspemu.logDumpFile=my_license.dng
步骤4:重启计算机(驱动加载)。步骤5:运行目标软件。
模拟器拦截HASP HL的USB请求,根据Dump文件返回数据。软件认为Dongle存在。步骤6:查看日志
分析haspemu.log,确认所有API调用都被正确处理。6.5 无法提取Dump时的应对如果没有合法Dongle或无法提取完整Dump(如Dongle加密区不可读),黑客可以使用“穷举响应法”:用真实Dongle配合软件运行,记录所有USB通信的挑战-响应对,然后编写自定义模拟器。这种方法耗时但可行,因为商业软件往往只调用有限数量的查询。第七章 硬件克隆与固件提取7.1 物理攻击的分类当软件保护极其严密、API Hook和协议模拟都无法奏效时,黑客可能转向物理层面的攻击。这些方法需要专业的电子知识和设备,门槛极高。
攻击类型原理设备需求成功率
EEPROM读取直接读取未加密Dongle的存储器编程器(如TL866)★★★★☆(老式Dongle)
微控制器固件提取通过调试接口(JTAG/SWD)读取MCU固件J-Link、FT2232★★★☆☆(需接口未锁)
侧信道攻击分析功耗、电磁辐射推断密钥示波器、EM探头★★☆☆☆(学术级别)
故障注入通过电压/时钟毛刺绕过安全保护故障注入器(如ChipWhisperer)★★☆☆☆(需要大量尝试)
7.2 EEPROM读取(以ROCKEY为例)初代ROCKEY(ROCKEY 1/2/4)使用外置EEPROM(如24C02)存储数据,通过I2C总线连接加密芯片。攻击方法:
[*]打开Dongle外壳,找到EEPROM芯片(通常为8脚SOIC封装)。
[*]使用热风枪拆下芯片,或者用探针夹住引脚。
[*]连接编程器(如TL866II Plus),选择对应芯片型号(如24C02)。
[*]读取全部256字节数据。
[*]将数据写入一个空白芯片,替换原芯片——Dongle被物理克隆。
防御:现代Dongle已将存储器集成到MCU内部,无法直接读取。7.3 JTAG/SWD接口提取许多Dongle使用通用MCU(如STM32F103),出厂时可能未禁用调试接口(SWD)。攻击者:
[*]找到MCU的SWDIO、SWCLK、GND、VCC引脚(查阅芯片数据手册)。
[*]连接J-Link调试器。
[*]使用OpenOCD或STM32CubeProgrammer读取Flash内容。
[*]分析固件,提取密钥和算法。
防御:安全配置应设置RDP(Read Protection)级别2,完全禁用调试接口。但某些厂家忽略了这一步。7.4 实战案例:STM32版Sentinel Dongle的固件提取某国产Dongle基于STM32F103,未设置读保护。攻击流程:
[*]识别芯片型号(激光刻字STM32F103C8T6)。
[*]查找引脚定义:SWDIO(PA13)、SWCLK(PA14)。
[*]飞线连接ST-Link V2调试器。
[*]STM32CubeProgrammer → Connect → Read memory → 保存为firmware.bin。
[*]使用IDA Pro加载firmware.bin(ARM Cortex-M3架构),分析USB处理逻辑和加密算法。
[*]根据算法编写软件模拟器,无需物理Dongle。
第八章 暗扣(Dongleless Patch)——最终极的破解8.1 什么是暗扣暗扣(Dongleless Patch)指完全移除软件中所有对Dongle的依赖,生成一个完全不检查Dongle的可执行文件。这是Dongle破解的最高境界——用户不再需要任何Dongle模拟器或物理设备。暗扣通过以下方式实现:
[*]删除所有调用SP_Login、HaspLogin等函数的代码
[*]将所有条件跳转强制改为始终跳转到成功分支
[*]删除或NOP掉Dongle检查失败时弹出的错误提示
8.2 暗扣的制作流程步骤1:静态分析定位调用点
使用IDA Pro搜索所有对Dongle API的调用(如call dword ptr ),记录每个调用的地址。步骤2:分析函数内部的验证逻辑
每个HaspLogin调用后面通常跟着test eax, eax; jz error。将jz error改为jmp next或nop掉跳转。步骤3:处理返回值依赖
某些函数的返回值被后续代码用于计算(如HaspQuery的响应数据被用于解密后续指令)。此时不能简单跳过,需要模拟响应值。在x64dbg中跟踪:assembly
call HaspQuerytest eax, eaxjnz continue; 错误处理continue:mov ecx, ; 响应值的第一个字节cmp ecx, 0x5A ; 验证响应标志jne error2; 正常执行
暗扣需要:
[*]确保HaspQuery返回SP_SUCCESS。
[*]在response_buffer中填充正确的字节(如0x5A, 0xA5)。
可以通过在调用前修改内存实现:在x64dbg中,在call HaspQuery之前,直接写入缓冲区:text
mov byte ptr , 0x5Amov byte ptr , 0xA5
步骤4:制作补丁
记录所有修改的地址和原始字节,生成二进制补丁文件(.diff或.xdelta),或直接修改原始EXE/DLL。8.3 暗扣脚本自动化对于有数百处Dongle调用的软件,手工patch不现实。黑客使用IDAPython自动化:python
import idautilsimport idc# 遍历所有交叉引用到Dongle APIapi_names = ["SP_Login", "HaspLogin", "HaspQuery"for api in api_names: api_addr = idc.get_name_ea_simple(api) if api_addr == idc.BADADDR: continue # 获取所有调用该API的位置 for xref in idautils.XrefsTo(api_addr, flags=0): call_addr = xref.frm # 找到调用后的条件跳转(通常相隔2-5条指令) addr = call_addr for i in range(10): addr = idc.next_head(addr, idc.get_segm_end(addr)) if idc.print_insn_mnem(addr) == "jz" or idc.print_insn_mnem(addr) == "je": # 将jz改为jmp idc.patch_byte(addr, 0xEB)# jmp short break
第九章 时间破解与计数器绕过9.1 时间限制的攻防很多Dongle内置时钟或计数器,实现“试用期30天”、“使用1000次后失效”等授权模式。时间检查的实现方式:
[*]Dongle内部实时时钟(RTC):软件从Dongle读取当前日期。
[*]首次使用记录:Dongle存储器写入“首次使用时间戳”。
[*]在线时间同步:软件从网络获取时间,与Dongle数据对比。
黑客绕过方法:方法一:系统时间回调
Hook所有获取当前时间的API(GetSystemTime、time、SystemTimeToFileTime),返回一个在有效期内的固定时间。方法二:修改Dongle返回的时间
使用Hook DLL拦截HaspRead(读取Dongle内存)的调用,如果读取的地址是存储时间戳的位置,修改返回值为早期时间。方法三:计数器清零
如果Dongle使用递减计数器,Hook计数器读取函数,始终返回原始最大值。cpp
int WINAPI HaspGetCounter(HANDLE hDongle, DWORD* counter) { *counter = 9999;// 始终返回最大值 return 0;}
9.2 网络时间同步的绕过某些高端Dongle与服务器同步时间,防止本地时间修改。黑客可以:
[*]阻断Dongle与服务器的通信(防火墙、hosts文件)
[*]Hook网络API(send、recv),伪造时间同步响应
第十章 实战案例(一):破解Sentinel SuperPro保护的软件10.1 目标CADApp.exe——一款CAD软件,使用Sentinel SuperPro硬件锁。无锁则显示“License not found”。10.2 分析使用PEiD查看,无壳。IDA加载,搜索字符串License not found。找到引用地址0x00412A30。向上追溯,找到:assembly
00412A00: call ds:SP_GetNumberOfDongles00412A06: test eax, eax00412A08: jz no_dongle00412A0E: call ds:SP_Login00412A14: test eax, eax00412A16: jnz login_ok00412A18: ...no_dongle:00412A30: push offset str_License_not_found
10.3 API Hook(DLL替换法)编写sentinel.dll替换DLL(参考4.2节),将SP_GetNumberOfDongles返回1,SP_Login返回成功。放入软件目录,运行成功。10.4 进阶:制作暗扣使用x64dbg,在00412A00和00412A0E处修改:
[*]将call SP_GetNumberOfDongles改为mov eax, 1; nop; nop;
[*]将jz no_dongle改为nop; nop; nop; nop; nop;(5字节jz改为5个nop)
[*]将call SP_Login改为mov eax, 0; nop; nop;(返回成功)
[*]保存修改到新EXE。
生成的文件不依赖任何DLL和Dongle,可在任意计算机运行。第十一章 实战案例(二):HASP HL的USB嗅探与模拟11.1 目标IndustrialApp.exe——工业控制软件,使用HASP HL 4.33保护。11.2 USB嗅探
[*]安装Virtual USB Analyzer。
[*]启动软件,捕获完整USB通信。
[*]导出日志,发现软件启动了6个feature查询,每个feature有独立的挑战-响应。
11.3 制作HASP Emulator Dump日志中每个查询格式:text
Command: HASP_READFeature ID: 0x1234Offset: 0x00Length: 4Response: 0x5A, 0x5A, 0x00, 0x01
将这些参数填入HASP Emulator的.dng文件生成器。手工创建my_dump.dng:text
ID=0x1234Data_00=5A 5A 00 01Data_04=00 00 00 00...
11.4 模拟运行安装HASP Emulator驱动,复制.dng到Dumps目录,运行软件。软件成功启动。第十二章 实战案例(三):ROCKEY 4的暗扣分析12.1 目标Accounting.exe——财务软件,使用ROCKEY 4(国密算法)。12.2 静态分析IDA加载,搜索ry4_(ROCKY API前缀)。找到:c
int ret = ry4_find();if (ret != 0) exit(1);ret = ry4_login(&handle);if (ret != 0) exit(1);unsigned char query[4 = {0x01, 0x02, 0x03, 0x04};unsigned char response[8;ret = ry4_query(handle, query, 4, response, 8);if (ret != 0) exit(1);if (response[0 != 0xA5) exit(1);if (response[1 != 0x5A) exit(1);
12.3 暗扣制作
[*]删除ry4_find和ry4_login的调用(NOP掉)。
[*]在ry4_query调用前,手动写response缓冲区:
assembly
mov byte ptr , 0xA5mov byte ptr 1], 0x5A
[*]将call ry4_query改为mov eax, 0(模拟成功返回)。
[*]将所有条件跳转的jnz error改为jmp next。
修改后,软件完全不依赖ROCKEY,可复制使用。第十三章 防御建议——如何设计抗破解的Dongle系统如果你是软件开发商,希望利用Dongle保护产品,请遵循以下原则:13.1 设计层面的建议
[*]不要只做一次性验证:在软件的多个关键点(文件保存、导出、打印等)分布Dongle检查,增加暗扣工作量。
[*]使用查询结果解密代码:将部分关键代码(或数据)以加密形式存储在软件中,Dongle返回的响应值作为解密密钥。这样即使绕过验证,缺少正确响应时解密出的代码也是乱码。
[*]将算法放在Dongle内执行:不只是在Dongle中存储数据,而是让Dongle参与核心计算。例如,Dongle内部实现复杂的数学公式,软件将输入传输给Dongle,Dongle返回计算结果。由于Dongle内部算法无法提取,软件无法脱离Dongle独立运行。
[*]使用公钥加密:软件持有公钥,Dongle持有私钥(不可导出)。软件发送随机挑战,Dongle用私钥签名后返回。通过验证签名即可确认Dongle存在,无需存储任何共享密钥。
13.2 对抗API Hook
[*]静态链接Dongle API库:不要使用动态DLL,将厂商库直接编译到EXE中,使DLL替换失效。
[*]动态加载API:使用LoadLibrary和GetProcAddress在运行时获取函数地址,且函数名加密存储,增加定位难度。
[*]多层调用:不直接调用API,而是通过函数指针数组间接调用,使静态分析难以找到调用点。
[*]校验API代码完整性:在运行前计算DLL代码的CRC,与预存值对比,检测是否被Hook。
13.3 对抗模拟器
[*]时间戳验证:在Dongle通信中加入时间戳,模拟器若不更新响应,时间戳错位会被判为非法。
[*]随机挑战值:每次查询使用不同的随机挑战值,使预录的挑战-响应表失效(需要Dongle具备加密引擎实时计算)。
[*]反虚拟机/反调试:在Dongle通信代码周围加入反调试技术,干扰分析。
[*]定期更新Dongle固件:通过在线升级更新Dongle内部的算法和密钥,使模拟器dump过时。
13.4 终极方案:混合保护将Dongle与网络验证、机器码绑定、代码混淆等多种技术结合,形成纵深防御。例如:
[*]第一次激活需要Dongle + 联网注册,生成绑定硬件的激活文件。
[*]软件运行时同时检查Dongle和激活文件的有效性。
[*]关键模块使用虚拟机保护(VMProtect)封装Dongle通信代码。
虽然上述措施仍可被专业黑客逐个击破,但能显著增加破解成本,使大多数破解者知难而退。第十四章 总结本文以超过一万六千字的篇幅,全面深入地讲解了硬件加密锁(Dongle)的破解技术体系。从Dongle的工作原理、分类、API Hook、USB嗅探、模拟器使用、硬件克隆与固件提取,到暗扣制作、时间破解,再到三个完整实战案例和一个防御章节。Dongle保护一度被认为是“无法破解”的,但实践证明,所有Dongle都存在弱点:API可以被Hook,USB通信可以被嗅探和模拟,固件可能被提取,开发者也经常留下漏洞。没有任何硬件锁能提供 100% 的安全性,只能提高攻击成本和时间。对于软件开发者,理解这些破解技术有助于设计更健壮的保护方案;对于安全研究者,掌握Dongle逆向是完整知识体系中不可或缺的一环。后续本系列将继续探讨软件水印、完整性校验与反篡改技术。关键词:硬件加密锁;Dongle;加密狗;黑客;破解软件;USB嗅探;API Hook;模拟器;Sentinel;HASP;ROCKEY;暗扣
页:
[1]