回朔找記憶體地址 (17千字)
雙休日,幹什麼呢?閒著還不如惡搞一下(心理變態)。
把中國遊戲中心的象棋拿來看看,決定破之而後快。
目的,找出表示象棋棋子的記憶體地址.
象棋棋子的表示和其他遊戲裡的經驗值生命值不同,經驗值和生命值是用數值表示的,在記憶體中用值查詢就OK了,但是棋子呢,車用什麼表示?沒人知道。
首先,對軟體進行資源分析,發現棋子的在資源點陣圖中的順序是車馬炮帥士象兵,大概猜測知道(紅或黑)車~兵是用0~6表示。但是記憶體中是0~6的單元多如牛毛,而且還不確定值的存放長度和確切值,想在記憶體中找這些數簡直是大海撈針。
要怎麼辦呢,有一點WINDOWS圖象程式設計的人都知道,要最終畫出圖象,多半要用到BITBLT這個API,如果知道貼棋子時的BITBLT引數就可以用回朔法找到棋子資訊記憶體的指標。什麼?在BITBLT上下斷點就行了?那是不可能的,因為,BITBLT這個API的應用率太高,你的SOFTICE會一直中斷....
於是在W32DASM中找BITBLT函式,找到兩個:
:0041A630 55 push ebp
:0041A631 8BEC mov ebp, esp
:0041A633 51 push ecx
:0041A634 894DFC mov dword ptr [ebp-04], ecx
:0041A637 8B4524 mov eax, dword ptr [ebp+24]
:0041A63A 50 push eax
:0041A63B 8B4D20 mov ecx, dword ptr [ebp+20]
:0041A63E 51 push ecx
:0041A63F 8B551C mov edx, dword ptr [ebp+1C]
:0041A642 52 push edx
:0041A643 8B4D18 mov ecx, dword ptr [ebp+18]
:0041A646 E835FFFFFF call 0041A580
:0041A64B 50 push eax
:0041A64C 8B4514 mov eax, dword ptr [ebp+14]
:0041A64F 50 push eax
:0041A650 8B4D10 mov ecx, dword ptr [ebp+10]
:0041A653 51 push ecx
:0041A654 8B550C mov edx, dword ptr [ebp+0C]
:0041A657 52 push edx
:0041A658 8B4508 mov eax, dword ptr [ebp+08]
:0041A65B 50 push eax
:0041A65C 8B4DFC mov ecx, dword ptr [ebp-04]
:0041A65F 8B5104 mov edx, dword ptr [ecx+04]
:0041A662 52 push edx
* Reference To: GDI32.BitBlt, Ord:0011h
|
:0041A663 FF15C4304600 Call dword ptr [004630C4]
:0041A669 8BE5 mov esp, ebp
:0041A66B 5D pop ebp
:0041A66C C22000 ret 0020
和
:00448E78 2B442450 sub eax, dword ptr [esp+50]
:00448E7C 8B4C2450 mov ecx, dword ptr [esp+50]
:00448E80 83E80D sub eax, 0000000D
:00448E83 99 cdq
:00448E84 2BC2 sub eax, edx
:00448E86 C1F801 sar eax, 01
:00448E89 03C8 add ecx, eax
:00448E8B 8B44244C mov eax, dword ptr [esp+4C]
:00448E8F 51 push ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00448D01(U)
|
:00448E90 50 push eax
:00448E91 56 push esi
* Reference To: GDI32.BitBlt, Ord:0011h
|
:00448E92 FF15C4304600 Call dword ptr [004630C4]
:00448E98 53 push ebx
:00448E99 57 push edi
我們要的是初始化時繪棋子的那個,是哪個呢?
BITBLT的第8個引數是RASTER運算值,改成00000000的話就是黑的,在HIEW中把它們運算值改了,發現改第一個的時候全都黑了,於是斷定是第一個。
回到第一個看:
:0041A630 55 push ebp
:0041A631 8BEC mov ebp, esp
:0041A633 51 push ecx
:0041A634 894DFC mov dword ptr [ebp-04], ecx
:0041A637 8B4524 mov eax, dword ptr [ebp+24]
:0041A63A 50 push eax
:0041A63B 8B4D20 mov ecx, dword ptr [ebp+20]
:0041A63E 51 push ecx(8)
:0041A63F 8B551C mov edx, dword ptr [ebp+1C]
:0041A642 52 push edx(7)
:0041A643 8B4D18 mov ecx, dword ptr [ebp+18]
:0041A646 E835FFFFFF call 0041A580
:0041A64B 50 push eax(6)
:0041A64C 8B4514 mov eax, dword ptr [ebp+14]
:0041A64F 50 push eax(5)
:0041A650 8B4D10 mov ecx, dword ptr [ebp+10]
:0041A653 51 push ecx(4)
:0041A654 8B550C mov edx, dword ptr [ebp+0C]
:0041A657 52 push edx(3)
:0041A658 8B4508 mov eax, dword ptr [ebp+08]
:0041A65B 50 push eax(2)
:0041A65C 8B4DFC mov ecx, dword ptr [ebp-04]
:0041A65F 8B5104 mov edx, dword ptr [ecx+04]
:0041A662 52 push edx(第一個引數)
* Reference To: GDI32.BitBlt, Ord:0011h
|
:0041A663 FF15C4304600 Call dword ptr [004630C4]
:0041A669 8BE5 mov esp, ebp
:0041A66B 5D pop ebp
:0041A66C C22000 ret 0020
看CALL之前的PUSH,倒數8個,八個引數都出來了
於是看出倒數第3個正是來源點陣圖的左上角座標
知道了這個就可以知道是什麼棋子了,因為棋子的點陣圖
是透過在一張有所有棋子的點陣圖上擷取的。
然後開始回朔,回到上一級呼叫他的地方
* Referenced by a CALL at Addresses:
|:00419FBE , :0041A13C , :0041A1C3 , :0041A1EF , :0041A273
|:0041A29F , :0041A2C8 , :0041A2F1 , :0041B1AC , :0041F89C
|:0041FB46 , :00420018 , :0042296B , :00422A25 , :00422B98
|:00422DEA , :00422E13 , :00422E38 , :00422E61 , :004230C6
|:00431B57 , :004320F8 , :00432121 , :00432146 , :0043216F
這麼多!!
不過看看地址可以看出很多地方是同一個函式呼叫的,其
實只有5~6個函式呼叫了它,於是回朔看看,到達這裡:
:00422E3D 6846006600 push 00660046;8(Raster運算值)
:00422E42 8B5524 mov edx, dword ptr [ebp+24]
:00422E45 52 push edx;7
:00422E46 8B4520 mov eax, dword ptr [ebp+20]
:00422E49 50 push eax;6
:00422E4A 8B4D1C mov ecx, dword ptr [ebp+1C]
:00422E4D 51 push ecx;5
:00422E4E 8B5518 mov edx, dword ptr [ebp+18]
:00422E51 52 push edx;4
:00422E52 8B4514 mov eax, dword ptr [ebp+14]
:00422E55 50 push eax;3
:00422E56 8B4D10 mov ecx, dword ptr [ebp+10]
:00422E59 51 push ecx;2
:00422E5A 8B550C mov edx, dword ptr [ebp+0C]
:00422E5D 52 push edx;第一個引數
:00422E5E 8B4D08 mov ecx, dword ptr [ebp+08]
:00422E61 E8CA77FFFF call 0041A630
看到沒這個就是初始化時呼叫貼棋子的地方!
驗證一下,把Raster運算值改成0,結果,棋子全變黑了.
然後再回朔,為什麼不在這裡斷掉找棋子的記憶體地址呢?
因為還沒看見座標變換的運算啊,因為從拿到棋子引數後
到貼圖必須經過對棋子邏輯座標到顯示器的位置的座標變換
才能貼圖的。
於是繼續回蒴,到了這裡:
:00422BF9 68D6A54A00 push 004AA5D6
:00422BFE 6A00 push 00000000
:00422C00 8B550C mov edx, dword ptr [ebp+0C]
:00422C03 81E2FF000000 and edx, 000000FF
:00422C09 8B45C0 mov eax, dword ptr [ebp-40]
:00422C0C 0FAF9043010000 imul edx, dword ptr [eax+00000143]
:00422C13 52 push edx
:00422C14 8D4DC8 lea ecx, dword ptr [ebp-38]
:00422C17 51 push ecx
:00422C18 8B55C0 mov edx, dword ptr [ebp-40]
:00422C1B 8B8247010000 mov eax, dword ptr [edx+00000147]
:00422C21 50 push eax
:00422C22 8B4DC0 mov ecx, dword ptr [ebp-40]
:00422C25 8B9143010000 mov edx, dword ptr [ecx+00000143]
:00422C2B 52 push edx
:00422C2C 8B45C0 mov eax, dword ptr [ebp-40]
:00422C2F 8B4D14 mov ecx, dword ptr [ebp+14]
:00422C32 0FAF883F010000 imul ecx, dword ptr [eax+0000013F]
:00422C39 8B55C0 mov edx, dword ptr [ebp-40]
:00422C3C 8B8237010000 mov eax, dword ptr [edx+00000137]
:00422C42 03C1 add eax, ecx
:00422C44 50 push eax
:00422C45 8B4DC0 mov ecx, dword ptr [ebp-40]
:00422C48 8B5510 mov edx, dword ptr [ebp+10]
:00422C4B 0FAF913B010000 imul edx, dword ptr [ecx+0000013B]
:00422C52 8B45C0 mov eax, dword ptr [ebp-40]
:00422C55 8B8833010000 mov ecx, dword ptr [eax+00000133]
:00422C5B 03CA add ecx, edx
:00422C5D 51 push ecx
:00422C5E 8B5508 mov edx, dword ptr [ebp+08]
:00422C61 52 push edx
:00422C62 8B4DC0 mov ecx, dword ptr [ebp-40]
:00422C65 E8D5000000 call 00422D3F
看到沒,座標變換運算:
:00422C2C 8B45C0 mov eax, dword ptr [ebp-40]
:00422C2F 8B4D14 mov ecx, dword ptr [ebp+14]
:00422C32 0FAF883F010000 imul ecx, dword ptr [eax+0000013F]
:00422C39 8B55C0 mov edx, dword ptr [ebp-40]
:00422C3C 8B8237010000 mov eax, dword ptr [edx+00000137]
:00422C42 03C1 add eax, ecx
[eax+0000013F]是放棋子點陣圖寬的地方, [[ebp-40]+00000137]又
是什麼呢?是左上角的棋子到棋盤邊緣的距離(y軸)。
找到最重要的BITBLT第5個的定址:
:00422C00 8B550C mov edx, dword ptr [ebp+0C]
:00422C03 81E2FF000000 and edx, 000000FF
:00422C09 8B45C0 mov eax, dword ptr [ebp-40]
:00422C0C 0FAF9043010000 imul edx, dword ptr [eax+00000143]
:00422C13 52 push edx(第5個引數)
咦?怎麼要先和000000FF AND呢?難道..(後面再說)
不管了,先記下定址:
mov edx, dword ptr [ebp+0C]
然後再一路反跳轉回到這裡:
* Referenced by a CALL at Addresses:
|:004229F4 , :00422F78 , :00423193 , :0042323B , :00423FC4
|:00424337 , :004246E1 , :0042483A , :004249D6 , :004271D8
|:004272F3 , :00427316 , :00428444 , :0042947E , :004297A2
|:004297E5 , :00429A6E , :00429A92
|
:00422A8F 55 push ebp
:00422A90 8BEC mov ebp, esp
:00422A92 6AFF push FFFFFFFF
:00422A94 685B094600 push 0046095B
:00422A99 64A100000000 mov eax, dword ptr fs:[00000000]
:00422A9F 50 push eax
:00422AA0 64892500000000 mov dword ptr fs:[00000000], esp
:00422AA7 83EC34 sub esp, 00000034
:00422AAA 894DC0 mov dword ptr [ebp-40], ecx
:00422AAD 837D0800 cmp dword ptr [ebp+08], 00000000
:00422AB1 7505 jne 00422AB8
:00422AB3 E977020000 jmp 00422D2F
還有這麼多?回朔哪個?
沒關係了,因為如果再回朔一次的話很可能已經可以找到讀取
棋子引數的記憶體的指令了。(為什麼?因為已經是時候了,該
做的都做了,還不是讀棋子引數是什麼)
於是從第一個回蒴,到達:
:004229D2 8B55B8 mov edx, dword ptr [ebp-48]
:004229D5 52 push edx
:004229D6 8B45E8 mov eax, dword ptr [ebp-18]
:004229D9 50 push eax
:004229DA 8B4DE8 mov ecx, dword ptr [ebp-18]
:004229DD 6BC90A imul ecx, 0000000A
:004229E0 8B55B8 mov edx, dword ptr [ebp-48]
:004229E3 03D1 add edx, ecx
:004229E5 8B45B4 mov eax, dword ptr [ebp-4C]
:004229E8 8A4C1048 mov cl, byte ptr [eax+edx+48]
:004229EC 51 push ecx
:004229ED 8D55D0 lea edx, dword ptr [ebp-30]
:004229F0 52 push edx
:004229F1 8B4DB4 mov ecx, dword ptr [ebp-4C]
:004229F4 E896000000 call 00422A8F
因為上一步已經記下了最重要的定址:
EBP + C
於是只要回數2個PUSE就行了,由於CALL進去後還PUSH了一個EBP
:004229DA 8B4DE8 mov ecx, dword ptr [ebp-18]
:004229DD 6BC90A imul ecx, 0000000A
:004229E0 8B55B8 mov edx, dword ptr [ebp-48]
:004229E3 03D1 add edx, ecx
:004229E5 8B45B4 mov eax, dword ptr [ebp-4C]
:004229E8 8A4C1048 mov cl, byte ptr [eax+edx+48]
:004229EC 51 push ecx
有點複雜哦,不過CRACK就必須有耐心,耐心看完後知道:
棋子型別描述單元的定址是:
[[ebp - 4c] + [ebp - 48] + [ebp - 18] * 11 + 48]
這麼複雜是正常的,想想看,這麼多棋子,肯定要分幾步才能找到了
現在怎麼辦呢,如果能在這裡設個短點就可以知道ebp的值從而找到
棋子的單元了.
想一想,只要讀不能訪問的記憶體單元就會發生訪存錯誤,程式會被BREAK
呵呵,只要把其中一個語句改成非法的訪存語句就OK了,偶的系統是2000,讀寫小於0x00010000的記憶體是不允許的,會丟擲異常:xxxx指令的xxxxx記憶體不能為讀,於是決定虐待一下它,
用HIEW把mov ecx, dword ptr [ebp-4C]改成mov ecx, dword ptr [eax-4C],執行它!
點開始,生成棋盤棋子---當!WINDOWS的錯誤框預期出現在面前!
馬上對它進行除錯,看ebp的內容,代入[[ebp - 4c] + [ebp - 48] + [ebp - 18] * 11 + 48]
算出地址:0x016a4f00(這個值每臺電腦可能不同)
於是一切搞頂,現在只要找到初始化棋子時的語句就可以了(可以什麼?當
然是胡作非為了,想怎麼改不行!)
於是在0x016a4f00上下斷點,然後執行象棋...
SOFTICE彈出!
一眼就發現初始化棋子的語句了:
:004225AE 8B55FC mov edx, dword ptr [ebp-04]
:004225B1 C6424807 mov [edx+48], 07
:004225B5 8B45FC mov eax, dword ptr [ebp-04]
:004225B8 C6405208 mov [eax+52], 08
:004225BC 8B4DFC mov ecx, dword ptr [ebp-04]
:004225BF C6415C0C mov [ecx+5C], 0C
:004225C3 8B55FC mov edx, dword ptr [ebp-04]
:004225C6 C642660B mov [edx+66], 0B
:004225CA 8B45FC mov eax, dword ptr [ebp-04]
:004225CD C640700A mov [eax+70], 0A
:004225D1 8B4DFC mov ecx, dword ptr [ebp-04]
:004225D4 C6417A0B mov [ecx+7A], 0B
:004225D8 8B55FC mov edx, dword ptr [ebp-04]
:004225DB C682840000000C mov byte ptr [edx+00000084], 0C
:004225E2 8B45FC mov eax, dword ptr [ebp-04]
:004225E5 C6808E00000008 mov byte ptr [eax+0000008E], 08
:004225EC 8B4DFC mov ecx, dword ptr [ebp-04]
:004225EF C6819800000007 mov byte ptr [ecx+00000098], 07
:004225F6 8B55FC mov edx, dword ptr [ebp-04]
:004225F9 C6425409 mov [edx+54], 09
:004225FD 8B45FC mov eax, dword ptr [ebp-04]
:00422600 C6809000000009 mov byte ptr [eax+00000090], 09
:00422607 8B4DFC mov ecx, dword ptr [ebp-04]
:0042260A C6414B0D mov [ecx+4B], 0D
:0042260E 8B55FC mov edx, dword ptr [ebp-04]
:00422611 C6425F0D mov [edx+5F], 0D
:00422615 8B45FC mov eax, dword ptr [ebp-04]
:00422618 C640730D mov [eax+73], 0D
:0042261C 8B4DFC mov ecx, dword ptr [ebp-04]
:0042261F C681870000000D mov byte ptr [ecx+00000087], 0D
:00422626 8B55FC mov edx, dword ptr [ebp-04]
:00422629 C6829B0000000D mov byte ptr [edx+0000009B], 0D
:00422630 8B45FC mov eax, dword ptr [ebp-04]
:00422633 C6404E06 mov [eax+4E], 06
:00422637 8B4DFC mov ecx, dword ptr [ebp-04]
:0042263A C6416206 mov [ecx+62], 06
:0042263E 8B55FC mov edx, dword ptr [ebp-04]
:00422641 C6427500 mov [edx+75], 00
:00422645 8B45FC mov eax, dword ptr [ebp-04]
:00422648 C6808A00000006 mov byte ptr [eax+0000008A], 06
:0042264F 8B4DFC mov ecx, dword ptr [ebp-04]
:00422652 C6819E00000006 mov byte ptr [ecx+0000009E], 06
:00422659 8B55FC mov edx, dword ptr [ebp-04]
:0042265C C6425902 mov [edx+59], 02
:00422660 8B45FC mov eax, dword ptr [ebp-04]
:00422663 C6809500000002 mov byte ptr [eax+00000095], 02
:0042266A 8B4DFC mov ecx, dword ptr [ebp-04]
:0042266D C6415100 mov [ecx+51], 00
:00422671 8B55FC mov edx, dword ptr [ebp-04]
:00422674 C6425B01 mov [edx+5B], 01
:00422678 8B45FC mov eax, dword ptr [ebp-04]
:0042267B C6406505 mov [eax+65], 05
:0042267F 8B4DFC mov ecx, dword ptr [ebp-04]
:00422682 C6416F04 mov [ecx+6F], 04
:00422686 8B55FC mov edx, dword ptr [ebp-04]
:00422689 C6427903 mov [edx+79], 03
:0042268D 8B45FC mov eax, dword ptr [ebp-04]
:00422690 C6808300000004 mov byte ptr [eax+00000083], 04
:00422697 8B4DFC mov ecx, dword ptr [ebp-04]
:0042269A C6818D00000005 mov byte ptr [ecx+0000008D], 05
:004226A1 8B55FC mov edx, dword ptr [ebp-04]
:004226A4 C6829700000001 mov byte ptr [edx+00000097], 01
:004226AB 8B45FC mov eax, dword ptr [ebp-04]
:004226AE C680A100000000 mov byte ptr [eax+000000A1], 00
呵呵,0~6是黑的車馬炮將士象兵7~D是紅的
現在知道上面做座標運算的時候為什麼要用FF來AND了吧,
因為每個棋子的型別只用一個byte來存放,呵呵,這樣如果用值
查詢找一輩子也找不到,這裡還可以發現存放棋子型別不是以
棋子為物件,是以象棋盤上的交叉點來做物件,點上是FF為沒有
棋子,是0~D的話就是各種棋子.
現在大功告成,把所有棋子改成帥!呵呵,爽吧.
不過最後告訴大家,由於中國遊戲中心伺服器只接受棋子移動的資訊,
比如跑2平5,並不接受棋子型別資訊,所以如果你把自己的兵改成車的話,在本地機器上是可以傳送車1進3的命令的,但是到了伺服器就會被認為是兵1進3了,顯然兵是不能進3的,所以被認為是非法指令,馬上被踢!
呵呵,如果能作弊就不敢公開了,被XX就不好了....
(眾怒:TMD騙我們看了這麼久..)
啊..大家有話好說嘛....還是先閃了,水平甚菜,有不當之處還請大蝦們指出:)
相關文章
- 認識各種記憶體地址2020-06-04記憶體
- 動態分配記憶體地址(.NET)2009-04-15記憶體
- 17、python對記憶體的使用2018-01-01Python記憶體
- C語言記憶體地址基礎2014-08-12C語言記憶體
- project中的堆疊記憶體,記憶體地址引用,gc相關問題2018-10-31Project記憶體GC
- 記憶體管理篇——線性地址的管理2022-02-17記憶體
- 指標:存放記憶體地址的變數2024-08-16指標記憶體變數
- 17 種檢視 Linux 實體記憶體的方法2018-11-15Linux記憶體
- 17_buffer_cache記憶體組織結構剖析2014-12-03記憶體
- VB輸入限制的記憶體破解 (2千字)2003-04-28記憶體
- Redis記憶體——記憶體消耗(記憶體都去哪了?)2021-05-20Redis記憶體
- 記憶體_大頁記憶體2016-05-24記憶體
- Java Object.hashCode()返回的是物件記憶體地址?2017-07-14JavaObject物件記憶體
- 不生成core檔案的記憶體越界快速定位方法/記憶體越界定位/地址崩潰定位方法2024-10-16記憶體
- 記憶體管理 記憶體管理概述2020-11-03記憶體
- 【記憶體管理】記憶體佈局2024-06-10記憶體
- 實體記憶體和虛擬記憶體2007-03-05記憶體
- 讓linux下的sqlplus具有回朔功能(轉)2007-08-16LinuxSQL
- 遊戲記憶體對比普通記憶體區別 遊戲記憶體和普通記憶體相差大嗎?2018-06-23遊戲記憶體
- Go:記憶體管理與記憶體清理2020-08-04Go記憶體
- Java的記憶體 -JVM 記憶體管理2018-08-20Java記憶體JVM
- 聊聊 記憶體模型與記憶體序2022-06-16記憶體模型
- iOS 中的 timer 任務(尋找記憶體惡鬼之旅)2018-10-21iOS記憶體
- 記憶體管理篇——實體記憶體的管理2022-02-23記憶體
- 自動共享記憶體管理 自動記憶體管理 手工記憶體管理2017-11-20記憶體
- hashCode竟然不是根據物件記憶體地址生成的?還對記憶體洩漏與偏向鎖有影響?2020-08-05物件記憶體
- linux記憶體管理(一)實體記憶體的組織和記憶體分配2024-06-07Linux記憶體
- CIH 病毒原理的應用――實體記憶體的讀寫 (4千字)2001-07-02記憶體
- 笨辦法學C 練習17:堆和棧的記憶體分配2016-06-01記憶體
- JS中的棧記憶體、堆記憶體2019-02-23JS記憶體
- Java記憶體區域和記憶體模型2019-04-08Java記憶體模型
- 記憶體溢位和記憶體洩露2022-11-30記憶體溢位記憶體洩露
- 直接記憶體和堆記憶體誰快2018-05-30記憶體
- 記憶體分析與記憶體洩漏定位2017-11-03記憶體
- 記憶體洩漏和記憶體溢位2015-07-11記憶體溢位
- JVM 記憶體模型 記憶體分配,JVM鎖2016-05-20JVM記憶體模型
- Linux 記憶體管理:記憶體對映2015-09-24Linux記憶體
- 虛擬記憶體到實體記憶體(32位)2015-01-07記憶體