0%

SiglusEngine 地區限制破解


採用這個引擎的比較有名的就是key跟SAGA PLANETS這兩家公司了。這次以SAGA PLANET做的一個小遊戲為分析對象,遊戲可以免費下載:【はつゆきパズル☆神経衰弱☆】

下載下來的是一個壓縮檔,檔名為 hatsukipuzzle01.zip,直接解壓縮會得到一個資料夾,名字為:はつゆきパズル。其實遊戲必要的只有 はつゆきパズル\StartData\GameData 這個資料夾,直接把GameData資料夾搬到隨便一個地方,執行SiglusEngine.exe即可啟動遊戲。可惜事情沒這麼簡單,直接執行 SiglusEngine.exe,會出現這個視窗:

那用轉區工具啟動如何?經過測試,Locale Emulator 轉日區一樣無效,都會彈出上面那個視窗。於是我使用 OllyDbg 啟動遊戲進行調試,思路很簡單,就是直接對MessageBox函式下斷,然後重新啟動程式,按 F9 繼續執行就會停在這裡:

1
2
3
4
5
6
7
0045DCCF  |.  8D4424 50      LEA EAX,[ESP+50]
0045DCD3 |> 6A 30 PUSH 30
0045DCD5 |. 51 PUSH ECX
0045DCD6 |. 50 PUSH EAX
0045DCD7 |. A1 BCF3B304 MOV EAX,DWORD PTR DS:[4B3F3BC]
0045DCDC |. 50 PUSH EAX
0045DCDD |. FF15 B0D47700 CALL DWORD PTR DS:[<&USER32.MessageBoxW>] ;彈出錯誤訊息

接著我就往上查找,看看有沒有繞過這一段指令的跳轉,很幸運的只有找到一處:

1
2
3
0045DC5A  |.  E8 81F9FFFF    CALL 0045D5E0
0045DC5F |. 84C0 TEST AL,AL
0045DC61 |. 0F85 A9000000 JNZ 0045DD10 ;關鍵跳轉

這裡邏輯很簡單,只要call 0x0045D5E0返回值不為零就跳走,若為零則繼續執行並印出錯誤訊息。既然這樣修改的方式也很簡單,直接把 JNZ 改為 JMP 即可,這樣不管返回值為何都會跳走。於是我們修改指令,並把修改保存到執行檔,之後再直接啟動程式,結果如下:

然而還是無法啟動遊戲,不過仔細一看錯誤訊息跟上次並不相同,於是我們再度使用 OllyDbg 進行調試。這次我們先在上次找到的關鍵跳轉下斷,之後一步一步跟蹤看看問題出在哪裡。依照經驗,通常這些檢查都會在鄰近的地方。剛才的關鍵跳轉(已修改):

1
2
3
4
0045DC5A  |.  E8 81F9FFFF  CALL 0045D5E0
0045DC5F 84C0 TEST AL,AL
0045DC61 E9 AA000000 JMP 0045DD10 ;第一個關鍵跳轉
0045DC66 90 NOP

跳轉目的:

1
2
3
0045DD10  |>  E8 8BFCFFFF CALL 0045D9A0 ;跳到這裡,第一個關鍵跳轉目的
0045DD15 |. 84C0 TEST AL,AL
0045DD17 0F85 E9000000 JNZ 0045DE06 ;第二個關鍵跳轉

看起來很眼熟,我們先不要修改繼續按 F8 跟蹤,結果程式在這裡停了下來,跳出了圖二的錯誤訊息:

1
2
3
4
0045DD9B  |.  6A 30        PUSH 30  ; /Arg1 = 30
0045DD9D |. 8BC6 MOV EAX,ESI ;|
0045DD9F |. 8D4C24 34 LEA ECX,[ESP+34];|
0045DDA3 |. E8 78FA1000 CALL 0056D820 ; \SiglusEngine.0056D820 ;這裡!!

也就是說 SiglusEngine.0056D820 裡面呼叫了MessageBox。我們回到剛剛的 JNZ 發現他剛好有可能跳過呼叫 SiglusEngine.0056D820 的這段程式碼,也就是說這個 JNZ 也是一個關鍵跳轉。

我們同樣改為 JMP,然後保存修改,直接執行程式,又出現一個:

一樣,我們先對圖二的那個關鍵跳轉下斷,然後按F8跟蹤,馬上又找到一個地方:

1
2
3
0045DE06  |>  E8 E5FCFFFF     CALL 0045DAF0 ;第二個關鍵跳轉目的
0045DE0B |. 84C0 TEST AL,AL
0045DE0D |. 0F85 DE000000 JNZ 0045DEF1 ;第三個關鍵跳轉

修改方式一模一樣,這裡不再贅述。為防萬一,我繼續往下找是否還有類似的地方,結果在第三個關鍵跳轉後,這個函式很快的就返回了,看來應該是沒有類似的檢查了。保存修改後直接執行,即可看到第一張圖的遊戲畫面。

整理一下結果可以發現整個地區檢查的邏輯是這樣(C虛擬碼):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void check_location() {
if(!is_japanese_system()) {
...
MessageBox();
...
}
if(!is_japanese_system_language()) {
...
MessageBox();
...
}
if(!is_japan_time_zone()) {
...
MessageBox();
...
}
}

從這裡可以看出來 SiglusEngine 時做了三種檢查地區的方法,之後再來一一分析好了,目標就是把這三種方法寫成像這樣的函式:

1
2
3
bool is_japanese_system();
bool is_japanese_system_language();
bool is_japan_time_zone();

以上~