CRC轉ICS系列教學 by.kkmomo
- 取得連結
- 以電子郵件傳送
- 其他應用程式
CRC轉ICS系列教學 by.kkmomo 發表於永恆血色
雖說我網誌右邊有一區的"楓之谷更新必備"不過貌似沒啥人看...
那我的文筆不太好或者寫得太艱澀...
今天就來分享別人寫的教學文XD
這邊不會整篇考過來,那想看教程的自己點連結進去喔...
2013/07/24 由於舊站已關閉,為了想學習的人只好把文章轉過來了
CRC轉ICS(一)
覺得需要的能力:
★★★★★ 邏輯
★★★★ 程式語法的瞭解
★★★★ 耐心、毅力
★★★ 查找資料
★★★ 經驗
★ 組合語言
所需工具:UCE、有CRCbypass佳
--------------------------------------------------------
一、要先有CRC代碼
--------------------------------------------------------
首先就從 物理無敵CRC 開始說起吧,這應該是數據界的HelloWorld!!!
---------------------------------------------------------
閱讀原文...(展開/收縮)
CRC轉ICS(二)
狀況二:
call dword ptr [reg]
call dword ptr [reg+offset]
諸如此類
---------------------------------------------------------
閱讀原文...(展開/收縮)
CRC轉ICS(三)
狀況三:在同一層往上找不到call ptr
這時要用一些別的方法 - 往下層找或往上層找
這篇先講往下層找,從想改的地方往上
只要看到call即使不是call ptr也進去看一下
call ptr太遠,想縮簡代碼時也可用這方法試找看看
---------------------------------------------------------
閱讀原文...(展開/收縮)
CRC轉ICS(三)-1
雖說我網誌右邊有一區的"楓之谷更新必備"不過貌似沒啥人看...
那我的文筆不太好或者寫得太艱澀...
今天就來分享別人寫的教學文XD
這邊不會整篇考過來,那想看教程的自己點連結進去喔...
2013/07/24 由於舊站已關閉,為了想學習的人只好把文章轉過來了
CRC轉ICS(一)
覺得需要的能力:
★★★★★ 邏輯
★★★★ 程式語法的瞭解
★★★★ 耐心、毅力
★★★ 查找資料
★★★ 經驗
★ 組合語言
所需工具:UCE、有CRCbypass佳
--------------------------------------------------------
一、要先有CRC代碼
--------------------------------------------------------
首先就從 物理無敵CRC 開始說起吧,這應該是數據界的HelloWorld!!!
---------------------------------------------------------
閱讀原文...(展開/收縮)
最簡短的CRC版
[Enable]
00615994:
DB 75 //短程jne跳躍
[Disable]
00615994:
DB 74 //短程je跳躍
常見版本2
[Enable]
00615994:
jne 006159A2 // DB 75 0E 83 4D FC FF
[Disable]
00615994:
je 006159A2 // DB 74 0E 83 4D FC FF
從aob可以看出以上兩個數據是等價的
--------------------------------------------------------
二、找call dword ptr
--------------------------------------------------------
而要如何從CRC轉成ICS
基本上需要有3個地址
(1) ptr基址
(2) 被hook函數地址
(3) call的反回地址
基本形式如:
Addr_0 call dword ptr [Addr_1] : [Addr_2]
Addr_3 ***any code***
(1)=Addr_1
(2)=Addr_2
(3)=Addr_3
一般來說只要"往前"找到call dword ptr,(3)便可知
至於(1)、(2)通常都要用一些手段來得到
這數據往前多看兩行,就發現了!!
0061598C - FF 15 8C5EE200 - call dword ptr [00E25E8C] : [IsRectEmpty]
00615992 - 85 C0 - test eax,eax
00615994 - 74 0E - je 006159A4
感謝Inndy大大指點,winapi還是用函數名比較好XD
ps.758D0903 = IsRectEmpty,函數名本身即代表起始地址,用哪個都可以
這是最幸運的情況,3個願望一次滿足
(1)=Addr_1=00E25E8C
(2)=Addr_2=IsRectEmpty
(3)=Addr_3=00615992
--------------------------------------------------------
三、改寫
--------------------------------------------------------
3個地址都有了,那麼該如何改寫成ICS呢?
基本形如下:
CheckEsp:自定函數名
Size:大小
FunName:自定標籤名
[Enable]
Alloc(CheckEsp,Size)
Label(FunName)
CheckEsp:
cmp [esp],Addr_3 //看返回地點是不是我們要的
jne Addr_2 //不是則跳回原函數
mov [esp],FunName //將反迴值改成自己的函數
jmp Addr_2 //改變反迴值後一樣跳回原函數
FunName:
***copy code*** //把 [call dword ptr 下一行] 到 [je 006159A4] 之間的code複製過來
jne 006159A2 //從crc [enable]中copy過來
Addr_1:
DD CheckEsp
[Disable]
Addr_1:
DD Addr_2
DeAlloc(CheckEsp)
--------------------------------------------------------
成果如下
[Enable]
Alloc(CheckEsp,32)
Label(PGod)
CheckEsp:
cmp [esp],00615992
jne IsRectEmpty
mov [esp],PGod
jmp IsRectEmpty
PGod:
test eax,eax
jne 006159A2
00E25E8C:
DD CheckEsp
[Disable]
00E25E8C:
DD IsRectEmpty
DeAlloc(CheckEsp)
理解程式碼後可再自行縮減精簡代碼
CRC轉ICS(二)
狀況二:
call dword ptr [reg]
call dword ptr [reg+offset]
諸如此類
---------------------------------------------------------
閱讀原文...(展開/收縮)
這次以黑暗無敵為例
CRC
[enable]
008EF8FD:
DB 84
[disable]
008EF8FD:
DB 85
寫法2
[enable]
008EF8FC:
je 008F1EB9 //DB 0F 84 B7 25 00 00
[disable]
008EF8FC:
jne 008F1EB9 //DB 0F 85 B7 25 00 00
這也是等價的寫法
當然也不是只有這兩種表示表
---------------------------------------------------------
008EF8F3 - 8B 06 - mov eax,[esi]
008EF8F5 - 8B CE - mov ecx,esi
008EF8F7 - FF 50 18 - call dword ptr [eax+18]
008EF8FA - 85 C0 - test eax,eax
008EF8FC - 0F85 B7250000 - jne 008F1EB9
008EF902 - 8B 86 18450000 - mov eax,[esi+00004518]
也是往前兩行就發現call dword ptr
但括號裡卻是"eax+18"!!
這該死的"eax+18"值要如何得知呢!
方法也不少種
方法一:
可以利用CE內建的功能查找(我是用CE6.2)
在008EF8F7行,右鍵→"Find out what addresses this instruction accesses"
跳出個小視窗,CE會列出這行所訪問到的地址
在這個例子中剛好只找到一個,找到後就可以點Stop
如圖
Address欄 00C8A16C=eax+18
Value 欄 00931AC9=[00C8A16C]=[eax+18]
針對每個找到的地址可以更進一步查看各reg的值及stack的狀態
這下關鍵的3個地址又都有了,接下來做如同前,不再多作說明
---------------------------------------------------------
方法二:
如果沒有如方法一這類強大的功能,只好自己人工設斷點來查看
在call dword ptr前後找合適的地方jmp
寫法很多種,要看你想得到哪些資訊
以單純得到eax值的話,舉個例:
//get eax value at 008EF8F7
[enable]
RegisterSymbol(GetEAX) //註1
Alloc(GetEAX,4)
Alloc(MyBreak,32)
008EF8F7:
jmp MyBreak //在想要知道eax的地方,強制轉跳到自己的函數
MyBreak:
mov [GetEAX],eax //將eax值保存到自定的位置
call dword ptr [eax+18] //註2
test eax,eax
jmp 008EF8FC
[disable]
008EF8F7:
call dword ptr [eax+18]
test eax,eax
UnRegisterSymbol(GetEAX)
DeAlloc(GetEAX,4)
DeAlloc(MyBreak)
/*
註1:
註冊GetEAX是方便用"goto address"時
只要輸入GetEAX就能轉跳到保存位置查看
*/
/*
註2:
不要忘了,做完自己想做的事後
把原本沒執行到的程式碼補上
再轉跳回原程式
不然99%會一enable遊戲就掛掉
儘可能不要改動到原來的程式碼
除非你知道會有什麼後果
能在你掌控之中
不過有時需要錯誤嘗試法
看看會有什麼效果就另當別論
*/
寫累了 先告一個段落
---------------------------------------------------------
CRC轉ICS(三)
狀況三:在同一層往上找不到call ptr
這時要用一些別的方法 - 往下層找或往上層找
這篇先講往下層找,從想改的地方往上
只要看到call即使不是call ptr也進去看一下
call ptr太遠,想縮簡代碼時也可用這方法試找看看
---------------------------------------------------------
閱讀原文...(展開/收縮)
有時ICS會看到像
cmp [esp+10],004EC3AC
cmp [esp+offset],addr
大多數都是[esp],至於後面的+offset怎麼來的
先簡單說明一下esp是在幹麻的
esp : extended stack pointer
為32位元堆疊指位器
esp永遠指著堆疊的頂端
32位元中每push一個,esp值就會-4
反之,每pop一個,esp值就會+4
呼叫call指令時,會將call的下一行位址push到堆疊中
以ret離開副程式後會自動pop掉
===================
舉個簡單的例子
在00401000呼叫讓eax=0的副程式
----堆疊區狀態----
00281000 00000003
00280FFC 00000456
00280FF8 00000789 ←esp
00280FF4 00000442
----堆疊區狀態----
----程式區----
00401000 call 10000000
00401005 test eax,eax
…
10000000 xor eax,eax
10000002 ret
----程式區----
===================
call 10000000
EIP=00401000
esp=00280FF8
[esp]=789
00281000 00000003
00280FFC 00000456
00280FF8 00000789 ←esp
00280FF4 00000442
===================
xor eax,eax
EIP:10000000
esp=00280FF4
[esp]=00401005
00281000 00000003
00280FFC 00000456
00280FF8 00000789
00280FF4 00401005 ←esp
===================
ret
EIP:10000002
esp=00280FF4
[esp]=00401005
00281000 00000003
00280FFC 00000456
00280FF8 00000789
00280FF4 00401005 ←esp
===================
test eax,eax
EIP:00401005
esp=00280FF8
[esp]=00000789
00281000 00000003
00280FFC 00000456
00280FF8 00000789 ←esp
00280FF4 00401005
===================
詳細說明看書比較快XD
google一下應該也很多教學網站寫得比我清楚
這方面我就不再多廢話了,請看範例
--------------------------------------------------------
這次以物品定位為例,一時想不到有什麼比較短的實例,又懶得自己亂掰XD
CRC
[enable]
004EC443:
DB 90 90
[disable]
004EC443:
DB 75 4F
--------------------------------------------------------
從004EC443往上看,可以看到好幾個call
但我只找圈起來的那幾個
原因為在虛線中的區段可能會因je、jne的關係不一定會執行到
要怎麼先簡單過慮,就要看je、jne、jmp等會改變流程的指令
首先由下往上找call,採用深度優先搜尋法 - DFS(Depth-First-Search)
即一看到call就先進到下一層去,進去後是往下找,直到碰到ret反回上一層,再往上找下一個call
如果call裡面還有call就再跟進下一層,如此反覆找到call ptr為止
(level 0)
第1個(level 1)
004EC3DC - E8 B4F3FFFF - call 004EB795
裡面雖然還有一個call但在不一定會執行到,先不考慮,反回上層繼續
第2個(level 1)
004EC3D2 - E8 EEEDFFFF - call 004EB1C5
也沒發現,再下一個
第3個(level 1)
004EC3B8 - E8 559F4600 - call 00956312
也沒有,再下一個
第4個(level 1)
004EC3A7 - E8 B0F2FFFF - call 004EB65C
雖然沒有call ptr,但有沒在虛線中的call
從第一個call 004EB62E開始
第4-1個(level 2)
004EB65F - E8 CAFFFFFF - call 004EB62E
終於發現了,感動T_T
找到call ptr後,eax+04用上一篇的法方找就可以
但改ICS的方法略有不同
004EB639 - FF 50 04 - call dword ptr [eax+04]
004EB63C - 84 C0 - test al,al
原本找到call ptr後我們的返回值會是他的下一行004EB63C
但這裡不是我們原本的那層,而是進了兩層call之後的
我們要的返回值是要在level 0的,而offset要多少才會是我們要的呢
這就要先回到level 0來看
把相關的代碼複製過來
實際上只要看會影響到stack變化的esp、ebp、push、pushf、pushad、pop、popf、popad、leave(不知有沒有漏寫XD)
通常只有push跟pop比較會遇到
我們要的返回值是004EC3AC
假設[eax+04]=12345678
ICS最後的形式應該是會寫成
CheckEsp:
cmp [esp+offset],004EC3AC
jne 12345678
mov [esp+offset],MyFunction
jmp 12345678
-----------------------------------------------------------
level 0
004EC3A7 - E8 B0F2FFFF - call 004EB65C
004EC3AC - 85 C0 - test eax,eax
level 1
004EB65C - 56 - push esi
004EB65D - 8B F1 - mov esi,ecx
004EB65F - E8 CAFFFFFF - call 004EB62E
004EB664 - 85 C0 - test eax,eax
level 2
004EB62E - 56 - push esi
004EB62F - 8B B1 B81F0000 - mov esi,[ecx+00001FB8]
004EB635 - 8B 06 - mov eax,[esi]
004EB637 - 8B CE - mov ecx,esi
004EB639 - FF 50 04 - call dword ptr [eax+04]
004EB63C - 84 C0 - test al,al
怎麼算出offset是多少,簡單意示一下
當進到 call dword ptr [eax+04]之後stack的狀態
004EC3AC (by 004EC3A7)←esp+10
esi (by 004EB65C)←esp+0C
004EB664 (by 004EB65F)←esp+08
esi (by 004EB62E)←esp+04
004EB63C (by 004EB639)←esp
每一個差是4 byte
所以可以算得offset=10
關鍵的幾個都有了
剩下的就跟前面做法一樣了
you can do it!!
CRC轉ICS(三)-1
繼續上次的教程
---------------------------------------------------------
閱讀原文...(展開/收縮)
CRC轉ICS(四)
這篇來說說怎麼往上層找
---------------------------------------------------------
閱讀原文...(展開/收縮)div>
話說看到"在次嚴重警告"的公告還蠻無言的
雖然這種事也不是沒看過沒發生過
還是讓人心寒
如果沒有這種小白,
我是很樂意把會的全部分享出來
不過技術是無價的
學得到就是你的
學不起來偷也沒用
比起抓魚給你
不如把你教會如何釣魚
是吧!
其實是希望多栽培黑客
現在小孩潛力無限:)
提外話了
--------------------------------------------------
150.2
這篇來說說怎麼往上層找
這CRC單純只用(一)~(四)的方法還不能轉成ICS,不過是個不錯的教材XD
[ENABLE]
0048B66D:
DB 33 C0 90 90
[DISABLE]
0048B66D:
DB 8B 44 24 04
組語看多了
有時只看到aob也大概知道在幹麻
33 C0 90 90
即
xor eax,eax
nop
nop
啊!這不是重點,繼續下去
--------------------------------------------------
來到memory view的0048B66D
一如既往,往上拉要開始找call ptr或call
What the F***
0048B66D已經是頭了!!
還好叔叔有練過,只shock了0.1秒就想到方法
如果有想到搜尋"call 0048B66D"、"j* 0048B66D"
也不錯,表示你已經對程式的運作方式有感覺了
但通常直接這樣找要一個一個過慮起來很麻煩
運氣好只有幾十個,運氣不好幾百幾千個
大家還記得吧?用call呼叫時,會先把返回地址push到stack中
就先假設這裡也是用某處用call呼叫0048B66D
一定會先push返回值
如果是用jmp類或其他方法的到這就悲劇了,會比較難
所以當執行到這行時
0048B66D - 8B 44 24 04 - mov eax,[esp+04]
你的[esp]就是這副程式結束時要返回的地方,即你要找的上層地址
--------------------------------------------------
這次先說說人工的做法
雖然CE功能強大,但我比較沒在用CE內建的功能
大多都是自己hook
先copy一下會用到的片段
===================
0048B66D - 8B 44 24 04 - mov eax,[esp+04]
0048B671 - 56 - push esi
0048B672 - 8B F1 - mov esi,ecx
===================
[ENABLE]
registersymbol(RetAddr)
Alloc(RetAddr,4)
Alloc(MyHook,64)
0048B66D:
jmp MyHook
MyHook:
//push [RetAddr],[esp] //這樣的想法是沒錯,但語法不對,註1
push eax //我習慣選eax當中間人,先保存原eax值到stack中
mov eax,[esp+04] //註2
mov [RetAddr],eax
pop eax //有push也要記得pop回來,不然crash機會很大
//遠程jmp消耗5個byte,會蓋到的都補回來,再跳回原程式
mov eax,[esp+04]
push esi
jmp 0048B672
[DISABLE]
0048B66D:
mov eax,[esp+04]
push esi
unregistersymbol(RetAddr)
DeAlloc(RetAddr)
DeAlloc(MyHook)
/*
註1:
偷翻一下書(汗)
reg:8、16、32位元通用暫存器其中一個
(AH,AL,BH,BL,CH,DH,CL,AX,BX,CX,DX,SI,DI,BP,SP,EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP)
mem:使用任何標準的記憶體定址模式的一個記體運算元
imm:立即運算元(16進位數字)
segreg:一個16位元的區段暫存器(CS,DS,ES,SS,FS,GS)
mov使用的格式
mov reg,reg
mov mem,reg
mov reg,mem
mov reg16,segreg
mov segreg,reg16
mov reg,imm
mov mem,imm
mov mem16,segreg
mov segreg,mem16
*/
/*
註2:
因為自己多push一個eax所以要多4的偏移量
如果還有其他會影響到stack位置的
也要視情況增減偏移量
*/
--------------------------------------------------
這樣簡單的hook就完成了,再來只要到RetAddr去看上層地址在哪
就能再繼續用(一)~(四)的技巧找下去
不過有時呼叫的也不止一個地方
[RetAddr]可能會一直變動,這只好一一過慮
假設我們不知物理無敵這東西
在網上看的,查資料還不錯
Windows API 首頁
http://tlcheng.twbbs.org/TLCheng/WinAPI/winapi.asp
像是如果要找物理無敵
較單純直接的方法先找winapi
一開始會找跟方格有關 (人、怪、npc等等許多都是用矩形(Rectangle)來計算)
又看似跟怪碰撞有關的
IsRectEmpty、IntersectRect
如果先從IsRectEmpty開始
那麼物理無敵是從哪呼叫IsRectEmpty?
用上述方法可能會得到很多Return Address
因為遊戲中Rect無所不在
要如何過慮,就要把上面的script改寫一下
寫法很多種,看各人習慣XD
假設已經得到一個Return Address但發現不是
或是可能不止要改一個地方時
還是先把那個地址記下
得到mem1、mem2、mem3…
過慮時可能會得到一堆地址
不一定對目前想改的沒用就是那個地址沒用處
也許是在意想不到的地方會發揮作用,可以先留下來
不過這大概是要研發新數據時才需要這麼做
[ENABLE]
registersymbol(RetAddr)
Alloc(RetAddr,4)
Alloc(MyHook,64)
Label(no)
0048B66D:
jmp MyHook
MyHook:
push eax
mov eax,[esp+04]
//一一比較eax,如果是在不要的名單中
//就跳過mov [RetAddr],eax,直接到pop eax
cmp eax,mem1
je no
cmp eax,mem2
je no
cmp eax,mem3
je no
…
mov [RetAddr],eax
no:
pop eax
mov eax,[esp+04]
push esi
jmp 0048B672
[DISABLE]
0048B66D:
mov eax,[esp+04]
push esi
unregistersymbol(RetAddr)
DeAlloc(RetAddr)
DeAlloc(MyHook)
閱讀原文...(展開/收縮)
這裡來教用CE內建功能的做法
首先移到CRC要改的位址004EC443右鍵"Select current function"
它會自動幫你反白整個副程式區塊
雖然有時也有例外要自己判斷
不過大部分都正確
找到副程式的頭後,在該行右鍵"Break and trace instructions"
會跳出的小視窗,一般用預設值就好,或是自己增減最大跟蹤數、加停止條件
OK後會跳出另一個視窗
一開始可能都沒東西,表示還沒有引發事件執行到這區塊
既然名稱叫物品定位,就回遊戲中做一些跟這相關的事
一處發後,CE就會自動幫你紀錄下來
接著從004EC443往上找把+號一個一個打開來看有沒有call ptr
結果發現一個比較近的
004EC3DC - E8 B4F3FFFF - call 004EB795
在上一篇中有提到,因為在level 1中的call直接看不確定會不會執行到所以先不予考慮
如果確定一定會經過的話選擇這個比較佳
不過為了配合上一篇,還是以同一個點來做說明
首先看到
004EC3A7 - E8 B0F2FFFF - call 004EB65C
把他底下的節點展開到要的call ptr就好
然後點004EC3A7看他esp的值
這裡是esp=0028C684
接著點
004EB639 - FF 50 04 - call dword ptr [eax+04]
左邊看到ptr下層的第一個位址006F65B8
右邊看到esp=0028C674及ptr 00C22D88
得到這幾個位址就差不多完工了
offset = [level 0 call的esp] - [call ptr的esp] = 0028C684 - 0028C674 = +10
至於00C22D88及006F65B8,就是ptr的位址
在代碼中是
[disable]
00C22D88:
DD 006F65B8
首先移到CRC要改的位址004EC443右鍵"Select current function"
它會自動幫你反白整個副程式區塊
雖然有時也有例外要自己判斷
不過大部分都正確
找到副程式的頭後,在該行右鍵"Break and trace instructions"
會跳出的小視窗,一般用預設值就好,或是自己增減最大跟蹤數、加停止條件
OK後會跳出另一個視窗
一開始可能都沒東西,表示還沒有引發事件執行到這區塊
既然名稱叫物品定位,就回遊戲中做一些跟這相關的事
一處發後,CE就會自動幫你紀錄下來
接著從004EC443往上找把+號一個一個打開來看有沒有call ptr
結果發現一個比較近的
004EC3DC - E8 B4F3FFFF - call 004EB795
在上一篇中有提到,因為在level 1中的call直接看不確定會不會執行到所以先不予考慮
如果確定一定會經過的話選擇這個比較佳
不過為了配合上一篇,還是以同一個點來做說明
首先看到
004EC3A7 - E8 B0F2FFFF - call 004EB65C
把他底下的節點展開到要的call ptr就好
然後點004EC3A7看他esp的值
這裡是esp=0028C684
接著點
004EB639 - FF 50 04 - call dword ptr [eax+04]
左邊看到ptr下層的第一個位址006F65B8
右邊看到esp=0028C674及ptr 00C22D88
得到這幾個位址就差不多完工了
offset = [level 0 call的esp] - [call ptr的esp] = 0028C684 - 0028C674 = +10
至於00C22D88及006F65B8,就是ptr的位址
在代碼中是
[disable]
00C22D88:
DD 006F65B8
CRC轉ICS(四)
這篇來說說怎麼往上層找
---------------------------------------------------------
閱讀原文...(展開/收縮)div>
話說看到"在次嚴重警告"的公告還蠻無言的
雖然這種事也不是沒看過沒發生過
還是讓人心寒
如果沒有這種小白,
我是很樂意把會的全部分享出來
不過技術是無價的
學得到就是你的
學不起來偷也沒用
比起抓魚給你
不如把你教會如何釣魚
是吧!
其實是希望多栽培黑客
現在小孩潛力無限:)
提外話了
--------------------------------------------------
150.2
這篇來說說怎麼往上層找
這CRC單純只用(一)~(四)的方法還不能轉成ICS,不過是個不錯的教材XD
[ENABLE]
0048B66D:
DB 33 C0 90 90
[DISABLE]
0048B66D:
DB 8B 44 24 04
組語看多了
有時只看到aob也大概知道在幹麻
33 C0 90 90
即
xor eax,eax
nop
nop
啊!這不是重點,繼續下去
--------------------------------------------------
來到memory view的0048B66D
一如既往,往上拉要開始找call ptr或call
What the F***
0048B66D已經是頭了!!
還好叔叔有練過,只shock了0.1秒就想到方法
如果有想到搜尋"call 0048B66D"、"j* 0048B66D"
也不錯,表示你已經對程式的運作方式有感覺了
但通常直接這樣找要一個一個過慮起來很麻煩
運氣好只有幾十個,運氣不好幾百幾千個
大家還記得吧?用call呼叫時,會先把返回地址push到stack中
就先假設這裡也是用某處用call呼叫0048B66D
一定會先push返回值
如果是用jmp類或其他方法的到這就悲劇了,會比較難
所以當執行到這行時
0048B66D - 8B 44 24 04 - mov eax,[esp+04]
你的[esp]就是這副程式結束時要返回的地方,即你要找的上層地址
--------------------------------------------------
這次先說說人工的做法
雖然CE功能強大,但我比較沒在用CE內建的功能
大多都是自己hook
先copy一下會用到的片段
===================
0048B66D - 8B 44 24 04 - mov eax,[esp+04]
0048B671 - 56 - push esi
0048B672 - 8B F1 - mov esi,ecx
===================
[ENABLE]
registersymbol(RetAddr)
Alloc(RetAddr,4)
Alloc(MyHook,64)
0048B66D:
jmp MyHook
MyHook:
//push [RetAddr],[esp] //這樣的想法是沒錯,但語法不對,註1
push eax //我習慣選eax當中間人,先保存原eax值到stack中
mov eax,[esp+04] //註2
mov [RetAddr],eax
pop eax //有push也要記得pop回來,不然crash機會很大
//遠程jmp消耗5個byte,會蓋到的都補回來,再跳回原程式
mov eax,[esp+04]
push esi
jmp 0048B672
[DISABLE]
0048B66D:
mov eax,[esp+04]
push esi
unregistersymbol(RetAddr)
DeAlloc(RetAddr)
DeAlloc(MyHook)
/*
註1:
偷翻一下書(汗)
reg:8、16、32位元通用暫存器其中一個
(AH,AL,BH,BL,CH,DH,CL,AX,BX,CX,DX,SI,DI,BP,SP,EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP)
mem:使用任何標準的記憶體定址模式的一個記體運算元
imm:立即運算元(16進位數字)
segreg:一個16位元的區段暫存器(CS,DS,ES,SS,FS,GS)
mov使用的格式
mov reg,reg
mov mem,reg
mov reg,mem
mov reg16,segreg
mov segreg,reg16
mov reg,imm
mov mem,imm
mov mem16,segreg
mov segreg,mem16
*/
/*
註2:
因為自己多push一個eax所以要多4的偏移量
如果還有其他會影響到stack位置的
也要視情況增減偏移量
*/
--------------------------------------------------
這樣簡單的hook就完成了,再來只要到RetAddr去看上層地址在哪
就能再繼續用(一)~(四)的技巧找下去
不過有時呼叫的也不止一個地方
[RetAddr]可能會一直變動,這只好一一過慮
假設我們不知物理無敵這東西
在網上看的,查資料還不錯
Windows API 首頁
http://tlcheng.twbbs.org/TLCheng/WinAPI/winapi.asp
像是如果要找物理無敵
較單純直接的方法先找winapi
一開始會找跟方格有關 (人、怪、npc等等許多都是用矩形(Rectangle)來計算)
又看似跟怪碰撞有關的
IsRectEmpty、IntersectRect
如果先從IsRectEmpty開始
那麼物理無敵是從哪呼叫IsRectEmpty?
用上述方法可能會得到很多Return Address
因為遊戲中Rect無所不在
要如何過慮,就要把上面的script改寫一下
寫法很多種,看各人習慣XD
假設已經得到一個Return Address但發現不是
或是可能不止要改一個地方時
還是先把那個地址記下
得到mem1、mem2、mem3…
過慮時可能會得到一堆地址
不一定對目前想改的沒用就是那個地址沒用處
也許是在意想不到的地方會發揮作用,可以先留下來
不過這大概是要研發新數據時才需要這麼做
[ENABLE]
registersymbol(RetAddr)
Alloc(RetAddr,4)
Alloc(MyHook,64)
Label(no)
0048B66D:
jmp MyHook
MyHook:
push eax
mov eax,[esp+04]
//一一比較eax,如果是在不要的名單中
//就跳過mov [RetAddr],eax,直接到pop eax
cmp eax,mem1
je no
cmp eax,mem2
je no
cmp eax,mem3
je no
…
mov [RetAddr],eax
no:
pop eax
mov eax,[esp+04]
push esi
jmp 0048B672
[DISABLE]
0048B66D:
mov eax,[esp+04]
push esi
unregistersymbol(RetAddr)
DeAlloc(RetAddr)
DeAlloc(MyHook)
這篇文章死了@@
回覆刪除請問還有相關CRC轉ICS的教學文嗎@@?
最近再用一個 好像需要esp+n 才可以轉ICS
可是找不到相關的文章QQ
連結已修正。
刪除本站教學皆在 http://knowlet3389.blogspot.tw/p/blog-page.html
站點已經禁止註冊,新論壇暫時沒有放資源.想學習但沒有辦法,大大還有備份嗎?
刪除已將內容被分到此
刪除在CRC轉ICS(三)中,原CRC修改內容的位址是:004EC443 但ICS判斷的位址僅到004EC3AC,該如何寫Hook的腳本內容才不會出錯又能實現更改004EC443處的判斷類型
刪除大大...無法展開耶
回覆刪除一展開就跳到javascript:chp3.style.display='block'
我的JAVA壞了?