回朔找記憶體地址 (17千字)

看雪資料發表於2015-11-15

雙休日,幹什麼呢?閒著還不如惡搞一下(心理變態)。
把中國遊戲中心的象棋拿來看看,決定破之而後快。
目的,找出表示象棋棋子的記憶體地址.
象棋棋子的表示和其他遊戲裡的經驗值生命值不同,經驗值和生命值是用數值表示的,在記憶體中用值查詢就OK了,但是棋子呢,車用什麼表示?沒人知道。
首先,對軟體進行資源分析,發現棋子的在資源點陣圖中的順序是車馬炮帥士象兵,大概猜測知道(紅或黑)車~兵是用0~6表示。但是記憶體中是0~6的單元多如牛毛,而且還不確定值的存放長度和確切值,想在記憶體中找這些數簡直是大海撈針。
要怎麼辦呢,有一點WINDOWS圖象程式設計的人都知道,要最終畫出圖象,多半要用到BITBLT這個API,如果知道貼棋子時的BITBLT引數就可以用回朔法找到棋子資訊記憶體的指標。什麼?在BITBLT上下斷點就行了?那是不可能的,因為,BITBLT這個API的應用率太高,你的SOFTICE會一直中斷....
於是在W32DASM中找BITBLT函式,找到兩個:
:0041A630 55                      push ebp
:0041A631 8BEC                    mov ebpesp
:0041A633 51                      push ecx
:0041A634 894DFC                  mov dword ptr [ebp-04], ecx
:0041A637 8B4524                  mov eaxdword ptr [ebp+24]
:0041A63A 50                      push eax
:0041A63B 8B4D20                  mov ecxdword ptr [ebp+20]
:0041A63E 51                      push ecx
:0041A63F 8B551C                  mov edxdword ptr [ebp+1C]
:0041A642 52                      push edx
:0041A643 8B4D18                  mov ecxdword ptr [ebp+18]
:0041A646 E835FFFFFF              call 0041A580
:0041A64B 50                      push eax
:0041A64C 8B4514                  mov eaxdword ptr [ebp+14]
:0041A64F 50                      push eax
:0041A650 8B4D10                  mov ecxdword ptr [ebp+10]
:0041A653 51                      push ecx
:0041A654 8B550C                  mov edxdword ptr [ebp+0C]
:0041A657 52                      push edx
:0041A658 8B4508                  mov eaxdword ptr [ebp+08]
:0041A65B 50                      push eax
:0041A65C 8B4DFC                  mov ecxdword ptr [ebp-04]
:0041A65F 8B5104                  mov edxdword ptr [ecx+04]
:0041A662 52                      push edx

* Reference To: GDI32.BitBlt, Ord:0011h
                                  |
:0041A663 FF15C4304600            Call dword ptr [004630C4]
:0041A669 8BE5                    mov espebp
:0041A66B 5D                      pop ebp
:0041A66C C22000                  ret 0020

:00448E78 2B442450                sub eaxdword ptr [esp+50]
:00448E7C 8B4C2450                mov ecxdword ptr [esp+50]
:00448E80 83E80D                  sub eax, 0000000D
:00448E83 99                      cdq
:00448E84 2BC2                    sub eaxedx
:00448E86 C1F801                  sar eax, 01
:00448E89 03C8                    add ecxeax
:00448E8B 8B44244C                mov eaxdword 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 ebpesp
:0041A633 51                      push ecx
:0041A634 894DFC                  mov dword ptr [ebp-04], ecx
:0041A637 8B4524                  mov eaxdword ptr [ebp+24]
:0041A63A 50                      push eax
:0041A63B 8B4D20                  mov ecxdword ptr [ebp+20]
:0041A63E 51                      push ecx(8)
:0041A63F 8B551C                  mov edxdword ptr [ebp+1C]
:0041A642 52                      push edx(7)
:0041A643 8B4D18                  mov ecxdword ptr [ebp+18]
:0041A646 E835FFFFFF              call 0041A580
:0041A64B 50                      push eax(6)
:0041A64C 8B4514                  mov eaxdword ptr [ebp+14]
:0041A64F 50                      push eax(5)
:0041A650 8B4D10                  mov ecxdword ptr [ebp+10]
:0041A653 51                      push ecx(4)
:0041A654 8B550C                  mov edxdword ptr [ebp+0C]
:0041A657 52                      push edx(3)
:0041A658 8B4508                  mov eaxdword ptr [ebp+08]
:0041A65B 50                      push eax(2)
:0041A65C 8B4DFC                  mov ecxdword ptr [ebp-04]
:0041A65F 8B5104                  mov edxdword ptr [ecx+04]
:0041A662 52                      push edx(第一個引數)

* Reference To: GDI32.BitBlt, Ord:0011h
                                  |
:0041A663 FF15C4304600            Call dword ptr [004630C4]
:0041A669 8BE5                    mov espebp
: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 edxdword ptr [ebp+24]
:00422E45 52                      push edx;7
:00422E46 8B4520                  mov eaxdword ptr [ebp+20]
:00422E49 50                      push eax;6
:00422E4A 8B4D1C                  mov ecxdword ptr [ebp+1C]
:00422E4D 51                      push ecx;5
:00422E4E 8B5518                  mov edxdword ptr [ebp+18]
:00422E51 52                      push edx;4
:00422E52 8B4514                  mov eaxdword ptr [ebp+14]
:00422E55 50                      push eax;3
:00422E56 8B4D10                  mov ecxdword ptr [ebp+10]
:00422E59 51                      push ecx;2
:00422E5A 8B550C                  mov edxdword ptr [ebp+0C]
:00422E5D 52                      push edx;第一個引數
:00422E5E 8B4D08                  mov ecxdword ptr [ebp+08]
:00422E61 E8CA77FFFF              call 0041A630
看到沒這個就是初始化時呼叫貼棋子的地方!
驗證一下,把Raster運算值改成0,結果,棋子全變黑了.
然後再回朔,為什麼不在這裡斷掉找棋子的記憶體地址呢?
因為還沒看見座標變換的運算啊,因為從拿到棋子引數後
到貼圖必須經過對棋子邏輯座標到顯示器的位置的座標變換
才能貼圖的。
於是繼續回蒴,到了這裡:
:00422BF9 68D6A54A00              push 004AA5D6
:00422BFE 6A00                    push 00000000
:00422C00 8B550C                  mov edxdword ptr [ebp+0C]
:00422C03 81E2FF000000            and edx, 000000FF
:00422C09 8B45C0                  mov eaxdword ptr [ebp-40]
:00422C0C 0FAF9043010000          imul edxdword ptr [eax+00000143]
:00422C13 52                      push edx
:00422C14 8D4DC8                  lea ecxdword ptr [ebp-38]
:00422C17 51                      push ecx
:00422C18 8B55C0                  mov edxdword ptr [ebp-40]
:00422C1B 8B8247010000            mov eaxdword ptr [edx+00000147]
:00422C21 50                      push eax
:00422C22 8B4DC0                  mov ecxdword ptr [ebp-40]
:00422C25 8B9143010000            mov edxdword ptr [ecx+00000143]
:00422C2B 52                      push edx
:00422C2C 8B45C0                  mov eaxdword ptr [ebp-40]
:00422C2F 8B4D14                  mov ecxdword ptr [ebp+14]
:00422C32 0FAF883F010000          imul ecxdword ptr [eax+0000013F]
:00422C39 8B55C0                  mov edxdword ptr [ebp-40]
:00422C3C 8B8237010000            mov eaxdword ptr [edx+00000137]
:00422C42 03C1                    add eaxecx
:00422C44 50                      push eax
:00422C45 8B4DC0                  mov ecxdword ptr [ebp-40]
:00422C48 8B5510                  mov edxdword ptr [ebp+10]
:00422C4B 0FAF913B010000          imul edxdword ptr [ecx+0000013B]
:00422C52 8B45C0                  mov eaxdword ptr [ebp-40]
:00422C55 8B8833010000            mov ecxdword ptr [eax+00000133]
:00422C5B 03CA                    add ecxedx
:00422C5D 51                      push ecx
:00422C5E 8B5508                  mov edxdword ptr [ebp+08]
:00422C61 52                      push edx
:00422C62 8B4DC0                  mov ecxdword ptr [ebp-40]
:00422C65 E8D5000000              call 00422D3F
看到沒,座標變換運算:
:00422C2C 8B45C0                  mov eaxdword ptr [ebp-40]
:00422C2F 8B4D14                  mov ecxdword ptr [ebp+14]
:00422C32 0FAF883F010000          imul ecxdword ptr [eax+0000013F]
:00422C39 8B55C0                  mov edxdword ptr [ebp-40]
:00422C3C 8B8237010000            mov eaxdword ptr [edx+00000137]
:00422C42 03C1                    add eaxecx
[eax+0000013F]是放棋子點陣圖寬的地方, [[ebp-40]+00000137]又
是什麼呢?是左上角的棋子到棋盤邊緣的距離(y軸)。
找到最重要的BITBLT第5個的定址:
:00422C00 8B550C                  mov edxdword ptr [ebp+0C]
:00422C03 81E2FF000000            and edx, 000000FF
:00422C09 8B45C0                  mov eaxdword ptr [ebp-40]
:00422C0C 0FAF9043010000          imul edxdword ptr [eax+00000143]
:00422C13 52                      push edx(第5個引數)
咦?怎麼要先和000000FF AND呢?難道..(後面再說)
不管了,先記下定址:
mov edxdword 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 ebpesp
:00422A92 6AFF                    push FFFFFFFF
:00422A94 685B094600              push 0046095B
:00422A99 64A100000000            mov eaxdword 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 edxdword ptr [ebp-48]
:004229D5 52                      push edx
:004229D6 8B45E8                  mov eaxdword ptr [ebp-18]
:004229D9 50                      push eax
:004229DA 8B4DE8                  mov ecxdword ptr [ebp-18]
:004229DD 6BC90A                  imul ecx, 0000000A
:004229E0 8B55B8                  mov edxdword ptr [ebp-48]
:004229E3 03D1                    add edxecx
:004229E5 8B45B4                  mov eaxdword ptr [ebp-4C]
:004229E8 8A4C1048                mov clbyte ptr [eax+edx+48]
:004229EC 51                      push ecx
:004229ED 8D55D0                  lea edxdword ptr [ebp-30]
:004229F0 52                      push edx
:004229F1 8B4DB4                  mov ecxdword ptr [ebp-4C]
:004229F4 E896000000              call 00422A8F
因為上一步已經記下了最重要的定址:
EBP + C
於是只要回數2個PUSE就行了,由於CALL進去後還PUSH了一個EBP
:004229DA 8B4DE8                  mov ecxdword ptr [ebp-18]
:004229DD 6BC90A                  imul ecx, 0000000A
:004229E0 8B55B8                  mov edxdword ptr [ebp-48]
:004229E3 03D1                    add edxecx
:004229E5 8B45B4                  mov eaxdword ptr [ebp-4C]
:004229E8 8A4C1048                mov clbyte 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 ecxdword ptr [ebp-4C]改成mov ecxdword ptr [eax-4C],執行它!
點開始,生成棋盤棋子---當!WINDOWS的錯誤框預期出現在面前!
馬上對它進行除錯,看ebp的內容,代入[[ebp - 4c] + [ebp - 48] + [ebp - 18] * 11 + 48]
算出地址:0x016a4f00(這個值每臺電腦可能不同)
於是一切搞頂,現在只要找到初始化棋子時的語句就可以了(可以什麼?當
然是胡作非為了,想怎麼改不行!)
於是在0x016a4f00上下斷點,然後執行象棋...
SOFTICE彈出!
一眼就發現初始化棋子的語句了:
:004225AE 8B55FC                  mov edxdword ptr [ebp-04]
:004225B1 C6424807                mov [edx+48], 07
:004225B5 8B45FC                  mov eaxdword ptr [ebp-04]
:004225B8 C6405208                mov [eax+52], 08
:004225BC 8B4DFC                  mov ecxdword ptr [ebp-04]
:004225BF C6415C0C                mov [ecx+5C], 0C
:004225C3 8B55FC                  mov edxdword ptr [ebp-04]
:004225C6 C642660B                mov [edx+66], 0B
:004225CA 8B45FC                  mov eaxdword ptr [ebp-04]
:004225CD C640700A                mov [eax+70], 0A
:004225D1 8B4DFC                  mov ecxdword ptr [ebp-04]
:004225D4 C6417A0B                mov [ecx+7A], 0B
:004225D8 8B55FC                  mov edxdword ptr [ebp-04]
:004225DB C682840000000C          mov byte ptr [edx+00000084], 0C
:004225E2 8B45FC                  mov eaxdword ptr [ebp-04]
:004225E5 C6808E00000008          mov byte ptr [eax+0000008E], 08
:004225EC 8B4DFC                  mov ecxdword ptr [ebp-04]
:004225EF C6819800000007          mov byte ptr [ecx+00000098], 07
:004225F6 8B55FC                  mov edxdword ptr [ebp-04]
:004225F9 C6425409                mov [edx+54], 09
:004225FD 8B45FC                  mov eaxdword ptr [ebp-04]
:00422600 C6809000000009          mov byte ptr [eax+00000090], 09
:00422607 8B4DFC                  mov ecxdword ptr [ebp-04]
:0042260A C6414B0D                mov [ecx+4B], 0D
:0042260E 8B55FC                  mov edxdword ptr [ebp-04]
:00422611 C6425F0D                mov [edx+5F], 0D
:00422615 8B45FC                  mov eaxdword ptr [ebp-04]
:00422618 C640730D                mov [eax+73], 0D
:0042261C 8B4DFC                  mov ecxdword ptr [ebp-04]
:0042261F C681870000000D          mov byte ptr [ecx+00000087], 0D
:00422626 8B55FC                  mov edxdword ptr [ebp-04]
:00422629 C6829B0000000D          mov byte ptr [edx+0000009B], 0D
:00422630 8B45FC                  mov eaxdword ptr [ebp-04]
:00422633 C6404E06                mov [eax+4E], 06
:00422637 8B4DFC                  mov ecxdword ptr [ebp-04]
:0042263A C6416206                mov [ecx+62], 06
:0042263E 8B55FC                  mov edxdword ptr [ebp-04]
:00422641 C6427500                mov [edx+75], 00
:00422645 8B45FC                  mov eaxdword ptr [ebp-04]
:00422648 C6808A00000006          mov byte ptr [eax+0000008A], 06
:0042264F 8B4DFC                  mov ecxdword ptr [ebp-04]
:00422652 C6819E00000006          mov byte ptr [ecx+0000009E], 06
:00422659 8B55FC                  mov edxdword ptr [ebp-04]
:0042265C C6425902                mov [edx+59], 02
:00422660 8B45FC                  mov eaxdword ptr [ebp-04]
:00422663 C6809500000002          mov byte ptr [eax+00000095], 02
:0042266A 8B4DFC                  mov ecxdword ptr [ebp-04]
:0042266D C6415100                mov [ecx+51], 00
:00422671 8B55FC                  mov edxdword ptr [ebp-04]
:00422674 C6425B01                mov [edx+5B], 01
:00422678 8B45FC                  mov eaxdword ptr [ebp-04]
:0042267B C6406505                mov [eax+65], 05
:0042267F 8B4DFC                  mov ecxdword ptr [ebp-04]
:00422682 C6416F04                mov [ecx+6F], 04
:00422686 8B55FC                  mov edxdword ptr [ebp-04]
:00422689 C6427903                mov [edx+79], 03
:0042268D 8B45FC                  mov eaxdword ptr [ebp-04]
:00422690 C6808300000004          mov byte ptr [eax+00000083], 04
:00422697 8B4DFC                  mov ecxdword ptr [ebp-04]
:0042269A C6818D00000005          mov byte ptr [ecx+0000008D], 05
:004226A1 8B55FC                  mov edxdword ptr [ebp-04]
:004226A4 C6829700000001          mov byte ptr [edx+00000097], 01
:004226AB 8B45FC                  mov eaxdword 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騙我們看了這麼久..)
啊..大家有話好說嘛....還是先閃了,水平甚菜,有不當之處還請大蝦們指出:)

相關文章