VC编程——XP扫雷外挂

 

以下内容转载至本人QQ空间。如有雷同,纯属巧合。

 

前段时间,应魏小子之邀请开始学习编写外挂,后来他自己找到了按键精灵解决他的问题,于是我开始了自己的研究。最近研究了windows扫雷,QQ连连看两款游戏的外挂,下面先介绍扫雷外挂。

 

为什么先研究这两款呢?主要是网上能查得到相关信息,功力不够只能由浅入深,也算是依葫芦画瓢。

先看看扫雷效果:(由于游戏时间只需要1秒,因此可以称之为“秒杀”)

VC编程——XP扫雷外挂_第1张图片

 

下面是编程方法:

一:可能需要的技能:

1.了解VC或其他编程语言(本例为VC)

2.熟悉CE(Cheat Engine)的使用方法

3.熟悉OD(Ollydbg)的使用方法

4.熟悉VC的spy++的使用方法

如果不了解VC,需要下很大的功夫;如果不了解CE和OD可以在网上搜索相关教程,别指望我能教会你。

如果不了解spy++和Findwindow等函数的用法也可以网上搜索。

 

二:参考资料

1)   豆丁网——基于CE和OD开发扫雷外挂详细步骤  http://www.docin.com/p-49471470.html

2)看雪学院——CARY写的【原创】打造扫雷终极外挂 http://bbs.pediy.com/showthread.php?t=48517

 

三:方法分析

1. 首先是CARY说的猜测这个游戏要用到随机函数rand,最后真的发现游戏使用了该函数,于是用OD进行反汇编调试,找到了游戏构建雷所需数组的基地址,通过读取基地址的信息判断各个区域是否有雷。(如果游戏没有使用rand而是使用了编程者自己写的随机函数,那么该方法就不行,就只有想其他的办法,简单点说外挂制作就是要猜测编程者的编程方法,然后逆向思维,看是否有机可趁)

2. 找雷就是要找出有雷和无雷时该数值的对应值,比如该游戏中有雷就是8F,无雷时是0F。

3.CARY里面介绍的秒杀方法是可行,但是却不完美,他是通过直接修改“雷区”内存地址实现扫雷。

这有两个缺点:1)就是很容易被杀毒软件杀掉,因为你要直接写内存很多杀毒软件不允许的。

       2)由于游戏会记时还有英雄榜,直接写内存只能秒杀,不能让时间启动和停止,更不能让你登上英雄榜。除非找到写入英雄榜和停止时间的相关代码并进行信息传递,但是我一时也没找到。

4.本例采用模拟鼠标点击的方式,当读取内存发现有雷就右键单击,如果无雷就左键单击,速度很快,实现秒杀。

 

四:外挂代码

1.  主函数

DWORD addr = 0x1005361;   //windowsXP下的雷区基址,如果是其他操作系统需要自己重新找
 DWORD x = 0x10056A8;   
 DWORD y = 0x10056AC;
 RECT r1;
 POINT p;

bEnableDebugPriv();  //提升权限函数,由于OpenProcess需要管理员权限
 //保存当前鼠标指针
 //取得当前鼠标位置
 GetCursorPos(&p);

 HWND hwnd  = ::FindWindow(NULL, _T("扫雷"));   //查找应用程序窗口
 DWORD hProcessId;     

 ::GetWindowThreadProcessId(hwnd, &hProcessId);   //得到窗口进程
 ::GetWindowRect(hwnd,&r1); //得到窗口大小
 HANDLE Process = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, hProcessId);    //打开进程 
 int b = 0 , s = 0, nx = 0, ny = 0;   
 ::ReadProcessMemory(Process, (LPCVOID)x, &nx, 1, NULL);    //获取横向方格长度   
 ::ReadProcessMemory(Process, (LPCVOID)y, &ny, 1, NULL);    //获取纵向方格长度   

 for(int i = 0; i < nx * 32; i += 32)   
 {     
  for(int j = 0; j < ny; j++)     
  {       
   ::ReadProcessMemory(Process, (LPCVOID)(addr + i+j), &b, 1, NULL);       
   if (b == 0x8F || b == 0x8E)       //判断是否有雷       
   {          

  SetCursorPos(22+j*16+r1.left,115+i/32*16+r1.top);

   //移动鼠标位置,以下位置是很重要的,22和115是第一个雷相对应窗口的x,y坐标的大至距离,可以不是很精确,只要鼠标点击能实现就行,可以多根据抓图工具查看像素值,并且实践中多试一下。


VC编程——XP扫雷外挂_第2张图片
    

    mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
    mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
   }    
   else
   {
    SetCursorPos(22+j*16+r1.left,115+i/32*16+r1.top);
    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
   }

  }  
 }   
 ::InvalidateRect(hwnd, NULL, TRUE);  
 
 SetCursorPos(p.x,p.y);
 ::CloseHandle(Process);

2. 提升权限函数 bool bEnableDebugPriv() 

HANDLE hToken;
 LUID sedebugnameValue;
 TOKEN_PRIVILEGES tkp;

 if (!OpenProcessToken(GetCurrentProcess(),
  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
   return false;
 }
 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
  CloseHandle(hToken);
  return false;
 }
 tkp.PrivilegeCount = 1;
 tkp.Privileges[0].Luid = sedebugnameValue;
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
  CloseHandle(hToken);
  return false;
 }
 return true;

 

五、外挂缺陷

1. 由于该方法是读取基址,对于不同操作系统(比如win7和XP)的该游戏的基址是不同,因此需要对不同操作系统进行量身订做,以上代码适用于XP系统,如果是win7可能findwindow类名以及雷区基址不同。

2.模拟鼠标点击方式虽然不需要写内存,但是需要读内存,如果编程者注意到这个方面,在编写程序的时候不是全局分配而是临时分配则用OD跟踪的基址就不行,对于扫雷这种小游戏而言完全可以不用全局分配,就像我同事之前搞的一个水晶连连看就不是全局分配的。

3.模拟鼠标点击方式需要扫雷窗口完全不能被其他窗口遮挡,这里可以通过代码访问扫雷设置扫雷为始终最前,还可以将外挂窗体开机最小化并且通过设置windows系统热键RegisterHotKey相关函数实现快捷键。

4.可能在打开两个以上的外挂程序时出现失灵的状况。解决方法:可以通过互斥对象及OpenMutex等函数限制多个应用外挂程序同时运行。(可以网上查询)

你可能感兴趣的:(游戏,编程,XP,null,token,杀毒软件)