qq游戏外挂:游戏外挂设计技术探讨②

4. 例子实现

  通过上面学习我们已经基本具备了编写动作式游戏外挂能力了下面我们将创建个画笔外挂它实现自动移动画笔字光标位置并写下个红色“R”字以这个例子为基础加入相应游戏动作规则就可以实现个完整游戏外挂这里作者不想使用某个游戏作为例子来开发外挂(因没有游戏商家授权啊!)如读者感兴趣话可以找个游戏试试最好仅做测试技术用

  首先我们需要编写个全局钩子使用它来激活外挂激活键为F10创建全局钩子步骤如下:

  (1).选择MFC AppWizard(DLL)创建项目ActiveKey并选择MFC Extension DLL(共享MFC拷贝)类型

  (2).插入新文件ActiveKey.h在其中输入如下代码:

   #ndef _KEYDLL_H
   # _KEYDLL_H

    AFX_EXT_CLASS CKeyHook:public CObject
   {
    public:
 CKeyHook;
 ~CKeyHook;
 HHOOK Start; //安装钩子
 BOOL Stop; //卸载钩子
   };
   #end  

  (3).在ActiveKey.cpp文件中加入声明"# ActiveKey.h"

  (4).在ActiveKey.cpp文件中加入共享数据段代码如下:

   //Shared data section
   #pragma data_seg("sharedata")
   HHOOK glhHook=NULL; //钩子句柄
   HINSTANCE glhInstance=NULL; //DLL例子句柄
   #pragma data_seg  

  (5).在ActiveKey.def文件中设置共享数据段属性代码如下:

   SETCTIONS
   shareddata READ WRITE SHARED

  (6).在ActiveKey.cpp文件中加入CkeyHook类实现代码和钩子代码:

   //键盘钩子处理
   extern "C" LRESULT WINAPI KeyboardProc( nCode,WPARAM wParam,LPARAM lParam)
   {
   ( nCode >= 0 )
   {
   ( wParam 0X79 )//当按下F10键时激活外挂
 {
  //外挂实现代码
CPo Po,oldPo;
   GetCursorPos(&oldPo);
   Po.x = oldPo.x+40;
   Po.y = oldPo.y+10;
   SetCursorPos(Po.x,Po.y);
   mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模拟按下鼠标左键
  mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模拟放开鼠标左键
  keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0); //按下SHIFT键
  keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R键
  keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放开R键
  keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放开SHIFT键
      SetCursorPos(oldPo.x,oldPo.y);
 }
   }
    CallNextHookEx(glhHook,nCode,wParam,lParam);
   }

   CKeyHook::CKeyHook{}
   CKeyHook::~CKeyHook
   { 
   ( glhHook )
Stop;
   }
   //安装全局钩子
   HHOOK CKeyHook::Start
   {
glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//设置键盘钩子
glhHook;
}
   //卸载全局钩子
   BOOL CKeyHook::Stop
   {
   BOOL bResult = TRUE;
 ( glhHook )
   bResult = UnhookWindowsHookEx(glhHook);//卸载键盘钩子
    bResult;
   }  

  (7).修改DllMain代码如下:

   extern "C" APIENTRY
   DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
   {
//如果使用lpReserved参数则删除下面这行
UNREFERENCED_PARAMETER(lpReserved);

(dwReason DLL_PROCESS_ATTACH)
{
  TRACE0("NOtePadHOOK.DLL Initializing!\n");
   //扩展DLL仅
   (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))
0;
   CDynLinkLibrary(ActiveKeyDLL);
      //把DLL加入动态MFC类库中
  glhInstance = hInstance;
  //插入保存DLL例子句柄
}
(dwReason DLL_PROCESS_DETACH)
{
  TRACE0("NotePadHOOK.DLL Terminating!\n");
  //终止这个链接库前
  AfxTermExtensionModule(ActiveKeyDLL);
}
1;
   }

  (8).编译项目ActiveKey生成ActiveKey.DLL和ActiveKey.lib

  接着我们还需要创建个外壳将全局钩子安装了Windows系统中这个外壳编写步骤如下:

  (1).创建个对话框模式应用项目名为Simulate

  (2).在主对话框中加入个按钮使用ClassWizard为其创建CLICK事件

  (3).将ActiveKey项目Debug目录下ActiveKey.DLL和ActiveKey.lib拷贝到Simulate项目目录下

  (4).从“工程”菜单中选择“设置”弹出Project Setting对话框选择Link标签在“对象/库模块”中输入ActiveKey.lib

  (5).将ActiveKey项目中ActiveKey.h头文件加入到Simulate项目中并在Stdafx.h中加入# ActiveKey.h

  (6).在按钮单击事件输入如下代码:

   void CSimulateDlg::OnButton1
   {
// TODO: Add your control notication handler code here
( !bSetup )
{
m_hook.Start;//激活全局钩子
}

{
m_hook.Stop;//撤消全局钩子
}
bSetup = !bSetup;

   }  

  (7).编译项目并运行单击按钮激活外挂

  (8).启动画笔选择文本工具并将笔颜色设置为红色将鼠标放在任意位置后按F10键画笔自动移动鼠标并写下个红色大写R展示了按F10键前画笔状态图 2展示了按F10键后画笔状态


:按F10前状态(001.jpg)


图 2:按F10后状态(002.jpg)
   5、封包技术

  通过对动作模拟技术介绍我们对游戏外挂有了定程度上认识也学会了使用动作模拟技术来实现简单动作模拟型游戏外挂制作这种动作模拟型游戏外挂有局限性它仅仅只能解决使用计算机代替人力完成那么有规律、繁琐而无聊游戏动作但是随着网络游戏盛行和复杂度增加很多游戏要求将客户端动作信息及时反馈回服务器通过服务器对这些动作信息进行有效认证后再向客户端发送下步游戏动作信息这样动作模拟技术将失去原有效应为了更好地“外挂”这些游戏游戏外挂也进行了升级换代它们将以前针对游戏用户界面层模拟推进到数据通讯层通过封包技术在客户端挡截游戏服务器发送来游戏控制数据包分析数据包并修改数据包;同时还需按照游戏数据包结构创建数据包再模拟客户端发送给游戏服务器这个过程其实就是个封包过程

  封包技术是实现第 2类游戏外挂最核心技术封包技术涉及知识很广泛实现思路方法也很多如挡截WinSock、挡截API、挡截消息、VxD驱动在此我们也不可能在此文中将所有封包技术都进行详细介绍故选择两种在游戏外挂中最常用两种思路方法:挡截WinSock和挡截API

  1. 挡截WinSock

  众所周知Winsock是Windows网络编程接口它工作于Windows应用层它提供和底层传输协议无关高层数据传输编程接口在Windows系统中使用WinSock接口为应用提供基于TCP/IP协议网络访问服务这些服务是由Wsock32.DLL动态链接库提供库来完成

  由上介绍说明可知任何Windows基于TCP/IP应用都必须通过WinSock接口访问网络当然网络游戏也不例外由此我们可以想象如果我们可以控制WinSock接口那么控制游戏客户端和服务器的间数据包也将易如反掌按着这个思路下面工作就是如何完成控制WinSock接口了由上面介绍可知WinSock接口其实是由个动态链接库提供系列由这些实现对网络访问有了这层认识问题就好办多了我们可以制作个类似动态链接库来代替原WinSock接口库在其中实现WinSock32.dll中实现所有并保证所有参数个数和顺序、返回值类型都应和原库相同在这个自制作动态库中可以对我们感兴趣(如发送、接收等)进行挡截放入外挂控制代码最后还继续原WinSock库中提供相应功能这样就可以实现对网络数据包挡截、修改和发送等封包功能

  下面重点介绍创建挡截WinSock外挂基本步骤:

  (1) 创建DLL项目选择Win32 Dynamic-Link Library再选择An empty DLL project

  (2) 新建文件wsock32.h按如下步骤输入代码:

  ① 加入相关变量声明:

   HMODULE hModule=NULL; //模块句柄
   char buffer[1000]; //缓冲区
   FARPROC proc; //入口指针  

  ② 定义指向原WinSock库中所有地址指针变量因WinSock库共提供70多个限于篇幅在此就只选择几个常用列出有关这些库介绍说明可参考MSDN相关内容

   //定义指向原WinSock库地址指针变量
   SOCKET (__stdcall *1)( ,,);//创建Sock
    (__stdcall *WSAStartup1)(WORD,LPWSADATA);//化WinSock库
    (__stdcall *WSACleanup1);//清除WinSock库
    (__stdcall *recv1)(SOCKET ,char FAR * , , );//接收数据
    (__stdcall *send1)(SOCKET ,const char * , ,);//发送数据
    (__stdcall *connect1)(SOCKET,const struct sockaddr *,);//创建连接
    (__stdcall *bind1)(SOCKET ,const struct sockaddr *, );//绑定
   ......其它地址指针定义略  

  (3) 新建wsock32.cpp文件按如下步骤输入代码:

  ① 加入相关头文件声明:

   # <windows.h>
   # <stdio.h>
   # "wsock32.h"  

  ② 添加DllMain在此中首先需要加载原WinSock库并获取此库中所有地址代码如下:

   BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)
   {
    (hModuleNULL){
     //加载原WinSock库原WinSock库已复制为wsock32.001
   hModule=LoadLibrary("wsock32.001");
  }
     1;
//获取原WinSock库中所有地址并保存下面仅列出部分代码
(hModule!=NULL){
     //获取原WinSock库地址并保存到WSAStartup1中
proc=GetProcAddress(hModule,"WSAStartup");
   WSAStartup1=( (_stdcall *)(WORD,LPWSADATA))proc;
     //获取原WinSock库消除地址并保存到WSACleanup1中
    proc=GetProcAddress(hModule i,"WSACleanup");
    WSACleanup1=( (_stdcall *))proc;
     //获取原创建Sock地址并保存到1中
    proc=GetProcAddress(hModule,"");
     1=(SOCKET (_stdcall *)( ,,))proc;
     //获取原创建连接地址并保存到connect1中
     proc=GetProcAddress(hModule,"connect");
     connect1=( (_stdcall *)(SOCKET ,const struct sockaddr *, ))proc;
     //获取原发送地址并保存到send1中
     proc=GetProcAddress(hModule,"send");
     send1=( (_stdcall *)(SOCKET ,const char * , , ))proc;
     //获取原接收地址并保存到recv1中
     proc=GetProcAddress(hModule,"recv");
     recv1=( (_stdcall *)(SOCKET ,char FAR * , , ))proc;
     ......其它获取地址代码略
   }
    0;
    1;
}

  ③ 定义库输出在此可以对我们感兴趣中添加外挂控制代码在所有输出最后步都原WinSock库同名部分输出定义代码如下:

//库输出定义
//WinSock
     PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
    {
     //原WinSock库
      WSAStartup1(wVersionRequired,lpWSAData);
    }
    //WinSock结束清除
     PASCAL FAR WSACleanup(void)
    {
      WSACleanup1; //原WinSock库结束清除
    }
    //创建Socket
    SOCKET PASCAL FAR ( af, type, protocol)
    {
     //原WinSock库创建Socket
      1(af,type,protocol);
    }
    //发送数据包
     PASCAL FAR send(SOCKET s,const char * buf, len, flags)
    {
   //在此可以对发送缓冲buf内容进行修改以实现欺骗服务器
   外挂代码......
   //原WinSock库发送数据包
      send1(s,buf,len,flags);
    }
//接收数据包
     PASCAL FAR recv(SOCKET s, char FAR * buf, len, flags)
    {
   //在此可以挡截到服务器端发送到客户端数据包先将其保存到buffer中
   strcpy(buffer,buf);
   //对buffer数据包数据进行分析后对其按照玩家指令进行相关修改
   外挂代码......
   //最后原WinSock中接收数据包
      recv1(s, buffer, len, flags);
     }
    .......其它定义代码略

  (4)、新建wsock32.def配置文件在其中加入所有库输出声明部分声明代码如下:

   LIBRARY "wsock32"
   EXPORTS
    WSAStartup @1
   WSACleanup @2
    recv @3
    send @4
     @5
   bind @6
   close @7
   connect @8

   ......其它输出声明代码略

  (5)、从“工程”菜单中选择“设置”弹出Project Setting对话框选择Link标签在“对象/库模块”中输入Ws2_32.lib

  (6)、编译项目产生wsock32.dll库文件

  (7)、将系统目录下原wsock32.dll库文件拷贝到被外挂目录下并将其改名为wsock.001;再将上面产生wsock32.dll文件同样拷贝到被外挂目录下重新启动游戏此时游戏将先加载我们自己制作wsock32.dll文件再通过该库文件间接原WinSock接口来实现访问网络上面我们仅仅介绍了挡载WinSock实现过程至于如何加入外挂控制代码还需要外挂开发人员对游戏数据包结构、内容、加密算法等方面仔细分析(这个过程将是个艰辛过程)再生成外挂控制代码有关数据包分析思路方法和窍门技巧不是本文讲解范围如您感兴趣可以到网上查查相关资料



  • 篇文章: 游戏外挂设计技术探讨①

  • 篇文章: 游戏外挂设计技术探讨③
  • Tags:  qq空间游戏外挂 qq空间游戏基地外挂 游戏外挂 qq游戏外挂

    延伸阅读

    最新评论

    发表评论