协议型外挂制作教程三

原创 2004年10月27日 10:06:00

协议型外挂制作教程三

By rix

       上一节中我们说了外挂平台的搭建,我们做完了Hook.dllwg.exe,但如何让wg.exe调用Hook.dll中的函数,可以自己查看CB的教程或者到网上查查。在这里我是在wg.exeHook按钮事件中添加了下面的语句来实现:

if(gamethreadid)

{

if(EnableHook(gamethreadid)==false)

ShowMessage("error");

}

       你可以点击Hook按钮在游戏界面出来之后,然后在游戏界面中按F12键调出外挂的窗口。

       昨天的尾巴完事之后,开始今天的教程。今天我想说说APIHOOK。虽然APIHOOK在大话游戏的外挂制作中不是必须的,但为了按照一般的制作流程顺序,就先将这部分加入到里面去了。

       使用APIHOOK的原因也很简单,游戏肯定要调用某些系统函数,使用APIHOOK可以简单的查看一些关键的信息并进行修改(就这么简单的理由?是的,我们一向再用杀牛的刀宰鸡的。。。)。

       Jeffrey Richter用了大量的篇幅来讲如何插入DLL和挂接API,如果你不知道Jeffrey Richter是谁的话,总该知道《Windows核心编程》的作者吧,如果不知道,我倒,系统抛出例外,你是外星人吧。我们的程序运行在用户层上,JR提出了两种办法,一种是改写代码,我刚开始也试图用这种办法,后来发现这种办法确实存在的漏洞多多,和JR说的一样。最后还是采用操作模块的输入节了。

       在查看资料的过程中,我发现JR的代码在中文Windows 2000上并不能运行(难道是外国人用的系统和中国的不一样?),后来只好JR的思路,重新安排了一下函数,但大部分函数都一样的。为了方便,我没有在类中捕获LoadLibraryALoadLibraryWLoadLibraryExALoadLibraryExW,也是因为我们的外挂程序运行的时候游戏的窗口已经出来了,该加载的一般都加载了。

       下面是我的APIHOOK类的源代码,该源代码是根据J.R的思路重新整理他的源代码来的:

       /*HookAPI.h*/

#include "windows.h"

 

class CAPIHOOK

{

public:

CAPIHOOK(PSTR pszCalleeModName,PSTR pszFuncName,PROC pfnHook,HANDLE prochandle,HMODULE hmod);

~CAPIHOOK();

operator PROC(){return (m_pfnOrig);};

public:

static PVOID sm_pvMaxAppAddr;

 static CAPIHOOK* sm_pHead;

CAPIHOOK* m_pNext;

PCSTR m_pszCalleeModName;

PCSTR m_pszFuncName;

PROC m_pfnOrig;

PROC m_pfnHook;

BOOL m_fExcludeAPIHookMod;

HMODULE m_module;

HANDLE m_handle;

private:

pfnOrig,PROC pfnHook,BOOL fExcludeAPIHookMod);

 void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,PROC pfnOrig,PROC pfnHook,HMODULE hmodcaller,HANDLE handle);

 void WINAPI FixupNewlyLoadedModule(HMODULE hmod,DWORD dwFlags);

FARPROC WINAPI GetProcAddress(HMODULE hmod,PCSTR pszProcName);

};

 

 

/*HookApi.cpp*/

 

 

#include "hookapi.h"

#include <assert.h>

#include "imagehlp.h"

PVOID CAPIHOOK::sm_pvMaxAppAddr = NULL;

const BYTE cPushOpCode = 0x68;

CAPIHOOK *CAPIHOOK::sm_pHead = NULL;

 

 

CAPIHOOK::CAPIHOOK(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook,

  HANDLE prochandle, HMODULE hmod)

{

  m_handle = prochandle;

  if (sm_pvMaxAppAddr == NULL)

  {

    SYSTEM_INFO si;

    GetSystemInfo(&si);

    sm_pvMaxAppAddr = si.lpMaximumApplicationAddress;

  }

  m_pNext = sm_pHead;

  sm_pHead = this;

  m_pszCalleeModName = pszCalleeModName;

  m_pszFuncName = pszFuncName;

  m_pfnHook = pfnHook;

  m_pfnOrig = ::GetProcAddress(GetModuleHandleA(pszCalleeModName),

    m_pszFuncName);

  assert(m_pfnOrig != NULL);

  if (m_pfnOrig == NULL)

  {

return;

  }

  if (m_pfnOrig > sm_pvMaxAppAddr)

  {

    PBYTE pb = (PBYTE)m_pfnOrig;

    if (pb[0] == cPushOpCode)

    {

      PVOID pv = *(PVOID*) &pb[1];

      m_pfnOrig = (PROC)pv;

    }

  }

  m_module = GetModuleHandle(pszCalleeModName);

  ReplaceIATEntryInOneMod(m_pszCalleeModName, m_pfnOrig, m_pfnHook, m_module,

    prochandle);

}

 

CAPIHOOK::~CAPIHOOK()

{

  ReplaceIATEntryInOneMod(m_pszCalleeModName, m_pfnHook, m_pfnOrig, m_module,

    m_handle);

  CAPIHOOK *p = sm_pHead;

  if (p == this)

  {

    sm_pHead = p->m_pNext;

  }

  else

  {

    BOOL fFound = FALSE;

    for (; !fFound && (p->m_pNext != NULL); p = p->m_pNext)

    {

      if (p->m_pNext == this)

      {

        p->m_pNext = p->m_pNext->m_pNext;

        break;

      }

    }

    assert(fFound);

  }

}

 

void WINAPI CAPIHOOK::FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags)

{

  if ((hmod != NULL) && ((dwFlags &LOAD_LIBRARY_AS_DATAFILE) == 0))

  {

    for (CAPIHOOK *p = sm_pHead; p != NULL; p = p->m_pNext)

    {

      ReplaceIATEntryInOneMod(p->m_pszCalleeModName, p->m_pfnOrig, p->m_pfnHook,

        hmod, m_handle);

    }

  }

}

 

FARPROC WINAPI CAPIHOOK::GetProcAddress(HMODULE hmod, PCSTR pszProcName)

{

  FARPROC pfn = ::GetProcAddress(hmod, pszProcName);

  CAPIHOOK *p = sm_pHead;

  for (; (pfn != NULL) && (p != NULL); p = p->m_pNext)

  {

    if (pfn == p->m_pfnOrig)

    {

      pfn = p->m_pfnHook;

      break;

    }

  }

  return (pfn);

}

 

void WINAPI CAPIHOOK::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC

  pfnCurrent, PROC pfnHook, HMODULE hmodcaller, HANDLE handle)

{

  ULONG ulSize;

 

  PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)

    ImageDirectoryEntryToData(hmodcaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT,

    &ulSize);

  if (pImportDesc == NULL)

  {

   

    return ;

  }

 

  for (; pImportDesc->Name; pImportDesc++)

  {

    PSTR pszModName = (PSTR)((PBYTE)hmodcaller + pImportDesc->Name);

    if (lstrcmpiA(pszModName, pszCalleeModName) == 0)

    {

     

      break;

    }

  }

  if (pImportDesc->Name == 0)

  {

   

    return ;

  }

  PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hmodcaller +

    pImportDesc->FirstThunk);

  for (; pThunk->u1.Function; pThunk++)

  {

    PROC *ppfn = (PROC*) &pThunk->u1.Function;

    BOOL fFound = (*ppfn == pfnCurrent);

    if (!fFound && (*ppfn > sm_pvMaxAppAddr))

    {

      PBYTE pbInFunc = (PBYTE) *ppfn;

      if (pbInFunc[0] == cPushOpCode)

      {

        ppfn = (PROC*) &pbInFunc[1];

        fFound = (*ppfn == pfnCurrent);

      }

    }

    if (fFound)

    {

      HANDLE handle1 = OpenProcess(PROCESS_ALL_ACCESS, FALSE,

        GetCurrentProcessId());

      DWORD dwIdOld;

      VirtualProtectEx(handle1, ppfn, sizeof(pfnHook), PAGE_READWRITE, &dwIdOld)

        ;

 

      if (WriteProcessMemory(handle1, ppfn, &pfnHook, sizeof(pfnHook), NULL) ==

        false)

      {

       

        return ;

      }

      else

      {

        VirtualProtectEx(handle1, ppfn, sizeof(pfnHook), dwIdOld, &dwIdOld);

        return ;

      }

    }

  }

}

上面是APIHOOK的完整代码。下面是使用的例子(拦截WString2ID函数):

typedef unsigned long(__stdcall *WString2ID)(char const*);

unsigned long __stdcall myWString2ID(char const*);

CAPIHOOK *My_WString2ID;

My_WString2ID = new CAPIHOOK("windsoul.dll", "?WString2ID@@YGKPBD@Z",

          (PROC)myWString2ID, gamehandle, gameInstance);

自己的myWString2ID的实现:

unsigned long __stdcall myWString2ID(char const *a)

{

  // SendMessage(wghandle,WM_USER+1,(WPARAM)a,NULL);

   return (((WString2ID)My_WString2ID->m_pfnOrig)(a));

}

下面是用来拦截游戏的WndProc函数的,当时写的时候为了全面,至于如何去用,随便自己了,反正我没有用。

gamehWnd = GetActiveWindow();

        gamehandle =GetCurrentProcess();

        gameInstance = (HINSTANCE)GetWindowLong(gamehWnd, GWL_HINSTANCE);

gameproc = (WNDPROC)SetWindowLong(gamehWnd, GWL_WNDPROC, (LONG)

          MyMsgProc);

自己用来替换游戏的WndProc函数:

LRESULT APIENTRY MyMsgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM

  lParam)

{

/*在这里做自己想做的事情,剩下的让游戏的WndProc来处理*/

  return CallWindowProc(gameproc, hwnd, message, wParam, lParam);

}

这一节到这里就结束了,下一节开始游戏程序的研究。最好准备大话客户端9.16更新之前的最后一个版本,不使用最新的版本有下面的原因:

1、              如果对现在客户端作过多的透漏的话,将会发现做盗号类的程序比做外挂要简单,这不是我所希望看到的。

2、              新版本采用的加密办法(双精度浮点数加密)在讲解上非常的麻烦,不是一般人容易入门的,但解决的办法和9.16之前的版本一样,只是繁琐而以。

3、              脱壳后的程序有更多的需要人工识别的部分,这会造成不必要的麻烦,免得误导大家。

              本文章只贴于www.csdn.netwww.gameres.com Blog上面,请勿将文章用于任何商业场合,如果因为本教程引起其他的后果的话,则与本人无关,本人只讲技术实现。如果要转贴的话,请注明出处,如果有疑问或者商议的话,请发E-Mailzeze0556@sina.com或者QQ23033206留言,MSNzeze0556@msn.com。另外请勿给我信箱发垃圾邮件,在添加好友的时候一定要写好附言,我已经被莫名其妙的广告信件和流言蜚语吓得没有胆了。算是我求各位大虾了

 

协议型外挂制作四

协议型外挂制作四By rix       上一次我们说了外挂中APIHOOK和基本平台的搭建,但仅仅只用APIHOOK在大多数的时候并不能达到目的,没有哪个公司会将网络打包加密解密解包的程序放在dll...
  • zhangze
  • zhangze
  • 2004年10月30日 10:58
  • 1885

协议型外挂制作五

协议型外挂制作五By rix       第一节到第三节我们说了基本工具的准备,第四节使用免升级和免弹出主页来做了一下基本的练习。第四节中和普通的游戏修改器没有太大的区别,只是一个修改的是数据,一个修...
  • zhangze
  • zhangze
  • 2004年11月03日 12:31
  • 1752

协议型外挂制作

       目前,网络游戏的外挂从程序角度主要分为辅助型的动作外挂和内核型的协议型外挂。动作外挂主要帮助玩家进行一些重复性的劳动量,网络上有许多介绍这方面的程序,按键精灵就是一个很好的例子。协议型外...
  • sanshao27
  • sanshao27
  • 2007年06月20日 10:24
  • 2197

简单游戏外挂制作教程

在几年前我看到别人玩网络游戏用上了外挂,做为程序员的我心里实在是不爽,想搞清楚这到底是怎么回事。就拿了一些来研究,小有心得,拿出来与大家共享,外挂无非就是分几种罢了(依制作难度):  1、动作式...
  • liujiayu2
  • liujiayu2
  • 2015年05月14日 15:52
  • 5531

第一个游戏外挂,附上详细制作过程

本教程分为几大部分 一、  先创建外挂对话框,定义外挂所需要的基本功能 二、  找出棋盘数组的地址,读出棋盘数据 三、  编写实现消去棋子的代码框架 四、  实现消去棋子功能 五、  修...
  • mysouling
  • mysouling
  • 2013年03月13日 17:19
  • 2022

零基础制作【武林外传】辅助工具(二)

 零基础制作【武林外传】辅助工具(二) 1.建立一个新的标准EXE工程,我们就可以开始这次的学习了。 2.我们要建立一个模块,然后添加以下代码: ...
  • pzhccy
  • pzhccy
  • 2007年08月21日 13:09
  • 718

植物大战僵尸做挂教程。(共7集)最详细!!!!适合学习!!!

植物大战僵尸做挂教程。(共7集)最详细!!!!适合学习!!!_精易论坛
  • yue31313
  • yue31313
  • 2014年05月07日 02:08
  • 452

协议型网络游戏外挂制作之启动

目前,网络游戏的外挂从程序角度主要分为辅助型的动作外挂和内核型的协议型外挂。动作外挂主要帮助玩家进行一些重复性的劳动量,网络上有许多介绍这方面的程序,按键精灵就是一个很好的例子。协议型外挂则给人一个很...
  • equationdz
  • equationdz
  • 2008年02月03日 17:56
  • 460

某些外挂的制作思路

之前自己曾经写过一个web游戏类的外挂,分析协议,模拟数据发送比较麻烦。 最近看到一款类似射击游戏的外挂,其实,之前,我也在想,这类外挂如何制作,难道也是抓数据包,数据封包,似乎难度很到。 那么这...
  • mamihong
  • mamihong
  • 2013年03月21日 13:08
  • 1085

外挂制作必备工具下载

原文引用:http://www.cnblogs.com/GameDeveloper/archive/2011/03/11/1981663.html 工具下载: peid 0.94    用于查壳,...
  • lianchao668
  • lianchao668
  • 2012年09月22日 09:37
  • 6304
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:协议型外挂制作教程三
举报原因:
原因补充:

(最多只允许输入30个字)