外挂制作之------游戏DLL注入

 

先谈下游戏,游戏每个动作都会调用函数。比方游戏设计人员是这样设计游戏的:
void zhixing() //执行函数
{
        dazuo();
        .......  //@1
}

void dazuo() //打坐函数
{
      jimi("...."); //加密函数
  return;                
}

void jimi(char *s)
{
      //对s加密处理,赋值给str变量
  fashong(str); //发送函数
  return;      
}

void fashong(char *s)
{
      send(s);
      return;        
}

你要打坐,你就必须要调用相对应的函数。上面的游戏只要你调用dazuo()就会在游戏中执行打坐这个动作。 而通过OD可以把游戏执行在内存中的代码反汇编出来。比如说你下断点bp send,意思就是当调用函数send时就断下来。你断下来后,当你按1次ctrl+f9,就返回到jimi函数中,按第2次ctrl+f9,就返回到dazuo函数中,再按一次ctrl+f9,就返回到zhixing函数中的@1位置,这样,上一行就是dazuo的函数。 你就可以通过调用call 地址执行这个动作了。

而为什么要DLL注入呢?
因为win NT系统是每个进程独立的,只有自己进程才能执行(调用自己进程的函数)
你把dll注入到游戏进程空间,dll就可以调用游戏进程空间中的函数了。
再打个比方:你call 0072e7a8,就是执行本进程空间的0072e7a8位置的函数。
你如果不注入,而在自己程序中执行call 0072e7a8,也就是调用自己进程0072e7a8地址的函数,那当然有问题啦,游戏的函数全在游戏进程中。你外挂进程0072e7a8是什么,与游戏执行无关。

再谈基址问题吧。
游戏中任何数据都在内存中存在,不管是血,蓝,等级,怪物名字,地图名字,只要是数据。全在内存中。 只要你读取那个内存地址就能显示出血来。 其实说白了,游戏客户端显示的数据也是读取的内存中的数据而显示出来的。
struct renwu //人物结构
{
      DWORD xue;  //血
  DWORD lan;    //蓝
  DWORD dengji;  //等级
  ........
};

void init() //游戏初始化函数
{
      struct renwu *dwRW;
      dwRW = new struct renwu;
}

游戏初始化了,dwRW在内存中的地址是固定的,这就是基地址
而new是动态分配的,谁也不知道系统会分配哪个地址给你。
比如说dwRW在内存中的地址是0026762e, 这样,你只需要
[0026762e]就可以得到dwRW结构的地址,偏移0就是血的地址,
偏移4就是蓝的地址,偏移8就是等级的地址了。

再谈谈f12呼出外挂吧。
想在游戏中按f12键呼出外挂,当然就是截取在游戏中按f12键的消息了。想到要截取某进程的某消息,
第一想法就应该是想到挂钩子。钩子就是hook,就是把游戏钩住的意思,比如你给游戏安装一个键盘钩子,这样,只要在游戏进程中的程序,有键盘消息,都会先执行你的钩子函数,所以,你只需要挂个钩子,在钩子函数中,判断按钮是否为F12,如果是,就显示外挂窗口,不是,就放弃这个消息,让游戏自己去处理。
如果只想在游戏执行后,在游戏中按F12,就呼出外挂,就必须把安装钩子和钩子函数写到dll,因为只有dll才能映射到别的进程空间去,exe程序是不行的,dll中的钩子函数映射到游戏进程空间去了,就可以只钩住这个进程的键盘消息了,(所以如果你不把安装钩子和钩子函数写到dll的话,就成了全局钩子了,全局钩子是钩住windows平台中所有的进程的,在任何时候你按f12,都会呼出外挂的

C++注入框架CHook_DLLApp::CHook_DLLApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CHook_DLLApp object CHook_DLLApp theApp; LRESULT CALLBACK KeyboardProc( int Code, //Hook絏 WPARAM wParam, //店览龄 VK_F1 , VK_F2 , VK_HOME LPARAM lParam //龄絃癟 (lParam&(1<<30)) 北磅︽Ω ぃ礛㎝秨常穦磅︽ ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); //ňゎ笆篈硈挡畐岿粇 //判断是否按下HOME键 if(wParam == VK_HOME && (lParam&(1<<30)))//(lParam&(1<<30)) 北磅︽Ω ぃ礛㎝秨常穦磅︽ { //如果按下HOME键(不监视键弹起的动作,只监视键按下的动作) //AfxMessageBox("为目标进程附加(注入DLL文件成功!"); _asm //游戏注入CALL { mov eax,0X004043A0 call eax } } return CallNextHookEx(0,Code,wParam,lParam); } void SetHook() { HWND h =::FindWindow(NULL,"模拟找CALL练习1.0版=梦工厂出品");//怠嘿 if(h==0) { AfxMessageBox("没找到游戏窗口!"); } DWORD Pid; //游戏进程PID Pid = ::GetWindowThreadProcessId(h,NULL); //把DLL挂钩(注入)到目标游戏进程 ::SetWindowsHookEx( WH_KEYBOARD, //KEY表示的是按键。啥时候触发钩子呢?(按键时候触发) &KeyboardProc, //使用DLL里面的具体某个自定义函数(在这里用函数指针即可) ::GetModuleHandle("Hook_DLL.dll"), //使用具体某个DLL,GetModuleHandle返回DLL的模块句柄 Pid //PID ); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值