哇嗚,我寫了一半了。接下來也繼續加油吧 \OwO/
在 Dx03 “hello world” 篇中,有嘗試利用修改檔案將顯示的字串改成其他的字串過 ( Patch )。但是當這個程式有經過壓縮器保護後,我們難以找到原本存放原本字串的位置 ( 通常是 .rdata 區塊 ) 來進行更改。所以想對已經被加殼的程式進行 patch 時,就需要等壓縮器的 EP 跑完後進入 OEP 時,插隊放入可以修改資料的代碼,這樣才能進行修改,俗稱 “code cave”。
原本解壓縮是像這樣 :
EP 開始執行OEP 執行原程式
插入 code cave 後 :
EP 開始執行CodeCave ( 透過修改 jmp )CodeCave 跳回 OEP

既然要做一個內嵌代碼補丁,就得來一個最好有加殼的破解對象。
看看今天要破解的項目吧 : unpackme by ap0x
由於原本的程式在書中與官網的連結掛了,所以我在這邊放上備份的檔案。
https://github.com/Dinlon5566/IT_Reverse_Engineering/tree/main/Dx15
首先利用 x32dbg 來分析這個程式在 EP 後會做甚麼 :

哇 ! 慘了,這個不像之前那個 UPX 可以直接找 popad 來查詢 OEP ( 因為連 pushad 都沒有 )。不過沒有關係,他 call 了 4010E9 的位置,執行進去看看 :

看來它把 4010F5 這個位置移到 EAX 後 call 了 40109B,一樣進去

看起來這邊有比較多東西可以分析,逐行分析看看
40109B : 把 EAX 推到 stack 保存起來,直到 4010BB 取出
40109C : 把剛剛丟進 EAX 的值傳到 EBX
40109E : 計數器設置 154,與 4010AD 一起判斷是在設定一個範圍
4010A3 : 對 EBX 的直指向位置的一個 byte 進行與 44 的 XOR 運算
4010A9 : EBX ++
4010AA : 檢查 ECX 是不是 0
4010AD : 透過 FLAG 確認上行的結果,非 0 就回到 4010A3
根據 40109C 與 40109E 可以判定解碼的範圍 : 40109B +153 ( 第一次也要 -1 ) = 401249
故第一個加密區塊範圍在 4010F5 ~ 401248
? 之後的加密區塊部分有些大同小異,差不多的就不再一行一行解釋 ( 懶 )。
當解密結束後,call 到 4010BD。此時 EAX = 004010F5。

看到了是跟上面很像的加密動作,起始點是 401007,範圍在 7F , XOR 值是 7。
計算出第二個解密區塊是 401007 ~ 401085。
緊接著又繼續下個解密,起始點是 EAX = 004010F5 ( 上面都沒動到 ),範圍是 154,值是11。
計算出第三個解密區塊是 4010F5 ~ 401248。
恩...這範圍似乎有點相似……這不就是剛剛解密的第一個區塊範圍 ! 原來是二次解密呢 !
回到 RET ,下一個指令是 call 401039。這個調用位置是剛剛解密過的第二個區塊。

首先可以看到 又將 EAX 給到 EBX,ECX 設定成 154。
但多了把 EDX 歸零的動作,之後將 EBX 指向位置的資料加上去。大概就是把 4010F5 ~ 401248 的資料全加起來,之後與 401062 行的 31EB8DB0 這個值來比對 ( overflow計算上忽略 ) ,要是不一樣就發出錯誤信息,稱之為 Check sum。
在 0040105D 時 call 了一個 40108A,看看吧

又是解密區塊,這時候 EAX 是 40124A ,他想直接做到 ESI = 00401280。XOR 值是 17。
結束後就跳回401062。

下一行就是比對 check sum,透過 JE 來分出是否有竄改的結局;要是正常就跳到 401083,否則就彈出視窗,解鎖 Bad End 。

繼續看上圖,正常路線該是 jmp 40121E,繼續下去。

看起來這邊就是主程式了,有種柳暗花明的感覺呢。
既然 40121E 就是 OEP 了,那就要特別關注帶我們跳到 OEP 的 401083。
今天就到這邊吧,明天來把 Cave code 打上去 !