《鐵甲風暴之黑色戰線》免CD破解手記 (5千字)

看雪資料發表於2002-02-14

《鐵甲風暴之黑色戰線》免CD破解手記
By: bood  E-mail: boodweb@263.net  2002/2/14

  看人家的破文(可不是指人家的文章破),在正式開始前總是有一段講述自己破解這個軟體的原因,至少也要說一下這個軟體的大致功能。這篇文章是我的處女作,當然也不能例外啦:))。有什麼問題還請大蝦們多多指教才是。
  這個遊戲大家應該都聽說過吧,還是目標在幾年前出的,當時還紅過一段時間,那時我朋友買了個光碟版,幾天前他不知哪根經搭錯了,想要聯機對戰,這樣就要兩張光碟,現在還哪兒去搞啊。算了,我自己動手吧,還能增加點經驗值呢。
  破CD嘛,當然先找GetDriveTypeA函式,mk.exe中共有三個地方用到,但是大致結構都一樣,現在僅挑一個地方出來分析(還有兩個地方在004820D3和0048248D):

:00481CED 8A44241C                mov al, byte ptr [esp+1C] ;初始磁碟機代號
:00481CF1 8D4C241C                lea ecx, dword ptr [esp+1C]
:00481CF5 FEC0                    inc al ;下一個磁碟機代號
:00481CF7 51                      push ecx
:00481CF8 88442420                mov byte ptr [esp+20], al

* Reference To: KERNEL32.GetDriveTypeA, Ord:00DFh
                                  |
:00481CFC FF15DC175300            Call dword ptr [005317DC]
:00481D02 83F805                  cmp eax, 00000005 ;光碟機?
:00481D05 754E                    jne 00481D55 ;不是則轉,然後測試下一個磁碟機代號
:004824A7 8DBC249C000000          lea edi, dword ptr [esp+0000009C] ;是光碟機
:004824AE 83C9FF                  or ecx, FFFFFFFF ;以下程式碼在磁碟機代號後面加檔名
:004824B1 33C0                    xor eax, eax

  GetDriveTypeA函式的返回值是這樣的:

#define DRIVE_UNKNOWN    0
#define DRIVE_NO_ROOT_DIR 1
#define DRIVE_REMOVABLE  2 //可移動
#define DRIVE_FIXED      3 //硬碟
#define DRIVE_REMOTE      4
#define DRIVE_CDROM      5 //光碟機
#define DRIVE_RAMDISK    6

  那我們就把cmp eax,5改成cmp eax,3,讓它在第一個硬碟上檢查(一般是C盤),也便於我偽造資料嘛。用softice跟下去會發現加的檔名一處是overmax0.avi,另一處是gen0.avi。不是有三個地方嗎?這個我不知道,反正用光碟啟動時只有兩次出現動畫。把這兩個檔案拷到C盤根目錄,再執行遊戲,兩次動畫順利透過,然後在出現選項介面的時候又跳出來說要光碟。這下可要費力氣了...
  經過一番痛苦的對比跟蹤(就是看插光碟和不插光碟流程有什麼不同),發現系統函式mciSendString的返回值不同,這下搞清楚了,玩遊戲的時候不是還有CD音樂嘛,怎麼早沒想到呢!用MSDN查查mciSendString發現返回0是成功,那我讓它永遠返回0不就行了,為了不讓光碟機受苦,乾脆一了百了,把整個mciSendString函式都給切了,呵呵,夠毒吧。

:00449F28 6A00                    push 00000000
:00449F2A 6800010000              push 00000100
:00449F2F 50                      push eax
:00449F30 51                      push ecx

* Reference To: WINMM.mciSendStringA, Ord:0034h
                                  |
:00449F31 FF158C1A5300            Call dword ptr [00531A8C]
:00449F37 33D2                    xor edx, edx
:00449F39 85C0                    test eax, eax
:00449F3B 0F94C2                  sete dl
:00449F3E 8BC2                    mov eax, edx
:00449F40 C20800                  ret 0008

  把Call dword ptr [00531A8C](就是mciSendString)改成:

83C410 add esp,10
33C0  xor eax,eax
90    nop

  再試試,好用了!不過還要想辦法幹掉硬碟上的那兩個累贅(沒辦法,有客觀原因在:硬碟太小)。在CreateFileA設斷,注意應該先設GetDriveTypeA的斷,攔下來後再設CreateFileA的斷,因為系統好像一直在頻繁的呼叫CreateFileA(要不就是我的機器有問題)。F12跳出後發現:

* Reference To: KERNEL32.CreateFileA, Ord:0031h
                                  |
:004A348A FF1520175300            Call dword ptr [00531720]
:004A3490 8945FC                  mov dword ptr [ebp-04], eax
:004A3493 837DFCFF                cmp dword ptr [ebp-04], FFFFFFFF ;返回值是否是-1?
:004A3497 7523                    jne 004A34BC ;不是-1則轉

... ...

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A3497(C)
|
:004A34BC 8B4DFC                  mov ecx, dword ptr [ebp-04]
:004A34BF 51                      push ecx

* Reference To: KERNEL32.GetFileType, Ord:00EFh
                                  |
:004A34C0 FF1500185300            Call dword ptr [00531800] ;檢查檔案型別
:004A34C6 8945F4                  mov dword ptr [ebp-0C], eax
:004A34C9 837DF400                cmp dword ptr [ebp-0C], 00000000 ;相等則錯誤
:004A34CD 752D                    jne 004A34FC ;不是0則轉

... ...

;下面轉到004A351C就差不多正確了,GetFileType函式倒沒仔細研究過
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A34CD(C)
|
:004A34FC 837DF402                cmp dword ptr [ebp-0C], 00000002
:004A3500 750B                    jne 004A350D
:004A3502 8A4DC8                  mov cl, byte ptr [ebp-38]
:004A3505 80C940                  or cl, 40
:004A3508 884DC8                  mov byte ptr [ebp-38], cl
:004A350B EB0F                    jmp 004A351C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A3500(C)
|
:004A350D 837DF403                cmp dword ptr [ebp-0C], 00000003
:004A3511 7509                    jne 004A351C
:004A3513 8A55C8                  mov dl, byte ptr [ebp-38]
:004A3516 80CA08                  or dl, 08
:004A3519 8855C8                  mov byte ptr [ebp-38], dl

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004A350B(U), :004A3511(C)
|
:004A351C 8B45FC                  mov eax, dword ptr [ebp-04]

  我轉到004A351C的方法是在CreateFileA後的比較那裡插個jmp直接跳到004A3502,即把那裡改成:
* Reference To: KERNEL32.CreateFileA, Ord:0031h
                                  |
:004A348A FF1520175300            Call dword ptr [00531720]
:004A3490 8945FC                  mov dword ptr [ebp-04], eax
:004A3493 E96A000000              jmp 004A3502 ;6A = 4A3502-(4A3493+5) 5是jmp指令本身長度
:004A3498 90                      nop
  全部搞定,清理戰場,把C盤上的兩個avi刪了:))。可以開始對戰了,呵呵!

相關文章