1. 程式人生 > >血戰上海灘尋找英雄血量地址 實現無敵效果

血戰上海灘尋找英雄血量地址 實現無敵效果

這個遊戲很火的,是單機、射擊類遊戲的經典,網上下載地址很多。。。 運行遊戲,CE附加程序 因為血量肯定是一定範圍內的值,所以初始就搜尋1-1000的值,每次收到攻擊時,就搜尋減少的值,未收到攻擊時,就搜尋未改變的值,最後定位到一個地址,然後搜尋什麼改寫了這個地址:
00487769 - 8B 4D 0C - mov ecx,[ebp+0C] 0048776C - 57 - push edi 0048776D - 89 46 0C - mov [esi+0C],eax << 00487770 - D8C9 - fmul st(0),st(1) 00487772 - 89 4E 10 - mov [esi+10],ecx 然後就分析一下eax這個地址怎麼來的,需要靜態分析了,上IDA:
可以看到eax來自函式的第一個引數,那就將這個函式命名為heart_blood,然後檢視該函式的呼叫:
可以看到該函式的呼叫有6處之多,怎麼定位是哪一處呼叫的函式heart_blood呢 比如在OD中可以在函式sub_455EF0處下條件記錄斷點,檢視該處的函式第一個引數的值 依次使用上述方法,最後定位到hero_blood_1+105處是修改血量時呼叫,同時我們發現,因為遊戲介面上最多隻有8顆星,血量值是0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91這八個值之一 有意思的一點是,如果血量是滿血就會發送0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91這八個引數,如果血量是四顆星,那麼就會發送0x5 0x19 0x2d 0x41這四個引數,這不是很奇怪嘛 看一下hero_blood_1的部分虛擬碼:

可以看到英雄的血量就是*((_DWORD *)v1 + 5) + v2++ % 8 * (v12 + 5) ,其中有個%8就是靈感所在,可以猜想如下:如果滿血的話 這裡就會傳入0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91 如果是7顆星就會傳入0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 如果是6顆星就會傳入0x5 0x19 0x2d 0x41 0x55 0x69 而控制這一切的就是while迴圈的條件v2<v15,看上下文 每次進入函式 然後迴圈的時候v2從0開始遞增,所以重點就是v15,猜測如下:如果是滿血,那麼v15應該就是8 如果7顆星那麼v15就是7,以此類推 看一下v15怎麼來的:

通過下斷點測試,v15來自v9,並不是來自v10,而且v15確實像我們猜測的那樣,當有6顆星時,v15就是6,依次類推 繼續往上推倒 v9=v7,v7 = v6 / sub_4331A0((void *)v3) + 0.050000001; 通過除錯發現sub_4331A0((void *)v3)=7 而且通過該函式操作 sp0=0.62500 虛擬碼可能不太準確,直接看彙編吧
通過這段程式碼可以看到,最終影響結果的是[ebp-0x18],如果滿血的話[ebp-0x18]===5.0,這樣fdivr後 sp0=8 當有七顆星時,[ebp-0x18]===4.375,這樣fdivr(4.375/0.625)後 sp0=7,依次類推 重點是[ebp-0x18]怎麼來的 通過 mov ecx, [esi+8] mov eax, [ecx+18h] mov edx, [eax+0F0h] mov eax, [eax+0F4h] mov [ebp+var_20], edx mov [ebp+var_18], eax ; biggest is 5.000 可以看到[ebp-0x18]=[[[esi+8]+0x18]+0xf4] ,這樣將改地址固定為5.000,就可以實現無敵效果了。