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

來源:互聯網
上載者:User
合肥程式員群:49313181。    合肥實名程式員群:128131462 (不願透露姓名和資訊者勿加入)
Q  Q:408365330     E-Mail:egojit@qq.com

上一節我講解了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++中嵌入彙編代碼的方式,主要上就是放在_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,a001417BE  mov         eax,dword ptr [a]      add eax,b001417C1  add         eax,dword ptr [b]      mov b,eax001417C4  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檔案中放入這個函數名稱

def中的代碼是:

; MFCLibrary1.def : 聲明 DLL 的模組參數。LIBRARYEXPORTS    ; 此處可以是顯式匯出    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所有,轉載請標明出處。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.