C++程序反編譯筆記(15) 掃雷雷數(shù)代碼識別與修正

分析主繪圖函數(shù)
????主繪圖函數(shù)sub_1002AC3就是簡單調(diào)用了其他函數(shù)而已, 并且, 繪圖函數(shù)只是根據(jù)數(shù)據(jù)顯示圖像, 基本上不會導(dǎo)致程序崩潰. 因此, 可以采用依次注釋掉某個函數(shù), 觀察界面的方法來分析主繪圖函數(shù).
????以下是分析出來的結(jié)果, 注釋掉對應(yīng)的函數(shù)后, 界面上的某個區(qū)域就不再繪制, 看不到了.


重構(gòu)繪制地雷數(shù)的主函數(shù)
????代碼重構(gòu)是反編譯過程中很重要的操作, 它可以讓代碼變得易懂.
????以下是繪制地雷數(shù)的函數(shù)的原始代碼.

????修正該函數(shù)用到了以下重構(gòu)方法:? ??
(1) 重命名. 已知標(biāo)識符(函數(shù), 變量等)的作用, 那么給它一個有意義的名字.?此處重命名了函數(shù), 變量hdca.
(2) 常量替換. 變量v3賦值后保持不變, 那么可以將賦值后的v3當(dāng)作常量. 變量v4由v3賦值, 賦值后也不變, 因此可以使用v3代替v4, 從而減少一個變量.
(3) 首次使用時定義. 一個變量, 在第一次使用它的時候才定義它, 而不是將所有變量都放在函數(shù)開頭定義, 這樣有利于分析變量的作用, 也可以減少函數(shù)的代碼函數(shù).
以下是修正后的代碼


分析調(diào)用函數(shù)
????分析sub_1002752, 一個變量的意義需要通過分析它的賦值和取值的地方來得出. 重構(gòu)后的sub_1002752如下. 可以看到第3個參數(shù)是一個數(shù)組的索引, 因此我給它起名index. 從而可以得出DrawMineCount函數(shù)的v2, v3都與數(shù)組索引有關(guān).


數(shù)組賦值循環(huán)條件錯誤
????要得出v2, v3的具體含義還需要知道那個數(shù)組dword_1005A60的含義. 首先觀察它的定義

????接著, 觀察它的引用(給它賦值和取值的地方). 使用Visual Studio的搜索功能就可以看到所有引用它的地方了. 很幸運(yùn), 只有一處給它賦值, 只有上面提到的那一處使用了它的值. 觀察給它賦值的地方

????顯然, 這里使用了循環(huán)來給數(shù)組dword_1005A60賦值. 但是, 這里循環(huán)的條件錯了. 在exe文件中, dword_1005A60和dword_1005A90是連續(xù)排列的. 而Visual Studio中, 它們卻是兩個變量, 雖然是連著定義, 但是C/C++標(biāo)準(zhǔn)并沒有保證連續(xù)定義的變量會連續(xù)存放. 所以, 這個循環(huán)很可能是死循環(huán).
????根據(jù)這兩個變量的后綴地址 1005A90 和 1005A60, 可以得出:
????1005A90 - 1005A60 = 0x30,
????0x30 ÷ 4 = 12
????所以,?dword_1005A60確實(shí)是12個4字節(jié)的數(shù)組, 至于是不是int類型還不知道. 因而, 把這個循環(huán)的條件改成指定數(shù)量的形式才是正確的. 如下

????v9 可以刪掉了.

順便修復(fù)另一個數(shù)組循環(huán)條件錯誤
????往上看了一個, 還有一個數(shù)組循環(huán)條件錯誤. 修正后如下


修正成果
????再寫下去就太長了, 看一下本次的成果吧.

????本次主要是重構(gòu)了繪制左上地雷數(shù)的代碼, 及修正了兩個數(shù)組循環(huán)錯誤. 第一個數(shù)組循環(huán)錯誤似乎對界面沒什么影響(可能是巧合, 兩個變量正好連續(xù)存放); 但是第二個數(shù)組循環(huán)錯誤就讓界面變得比較好看了, 雷區(qū)的"亂碼"變成了紅旗.