'遊戲外掛開發之C/C++內聯彙編代碼和DLL'

彙編語言 C語言 Windows BigDataKer 2019-08-06
"

上一節我講解了CE的使用,這一節我講解一下windows下C/C++的在以後外掛編程中會用到的知識,內聯彙編和C++MFC的DLL編寫。這兩個基本知識都是以後外掛中都會用到的,但是不一定是現在的高級語言編寫者都會的知識。我雖然第一個語言是C但是我還是以C#發家的(畢業後一直主打的還是.NET平臺的C#開發)。

1.C/C++中內聯彙編代碼:新建一個windows 控制檯項目代碼如下

#include "stdafx.h"
extern int add(int a,int b);//方法聲明
int main(int argc, _TCHAR* argv[])
{
int re;
re=add(1,3);//調用add方法
printf("%d",re);
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
return 0;
}
int add(int a,int b){
_asm{//彙編代碼塊
mov eax,a
add eax,b
mov b,eax

}
return b;
}

很容易看到在被調用的add方法中嵌入了彙編代碼。不難看出運行結果為4。以下是圖和真相

"

上一節我講解了CE的使用,這一節我講解一下windows下C/C++的在以後外掛編程中會用到的知識,內聯彙編和C++MFC的DLL編寫。這兩個基本知識都是以後外掛中都會用到的,但是不一定是現在的高級語言編寫者都會的知識。我雖然第一個語言是C但是我還是以C#發家的(畢業後一直主打的還是.NET平臺的C#開發)。

1.C/C++中內聯彙編代碼:新建一個windows 控制檯項目代碼如下

#include "stdafx.h"
extern int add(int a,int b);//方法聲明
int main(int argc, _TCHAR* argv[])
{
int re;
re=add(1,3);//調用add方法
printf("%d",re);
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
return 0;
}
int add(int a,int b){
_asm{//彙編代碼塊
mov eax,a
add eax,b
mov b,eax

}
return b;
}

很容易看到在被調用的add方法中嵌入了彙編代碼。不難看出運行結果為4。以下是圖和真相

遊戲外掛開發之C/C++內聯彙編代碼和DLL

通過這個簡單的內聯彙編我相信大家都熟悉了C/C++中嵌入彙編代碼的方式,主要上就是放在_asm{}中。當然這其中的代碼和真正的彙編還是有點區別的。讓我們來看一下反彙編後的代碼:

extern int add(int a,int b);//方法聲明
int main(int argc, _TCHAR* argv[])
{
00143A30 push ebp
00143A31 mov ebp,esp
00143A33 sub esp,0D0h
00143A39 push ebx
00143A3A push esi
00143A3B push edi
00143A3C lea edi,[ebp-0D0h]
00143A42 mov ecx,34h
00143A47 mov eax,0CCCCCCCCh
00143A4C rep stos dword ptr es:[edi]
00143A4E mov eax,dword ptr ds:[0014800Ch]
00143A53 xor eax,ebp
00143A55 mov dword ptr [ebp-4],eax
int re;
re=add(1,3);//調用add方法
00143A58 push 3
00143A5A push 1
00143A5C call add (01411D6h)
00143A61 add esp,8
00143A64 mov dword ptr [re],eax
printf("%d",re);
00143A67 mov esi,esp
00143A69 mov eax,dword ptr [re]
00143A6C push eax
00143A6D push 1458A8h
00143A72 call dword ptr ds:[1492BCh]
00143A78 add esp,8
00143A7B cmp esi,esp
00143A7D call __RTC_CheckEsp (01411E0h)
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
00143A82 mov esi,esp
00143A84 lea eax,[re]
00143A87 push eax
00143A88 push 1458A8h
00143A8D call dword ptr ds:[1492B8h]
00143A93 add esp,8
00143A96 cmp esi,esp
00143A98 call __RTC_CheckEsp (01411E0h)
return 0;
00143A9D xor eax,eax
}

這是main函數反彙編過來的。下面我們看看add函數的反彙編代碼:

int add(int a,int b){
001417A0 push ebp
001417A1 mov ebp,esp
001417A3 sub esp,0C0h
001417A9 push ebx
001417AA push esi
001417AB push edi
001417AC lea edi,[ebp-0C0h]
001417B2 mov ecx,30h
001417B7 mov eax,0CCCCCCCCh
001417BC rep stos dword ptr es:[edi]
_asm{//彙編代碼塊
mov eax,a
001417BE mov eax,dword ptr [a]
add eax,b
001417C1 add eax,dword ptr [b]
mov b,eax
001417C4 mov dword ptr [b],eax

}
return b;
001417C7 mov eax,dword ptr [b]
}

從中可以看出C中內聯彙編和彙編指令還是有點區別的。在main主函數中call add這個就是調用add函數,再往call add前面看,大家可以看到被調用的add參數被從右到左的放到堆棧中去了(彙編基礎知識)。至於add函數的返回值就放到通用寄存器eax中。彙編中函數放回值都是放到eax中,add函數中有這樣一行彙編mov eax,dword ptr [b]。其中 call add後面有add esp,8這個是為了保持堆棧平衡。這是高級語言中我們不需要關注的東西,其它的就不多說了。更多的還是自己去掌握彙編吧,畢竟彙編知識還是比較豐富的,三言兩語講不清。這裡我只是讓大家能看懂大致的脈絡。在外掛編程中我們很多時候是通過內聯彙編去call遊戲線程中的某個方法,例如我們call補金瘡藥或者魔藥的過程,可以實現自動喝藥。這是基本的外掛過程。

2.C++MFC DLL的編寫:從其他語言過來可能不知道C++寫DLL。C++DLL有很多種方式去寫。這裡我就介紹MFC DLL。它最容易上手。DLL的用處是什麼呢??其它用處我就不說了,只說在外掛中什麼作用。在外掛中我們需要進程注入。前面講過,每個程序都有一個自己私有的4G進程空間(32位系統,0x00000000~0x7FFFFFFF空間屬於應用程序的空間,高地址空間是屬於操作系統的),起到保護進程的作用。那麼我們怎麼控制另個一程序呢??這時候我們就要想到將我們的代碼放到被控制的進程空間中去,可是正常情況下,在一個程序中正常情況下是訪問不到另一個程序進程空間的。這時候我們可以用進程注入的方式將我們的DLL注入到遊戲進程空間中去。我比較常用的兩種方式其一是通過WriteProcessMemory的方式直接寫進去,另一種方式是通過鉤子的形式注入。這兩種注入方式在後面的章節中再做介紹。開始去寫一個DLL在項目解決方案上面添加項目(我用的是vs2012).然後選擇C++,在選擇MFC,選擇MFC DLL.在源文件後面添加一個add方法;

int add(int a,int b){
return a+b;
}

然後一步非常重要需要暴露出來。在def文件中放入這個函數名稱

"

上一節我講解了CE的使用,這一節我講解一下windows下C/C++的在以後外掛編程中會用到的知識,內聯彙編和C++MFC的DLL編寫。這兩個基本知識都是以後外掛中都會用到的,但是不一定是現在的高級語言編寫者都會的知識。我雖然第一個語言是C但是我還是以C#發家的(畢業後一直主打的還是.NET平臺的C#開發)。

1.C/C++中內聯彙編代碼:新建一個windows 控制檯項目代碼如下

#include "stdafx.h"
extern int add(int a,int b);//方法聲明
int main(int argc, _TCHAR* argv[])
{
int re;
re=add(1,3);//調用add方法
printf("%d",re);
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
return 0;
}
int add(int a,int b){
_asm{//彙編代碼塊
mov eax,a
add eax,b
mov b,eax

}
return b;
}

很容易看到在被調用的add方法中嵌入了彙編代碼。不難看出運行結果為4。以下是圖和真相

遊戲外掛開發之C/C++內聯彙編代碼和DLL

通過這個簡單的內聯彙編我相信大家都熟悉了C/C++中嵌入彙編代碼的方式,主要上就是放在_asm{}中。當然這其中的代碼和真正的彙編還是有點區別的。讓我們來看一下反彙編後的代碼:

extern int add(int a,int b);//方法聲明
int main(int argc, _TCHAR* argv[])
{
00143A30 push ebp
00143A31 mov ebp,esp
00143A33 sub esp,0D0h
00143A39 push ebx
00143A3A push esi
00143A3B push edi
00143A3C lea edi,[ebp-0D0h]
00143A42 mov ecx,34h
00143A47 mov eax,0CCCCCCCCh
00143A4C rep stos dword ptr es:[edi]
00143A4E mov eax,dword ptr ds:[0014800Ch]
00143A53 xor eax,ebp
00143A55 mov dword ptr [ebp-4],eax
int re;
re=add(1,3);//調用add方法
00143A58 push 3
00143A5A push 1
00143A5C call add (01411D6h)
00143A61 add esp,8
00143A64 mov dword ptr [re],eax
printf("%d",re);
00143A67 mov esi,esp
00143A69 mov eax,dword ptr [re]
00143A6C push eax
00143A6D push 1458A8h
00143A72 call dword ptr ds:[1492BCh]
00143A78 add esp,8
00143A7B cmp esi,esp
00143A7D call __RTC_CheckEsp (01411E0h)
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
00143A82 mov esi,esp
00143A84 lea eax,[re]
00143A87 push eax
00143A88 push 1458A8h
00143A8D call dword ptr ds:[1492B8h]
00143A93 add esp,8
00143A96 cmp esi,esp
00143A98 call __RTC_CheckEsp (01411E0h)
return 0;
00143A9D xor eax,eax
}

這是main函數反彙編過來的。下面我們看看add函數的反彙編代碼:

int add(int a,int b){
001417A0 push ebp
001417A1 mov ebp,esp
001417A3 sub esp,0C0h
001417A9 push ebx
001417AA push esi
001417AB push edi
001417AC lea edi,[ebp-0C0h]
001417B2 mov ecx,30h
001417B7 mov eax,0CCCCCCCCh
001417BC rep stos dword ptr es:[edi]
_asm{//彙編代碼塊
mov eax,a
001417BE mov eax,dword ptr [a]
add eax,b
001417C1 add eax,dword ptr [b]
mov b,eax
001417C4 mov dword ptr [b],eax

}
return b;
001417C7 mov eax,dword ptr [b]
}

從中可以看出C中內聯彙編和彙編指令還是有點區別的。在main主函數中call add這個就是調用add函數,再往call add前面看,大家可以看到被調用的add參數被從右到左的放到堆棧中去了(彙編基礎知識)。至於add函數的返回值就放到通用寄存器eax中。彙編中函數放回值都是放到eax中,add函數中有這樣一行彙編mov eax,dword ptr [b]。其中 call add後面有add esp,8這個是為了保持堆棧平衡。這是高級語言中我們不需要關注的東西,其它的就不多說了。更多的還是自己去掌握彙編吧,畢竟彙編知識還是比較豐富的,三言兩語講不清。這裡我只是讓大家能看懂大致的脈絡。在外掛編程中我們很多時候是通過內聯彙編去call遊戲線程中的某個方法,例如我們call補金瘡藥或者魔藥的過程,可以實現自動喝藥。這是基本的外掛過程。

2.C++MFC DLL的編寫:從其他語言過來可能不知道C++寫DLL。C++DLL有很多種方式去寫。這裡我就介紹MFC DLL。它最容易上手。DLL的用處是什麼呢??其它用處我就不說了,只說在外掛中什麼作用。在外掛中我們需要進程注入。前面講過,每個程序都有一個自己私有的4G進程空間(32位系統,0x00000000~0x7FFFFFFF空間屬於應用程序的空間,高地址空間是屬於操作系統的),起到保護進程的作用。那麼我們怎麼控制另個一程序呢??這時候我們就要想到將我們的代碼放到被控制的進程空間中去,可是正常情況下,在一個程序中正常情況下是訪問不到另一個程序進程空間的。這時候我們可以用進程注入的方式將我們的DLL注入到遊戲進程空間中去。我比較常用的兩種方式其一是通過WriteProcessMemory的方式直接寫進去,另一種方式是通過鉤子的形式注入。這兩種注入方式在後面的章節中再做介紹。開始去寫一個DLL在項目解決方案上面添加項目(我用的是vs2012).然後選擇C++,在選擇MFC,選擇MFC DLL.在源文件後面添加一個add方法;

int add(int a,int b){
return a+b;
}

然後一步非常重要需要暴露出來。在def文件中放入這個函數名稱

遊戲外掛開發之C/C++內聯彙編代碼和DLL

def中的代碼是:

; MFCLibrary1.def : 聲明 DLL 的模塊參數。
LIBRARY
EXPORTS
; 此處可以是顯式導出
add

這樣就將add函數暴露到了DLL外面。這樣在exe中就可以調用了;

exe程序中的調用代碼如下:

// ASMTest.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#pragma comment(lib,"MFCLibrary1.lib")
extern int add(int a,int b);
int main(int argc, _TCHAR* argv[])
{
int re=3;
re=add(1,3);//調用add方法
printf("%d",re);
scanf_s("%d",&re);//純粹為了停頓查看控制檯輸出的結果
return 0;
}
//int add(int a,int b){
//
// _asm{//彙編代碼塊
// mov eax,a
// add eax,b
// mov b,eax
//
// }
// return b;
//}
#pragma comment(lib,"MFCLibrary1.lib")這是其中一種調用方式。別忘了聲明extern int add(int a,int b);否則找不到add方法。
這樣,實現了一個DLL和對DLL的調用。為後面注入DLL做好鋪墊。

作者:egojit

原文:https://www.cnblogs.com/egojit/archive/2013/06/15/3135607.html

"

相關推薦

推薦中...