为了保证局域网内每个玩家的地图一致,War3在游戏开局前会同步、校验玩家的本地地图。
一、查找本地是否有匹配的地图
通过枚举游戏相关目录查找一样名字的地图文件,代码片段如下:
00C9785B |. 0F1045 14 movups xmm0,dqword ptr ss:[ebp+0x14]
00C9785F |. 57 push edi
00C97860 |. FF75 38 push [arg.13]
00C97863 |. 8B75 08 mov esi,[arg.1]
00C97866 |. 8B7D 2C mov edi,[arg.10]
00C97869 |. 8B5D 30 mov ebx,[arg.11]
00C9786C |. 8945 F8 mov [local.2],eax
00C9786F |. 8B45 34 mov eax,[arg.12]
00C97872 |. 50 push eax ; OUT FullMapFilePath
00C97873 |. 51 push ecx ; 计算SHA-1回调函数
00C97874 |. 8D45 D4 lea eax,[local.11]
00C97877 |. 50 push eax ; OUT SHA-1
00C97878 |. 52 push edx ; 计算Hash回调函数
00C97879 |. 8D45 CC lea eax,[local.13]
00C9787C |. 50 push eax ; OUT MapHash
00C9787D |. 8D45 C4 lea eax,[local.15]
00C97880 |. 50 push eax ; OUT UnkonwBuffer
00C97881 |. 8D45 C8 lea eax,[local.14]
00C97884 |. 50 push eax ; OUT MapFileSize
00C97885 |. 8D45 D0 lea eax,[local.12]
00C97888 |. 50 push eax ; OUT MapName
00C97889 |. 56 push esi ; IN MapFilePath
00C9788A |. 0F1145 E8 movups dqword ptr ss:[ebp-0x18],xmm0 ; 服务器的地图SHA-1
00C9788E |. E8 DDFCFFFF call Warcraft.00C97570
00C97893 |. 83C4 28 add esp,0x28 ; 如果文件找到返回true
00C97896 |. 83F8 01 cmp eax,0x1
00C97899 |. 75 46 jnz short Warcraft.00C978E1
00C9789B |. 8B45 CC mov eax,[local.13]
00C9789E |. 3B45 0C cmp eax,[arg.2] ; 比较hash是否相同
00C978A1 |. 75 3E jnz short Warcraft.00C978E1
00C978A3 |. 8D4D D4 lea ecx,[local.11]
00C978A6 |. BE 10000000 mov esi,0x10 ; SHA-1长度 16个字节
00C978AB |. 8D55 E8 lea edx,[local.6]
00C978AE |. 66:90 nop
00C978B0 |> 8B01 /mov eax,dword ptr ds:[ecx] ; 比较SHA-1
00C978B2 |. 3B02 |cmp eax,dword ptr ds:[edx] ; 服务器的地图SHA-1
00C978B4 |. 75 2B |jnz short Warcraft.00C978E1
00C978B6 |. 83C1 04 |add ecx,0x4
00C978B9 |. 83C2 04 |add edx,0x4
00C978BC |. 83EE 04 |sub esi,0x4
00C978BF |.^ 73 EF \jnb short Warcraft.00C978B0
00C978C1 |. 8B4D D0 mov ecx,[local.12]
00C978C4 |. B8 01000000 mov eax,0x1
00C978C9 |. 890F mov dword ptr ds:[edi],ecx ; MapName
00C978CB |. 8B4D C8 mov ecx,[local.14]
函数原型:
bool __cdecl FindMapFile(IN char *szMapFilePath,
OUT char *szMapName,
OUT int *pMapFileSize,
OUT char *szUnkonwBuffer,
OUT int *MapHash,
OUT pvoid pCalcMapHash,
OUT char *szSHA1,
OUT pvoid pCalcMapSHA1,
OUT char*szFullMapFilePath);
函数如果找到地图了,则返回true后面校验地图是否相同,如果相同则会执行下面的地图校验 ,否则会去执行下载地图操作。
二、校验地图是否为游戏局内地图 (这里的逻辑只有地图文件存在才会去做)
0087EAF6 |. 5B pop ebx ; 0251C320
0087EAF7 |. 8B4D FC mov ecx,[local.1]
0087EAFA |. 33CD xor ecx,ebp
0087EAFC |. E8 D7805300 call Warcraft.00DB6BD8
0087EB01 |. 8BE5 mov esp,ebp
0087EB03 |. 5D pop ebp ; 0251C320
0087EB04 |. C3 retn
0087EB05 |> 0FB643 30 movzx eax,byte ptr ds:[ebx+0x30]
0087EB09 |. 56 push esi
0087EB0A |. 83E0 01 and eax,0x1
0087EB0D |. 6A 00 push 0x0
0087EB0F |. 50 push eax
0087EB10 |. E8 4BFB0800 call Warcraft.0090E660
0087EB15 |. 83C4 08 add esp,0x8
0087EB18 |. F783 48010000>test dword ptr ds:[ebx+0x148],0x200
0087EB22 |. 0F85 CC000000 jnz Warcraft.0087EBF4
0087EB28 |. 68 04010000 push 0x104
0087EB2D |. 8D85 F8FEFFFF lea eax,[local.66]
0087EB33 |. 50 push eax ; OutFullMapFilePath
0087EB34 |. 8D43 54 lea eax,dword ptr ds:[ebx+0x54]
0087EB37 |. 50 push eax ; MapPath
0087EB38 |. E8 03C92700 call Warcraft.00AFB440
0087EB3D |. 83C4 0C add esp,0xC
0087EB40 |. 8D43 40 lea eax,dword ptr ds:[ebx+0x40]
0087EB43 |. 8BCF mov ecx,edi
0087EB45 |. 50 push eax ; SHA-1
0087EB46 |. FF73 3C push dword ptr ds:[ebx+0x3C] ; Map Hash
0087EB49 |. 8B83 48010000 mov eax,dword ptr ds:[ebx+0x148]
0087EB4F |. 25 FF030000 and eax,0x3FF
0087EB54 |. 50 push eax ; 1
0087EB55 |. 8D85 F8FEFFFF lea eax,[local.66]
0087EB5B |. 50 push eax ; MapFilePath
0087EB5C |. E8 9FABF5FF call Warcraft.007D9700 ; CheckMap
0087EB61 |. 85C0 test eax,eax
0087EB63 |. 74 23 je short Warcraft.0087EB88
0087EB65 |. 53 push ebx
0087EB66 |. 8D4F 38 lea ecx,dword ptr ds:[edi+0x38]
0087EB69 |. E8 02A2F4FF call Warcraft.007C8D70
0087EB6E |. 8B77 30 mov esi,dword ptr ds:[edi+0x30]
0087EB71 |. 8B83 44010000 mov eax,dword ptr ds:[ebx+0x144]
0087EB77 |. 8947 48 mov dword ptr ds:[edi+0x48],eax
0087EB7A |. 85F6 test esi,esi
0087EB7C |. 75 1D jnz short Warcraft.0087EB9B
0087EB7E |. 6A 57 push 0x57
这里的CheckMap就是校验本地的地图是否与加入局使用的地图一致
bool WINAPI CheckMap(char *szMapFilePath,int nMode,DWORD dwMapHash,char *szSHA1);
这个函数执行可以被忽略,如果参数中 dwMapHash = 0xFFFFFFFF, szSHA1 = NULL,则直接返回true
PS1.以上代码片段来自于 War3 129版本
PS2.只要过掉这2个地图校验,就可以加载修改版的地图,然而有几率会产生不匹配的错误