下载

逆向破解惠普增霸卡密码验证流程

作者: Petyrma (petyr)
原文链接: https://www.cnblogs.com/petyr/articles/19039113
摘要: 本文逆向分析并复刻了惠普增霸卡(ZBK)的密码存储逻辑,通过分析其 DLL 动态链接库,发现了其简单的异或加密机制,并实现了一个能够直接读取并破解密码的 C++ 小程序。


一、 背景与起因

惠普增霸卡是预装在部分惠普商用电脑上的一款安全管理软件,提供了硬盘保护、开机密码等功能。当需要修改设置时,LocalSet.exe 等程序会要求输入管理员密码。

本次分析的初衷是探讨其密码验证的内部逻辑。通过观察发现,安装目录下的 LocalSet.exeLoginMan.exeLxClient.exe 等多个程序在启动时弹出的密码界面完全相同。这引出两个推论:

  1. 代码复用:多个程序共用一套验证逻辑。
  2. 逻辑外置:验证逻辑很可能封装在某个共享的 DLL 文件中。

二、 逆向分析过程

1. 定位核心逻辑

经过排查,在 PublicFun.dll 中找到了关键函数:CZbkObject::ValidAdminPasswords

2. IDA Pro 伪代码分析

以下是该函数的核心 C++ 伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
BOOL __thiscall CZbkObject::ValidAdminPasswords(CZbkObject *this, char *a2, unsigned int a3) {
unsigned int v4;
int *p_InBuffer;
int InBuffer; // [esp+8h] [ebp-208h] BYREF
int v9; // [esp+Ch] [ebp-204h]

if ( *((_DWORD *)this + 132) == -1 )
CZbkObject::Initial(this);

// 核心步骤 1:从硬盘特定扇区读取加密后的密码
// 偏移量为基地址 + 6410 扇区
CZbkObject::ReadSectors(this, *((_QWORD *)this + 1) + 6410i64, &InBuffer, 1u);

v4 = a3;

// 核心步骤 2:使用固定的密钥进行异或(XOR)解密
InBuffer ^= 0x48414947u; // ASCII: "GIAG"
v9 ^= 0x55414E47u; // ASCII: "GUANG"

p_InBuffer = &InBuffer;

// 核心步骤 3:将用户输入的密码原文(a2) 与解密后的密码进行内存比对
if ( a3 >= 4 ) {
while ( *(_DWORD *)a2 == *p_InBuffer ) {
v4 -= 4;
++p_InBuffer;
a2 += 4;
// ... (后续字节比对逻辑)
}
return 0;
}
// ...
}

3. 验证流程总结

  • 读取位置:密码并非存放在文件中,而是直接写入硬盘物理扇区(基地址 + 6410 偏移)。
  • 加密方式:简单的异或(XOR)加密。
  • 硬编码密钥:使用了两个固定的 4 字节密钥 0x48414947 (“GIAG”) 和 0x55414E47 (“GUANG”)。
  • 安全性:由于密钥硬编码且算法简单,安全性极低。

三、 复现密码读取工具

根据分析逻辑,可以编写一个工具直接从物理硬盘读取并解密密码。

实现思路

  1. 遍历硬盘:通过 DeviceIoControl(控制码 0x72054)找到安装了增霸卡的物理磁盘并获取基地址。
  2. 读取扇区:计算 基地址 + 6410,通过控制码 0x7201C 读取该扇区数据。
  3. 解密输出:使用上述密钥进行异或运算。

C++ 实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <windows.h>
#include <stdio.h>

int main() {
HANDLE hDevice = INVALID_HANDLE_VALUE;
unsigned __int64 baseLBA = 0;
DWORD dwBytesReturned;

// 1. 遍历物理磁盘,获取基地址(LBA)
for (int diskIndex = 0; diskIndex < 20; ++diskIndex) {
char deviceName[50];
sprintf_s(deviceName, sizeof(deviceName), "\\\\.\\PhysicalDrive%d", diskIndex);
hDevice = CreateFileA(deviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

if (hDevice == INVALID_HANDLE_VALUE) continue;

__int64 inBuffer = 0;
BOOL bResult = DeviceIoControl(hDevice, 0x72054, &inBuffer, 8, &inBuffer, 8, &dwBytesReturned, NULL);
if (bResult && inBuffer != 0) {
baseLBA = inBuffer;
printf("Found Zengba Card data on PhysicalDrive%d. Base LBA: %llu\n", diskIndex, baseLBA);
break;
}
CloseHandle(hDevice);
hDevice = INVALID_HANDLE_VALUE;
}

if (baseLBA == 0) {
printf("Error: Could not find a drive with Zengba Card data.\n");
return 1;
}

// 2. 读取存储密码的扇区 (基地址 + 6410)
BYTE sectorBuffer[512] = {0};
DWORD* pBuffer = (DWORD*)sectorBuffer;
unsigned __int64 targetLba = baseLBA + 6410;

pBuffer[0] = (DWORD)targetLba;
pBuffer[1] = (DWORD)(targetLba >> 32);
pBuffer[2] = 1; // 读取1个扇区

BOOL bResult = DeviceIoControl(hDevice, 0x7201C, sectorBuffer, 512, sectorBuffer, 512, &dwBytesReturned, NULL);
if (!bResult) {
printf("Error: Failed to read sector. LastError: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}

// 3. 使用硬编码密钥解密
printf("Decrypting password...\n");
pBuffer[0] ^= 0x48414947u; // "GIAG"
pBuffer[1] ^= 0x55414E47u; // "GUANG"

// 4. 输出结果
printf("\n--- Password Found ---\n");
printf("Password as String: %s\n", (char*)sectorBuffer);
printf("----------------------\n");

CloseHandle(hDevice);
return 0;
}

注意:运行此程序需要管理员权限,且仅针对 ZBK_UEFI_v7 版本测试有效。


四、 总结

惠普增霸卡的验证机制存在明显的设计缺陷:将安全凭证以极弱的加密方式存储在物理扇区中,且密钥硬编码在 DLL 内。这种“隐藏式安全”在逆向分析面前几乎没有防御力。

标签: 逆向工程, IDA Pro, C++, 安全, 还原卡, ZBK, 破解