zoukankan      html  css  js  c++  java
  • 游戏外挂编程二之C/C++内联汇编代码和DLL

    合肥程序员群: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,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文件中放入这个函数名称

    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所有,转载请标明出处。
  • 相关阅读:
    django页面分类和继承
    django前端从数据库获取请求参数
    pycharm配置django工程
    django 应用各个py文件代码
    CF. 1428G2. Lucky Numbers(背包DP 二进制优化 贪心)
    HDU. 6566. The Hanged Man(树形背包DP DFS序 重链剖分)
    小米邀请赛 决赛. B. Rikka with Maximum Segment Sum(分治 决策单调性)
    区间树 学习笔记
    CF GYM. 102861M. Machine Gun(主席树)
    2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) (B, D, G, H)
  • 原文地址:https://www.cnblogs.com/egojit/p/3135607.html
Copyright © 2011-2022 走看看