星际母巢之战1.08b光盘版免CD方法的补充
2025-11-21 21:11:32

最近在逆向星际争霸,偶尔有时候启动游戏时会弹出需要CD-ROM的错误,但是我下载的就是破解版,于是上网找到了破解方法:
星际母巢之战1.08b光盘版免CD方法
改一个字节破解星际争霸母巢之战1.08b的光盘保护

调试看了一下storm.dll文件的1501867A处已经是jmp了,应该没问题才对。
然后看到原文章说要添加注册表路径,原话是这么说的:注册表中的CD盘付改成你的安装盘
于是我改了注册表

1
2
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Blizzard Entertainment\Starcraft]
"StarCD"="C:\\"

测试发现没用。
然后不得不自行调试,设置断点GetDriveTypeA,来到这里

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
int __fastcall sub_468BD0(int a1, int a2)
{
int v4; // eax
char *v5; // ebp
DWORD LogicalDriveStringsA; // eax
char v7; // al
CHAR *v8; // edi
char v9; // al
const CHAR *v10; // esi
int v11; // ecx
int v12; // [esp+78h] [ebp-21Ch] BYREF
int v13; // [esp+7Ch] [ebp-218h] BYREF
int v14; // [esp+80h] [ebp-214h] BYREF
int v15; // [esp+84h] [ebp-210h]
int v16; // [esp+88h] [ebp-20Ch] BYREF
CHAR v17[260]; // [esp+8Ch] [ebp-208h] BYREF
CHAR Buffer[260]; // [esp+190h] [ebp-104h] BYREF

v15 = a1;
if ( dword_655ECC )
return 1;
while ( 1 )
{
if ( Storm_422(aStarcraft, aStarcd, 0, v17, 260) )
{
Storm_503(v17, aInstallExe, 260);
v4 = Storm_266(v17, 1000, 3, &v12);
if ( !v4 )
goto LABEL_9;
if ( a2 )
{
if ( !Storm_268(v12, a2, 0, &v16) )
{
Storm_252(v12);
v4 = 0;
LABEL_9:
if ( v4 )
goto LABEL_27;
goto LABEL_10;
}
Storm_253(v16);
}
v4 = v12;
goto LABEL_9;
}
LABEL_10:
v5 = aInstallExe;
LogicalDriveStringsA = GetLogicalDriveStringsA(0x104u, Buffer);
if ( LogicalDriveStringsA && LogicalDriveStringsA <= 0x104 )
{
if ( aInstallExe[0] == 92 )
{
do
v7 = *++v5;
while ( v7 == 92 );
}
v8 = Buffer;
if ( Buffer[0] )
{
while ( 1 )
{
v9 = *v8;
v10 = v8++;
if ( v9 )
v8 += strlen(v8) + 1;
if ( GetDriveTypeA(v10) == 5 )
break;
LABEL_25:
if ( !*v8 )
goto LABEL_26;
}
Storm_501(v17, v10, 260);
Storm_503(v17, v5, 260);
v4 = Storm_266(v17, 1000, 3, &v13);
if ( v4 )
{
if ( !a2 )
goto LABEL_23;
if ( Storm_268(v13, a2, 0, &v14) )
{
Storm_253(v14);
LABEL_23:
v4 = v13;
}
else
{
Storm_252(v13);
v4 = 0;
}
}
if ( v4 )
goto LABEL_27;
goto LABEL_25;
}
}
LABEL_26:
v4 = 0;
LABEL_27:
dword_655ECC = v4;
if ( v4 )
return 1;
if ( !v15 )
return 0;
if ( !sub_4DE460() ) // 没有CD的错误
{
LOBYTE(v11) = 0;
sub_4DE920(v11);
}
}
}

如今日子好了,直接扔给 AI 分析:
这个函数 sub_468BD0 是一个**“游戏资源定位器”,它的核心功能是查找并打开游戏所需的核心数据文件(很可能是 StarCraft 的 CD-ROM)
它实现了一个非常健壮的搜索逻辑,包括
缓存**、注册表检查蛮力搜索


#详细逻辑分解

这个函数的工作流程可以分为三个主要阶段:

#1. 检查缓存

  • if ( dword_655ECC ) return 1;
  • 函数首先检查一个全局变量 dword_655ECC。这个变量显然是用来缓存上一次的搜索结果的(很可能存储了找到的文件的句柄)。
  • 如果这个值非零(表示“之前已经找到了”),函数会立即返回 1(成功),跳过所有搜索。

#2. 搜索尝试(在一个 while(1) 循环中)

如果缓存为空,它会进入一个无限循环来尝试定位文件。

#尝试 A:注册表/已知路径

  • if ( Storm_422(aStarcraft, aStarcd, 0, v17, 260) )
  • 它首先调用 Storm_422。这个函数很可能查询 Windows 注册表,查找 StarCraft 的“安装路径”或“CD 路径”。
  • 如果找到了路径(例如 "D:"):
    1. Storm_503(v17, aInstallExe, 260);:它将 aInstallExe(“Install.exe”)附加到路径上,v17 现在是 “D:\Install.exe”。
    2. v4 = Storm_266(v17, ... &v12);:它尝试将这个 “Install.exe” 作为数据档案打开Storm_266 可能是 SFileOpenArchive)。
    3. if ( a2 ) { ... Storm_268(...) }:如果参数 a2(一个文件名)被提供了,它会进一步尝试在这个档案中打开那个特定的文件Storm_268 可能是 SFileOpenFileEx)。
    4. 如果全部成功,它会跳转到 LABEL_27

#尝试 B:蛮力搜索 CD-ROM 驱动器

  • 如果 Storm_422(注册表检查)失败了,代码会跳转到 LABEL_10
  • LogicalDriveStringsA = GetLogicalDriveStringsA(...):它调用 Windows API 来获取一个包含所有驱动器号("C:"、"D:"、"E:"…)的列表。
  • while ( 1 ) { ... }:它开始遍历这个驱动器列表。
  • if ( GetDriveTypeA(v10) == 5 )
    • 这是此函数的关键。它调用 GetDriveTypeA 检查当前驱动器是否为 DRIVE_CDROM (类型 5)。
    • 它会跳过所有硬盘、U盘等,只检查 CD/DVD 驱动器
  • 如果找到了一个 CD-ROM 驱动器(例如 "E:"):
    1. Storm_501(v17, v10, 260);:将 "E:" 复制到路径缓冲区。
    2. Storm_503(v17, v5, 260);:将 “Install.exe” 附加到路径上,v17 现在是 “E:\Install.exe”。
    3. 它会重复“尝试 A”中的第 2、3 步:尝试打开 “E:\Install.exe” 并(可选地)在其中查找文件 a2
    4. 如果成功,跳转到 LABEL_27
    5. 如果失败(例如,这不是 StarCraft 的 CD),它会继续 while 循环,检查下一个 CD-ROM 驱动器。

#3. 处理结果(成功或失败)

  • LABEL_27: dword_655ECC = v4;
    • 如果搜索成功,v4 会包含一个有效的文件句柄。这个句柄被保存到全局缓存 dword_655ECC 中,供下次调用时使用。
  • if ( v4 ) return 1;
    • 如果 v4 有效,函数返回 1(成功)。
  • if ( !v15 ) return 0;
    • 如果搜索失败(v4 为 0)并且 v15(即 a1)为 0(这可能是一个“静默模式”标志),函数直接返回 0(失败)。
  • if ( !sub_4DE460() ) { ... }
    • 如果搜索失败且 a1 不为 0(“UI 模式”),它会调用 sub_4DE460sub_4DE920
    • 几乎可以肯定是弹出一个对话框,告诉用户:“请插入 StarCraft CD-ROM”。
    • 用户点击“重试”后,while(1) 循环会重新开始,再次执行整个搜索过程。

所以注册表那里并不是设置盘符,而是Install.exe的位置,也就是游戏目录

1
reg add "HKEY_CURRENT_USER\Software\Blizzard Entertainment\Starcraft" /v StarCD /t REG_SZ /d "C:\game\starcraft" /f /reg:32