spy++和游戏修改器

标签: spy 游戏修改 | 发表时间:2011-08-09 15:06 | 作者:陈晓 大宝PKU
出处:http://www.cppblog.com/
这几天做了两个东西,spy++ 和游戏修改器。 spy++ 就是模仿 vs的那个工具spy++ 。游戏修改器,就是暴力搜索内存,找到我们关心的数据,然后进行更改。
总之这些东西做过之后感觉就是都不难,但是在做的时候多少会感觉点吃力。唉,功力不够啊。继续修炼……
闲下来无事,记录下它们的过程吧。
spy++ 分析(用vs2005做的——)
spy++ 需要拖动一个小图标 然后移动到别的窗口上(本窗口也可以),然后画出窗口的矩形,得到窗口的一些信息。
拖动的这个小图标,是一个picture conctrl控件 ,属性的type改成icon 也就是加载一个icon图标,在属性imag里把图标选上。
给这个控件添加一个类,在这个类里做这个控件的 小图标拖动操作,即 lbuttondown的时候 把鼠标加载成 小图标,把picture里的icon换成空心的。
当鼠标抬起的时候把鼠标换回来原先的光标,然后再把picture里的icon换成有小图标的那个图标。
这里要主次 要把鼠标设成全局有效,要不然的话,鼠标位置出了这个picture的范围就失效了。函数是 SetCapture()
然后再lbuttonup的时候记得 要释放。ReleaseCapture();
           就是这几个图标。吼吼。
把这个小图标托到 窗口上的时候怎么在窗口上画出矩形呢? 
当然是先得到这个矩形了。我要先得到这个窗口的句柄,我们才能得到windowrect 然后才能画。
所以各 下一步就是WindowFromPoint(Point)传一个鼠标点 然后得到这个点的window的hWnd了 哈,很强大的函数啊。
得到窗口句柄就好办了。GetWindowRect得到矩形区域啊,然后用windowdc 画,用windowdc的原因就是,我们要在整个桌面上都能画。
这里画这个矩形有个技巧,我们要画出来,但是当我们不需要这个矩形的时候我们还要给这个颜色画回原来的背景色。这里算是整个程序的一个难点,考验画图工夫。
dc设备中默认选入的是一个黑色画笔,一个白色画刷,也就是说正常我们画矩形的话会画出黑边白底得矩形,现在我们要透明的底,然后画的黑边还要可画回原先的背景色。有一个函数通过dc调用  dc.SetROP2(R2_NOTXORPEN);参数传这个同或运算,这个函数的意思就是,拿你设备中的画笔画刷 去跟背景色运算,同或运算。
比如背景有个颜色是10010100011   你的画刷颜色是白色 也就是111111111111(比如就这么多位)  白色因为是255,255,255所以都是1  
然后进行同或运算得到的是什么?是10010100011(同或,同则1,不同则0)!也就说 还是背景色,这就做到了画刷透明。然后画笔是黑色,0000000000
跟背景色同或运算的到得是01101011100 这个。然后这个就是真正画到屏幕上显示出来的颜色。怎么在把这个颜色画没呢?大家在用这个黑色的画笔画一下,在同或运算看看结果是什么?10010100011 看看是不是又变回去了?吼吼。等会下面贴代码画图这里的。
这个画图就完事了。而且窗口句柄我们也通过windowfrompoint得到了。有了窗口句柄我们能得到很多东西了。
比如说窗口类名GetClassName
窗口标题GetWindowText
窗口矩形GetWindowRect
窗口id等信息GetWindowLong
进程id   GetWindowThreadProcessId
进程路径 OpenProcess()   GetModuleFileNameEx();

还可以向窗口中发消息 sendmessage(这个比较好玩,可以拿你的spy++去关闭别人的窗口。
然后把他设置到窗口上就可以了。
代码贴一小段。

void CMyPic::OnTimer(UINT_PTR nIDEvent)
{
    POINT p;
    ::GetCursorPos(
&p);
    hWnd
=::WindowFromPoint(p);
    CRect rect;
    ::GetWindowRect(hWnd,
&rect);
    CWindowDC dc(NULL);
    CPen redpen(PS_SOLID,
3,RGB(255,0,0));
    dc.SelectObject(
&redpen);
    dc.SetROP2(R2_NOTXORPEN);
    dc.Rectangle(rect);
    
//显示回去 就向没画一样
    Sleep(300);
    dc.Rectangle(rect);
    ReleaseDC(
&dc);
    CStatic::OnTimer(nIDEvent);
}

这个画图在timer里画,能做到 闪动的巨型。(我选的红色画笔,你可以把红色跟背景同或算算,跟黑色是一样的,在画一次就能画回来背景色)
下面的代码是 写我的spy++的第一页的代码

void CMyspyDlg::UpdataWindowNormal(HANDLE hWnd)
{
 CString str;
 int state=((CButton *)GetDlgItem(IDC_CHECK1))->GetCheck();
 //窗口句柄
 if (state==BST_CHECKED)
 {
  str.Format(_T("%p"),hWnd);
 }
 else
 {
  str.Format(_T("%d"),hWnd);
 }
 m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_HANDLE)->SetWindowText(str);
 //窗口类名
 TCHAR tempTC[50];
 GetClassName((HWND)hWnd,tempTC,49);
 m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_CLASSNAME)->SetWindowText(tempTC);
 //窗口标题
 ZeroMemory(tempTC,100);
 ::GetWindowText((HWND)hWnd,tempTC,49);
 if (*tempTC==_T('\0'))
 {
  m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_TITLE)->SetWindowText(_T("无"));
 }
 else
 {
  m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_TITLE)->SetWindowText(tempTC);
 }
 //窗口矩形
 CRect rect;
 ::GetWindowRect((HWND)hWnd,&rect);
 str.Empty();
 if (state==BST_CHECKED)
 {
  str.Format(_T("x=%x,y=%x,width=%x,hight=%x"),rect.left,rect.top,rect.Width(),rect.Height());
 }
 else
 {
  str.Format(_T("x=%d,y=%d,width=%d,hight=%d"),rect.left,rect.top,rect.Width(),rect.Height());
 }
 m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_WINRECT)->SetWindowText(str);
 //窗口id
 str.Empty();
 LONG l=::GetWindowLong((HWND)hWnd,GWL_ID);
 str.Format(_T("%ld"),l);
 m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_WINID)->SetWindowText(str);
 //进程id
 DWORD dword;
 ::GetWindowThreadProcessId((HWND)hWnd,&dword);
 str.Empty();
 if (state==BST_CHECKED)
 { 
  str.Format(_T("%p"),dword);
 }
 else
 {
  str.Format(_T("%d"),dword);
 }
 m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_PROCESSID)->SetWindowText(str);
 //程序路径
 HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dword);
 TCHAR src[200];
 GetModuleFileNameEx(hProcess,NULL,src,199);
  m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_PROSRC)->SetWindowText(src);
}

======================================================================
效果图

======================================================================

好了 下面记录下游戏修改器
其实我用的方法很笨的,但是比较简单。改成功了植物大战僵尸中的太阳值。
=======================================================================
效果图

=======================================================================
这个游戏修改 就是读内存,值进行比较,然后找到一些跟你输入的值相同的地址,记录在链表中,然后让这个值变化,在对链表进行搜索
如果链表中的地址中的值也变化了,正确的地址就在这链表里,继续变化值,之后最后地址确定下来为止,地址确定下来之后就可以修改了。
其中用到得函数 先是 快照,(我在前面做任务管理器中写到过) 得到进程id 进程名等。
然后用openprocess打开方式用要可读,可写,或者获得所有权PROCESS_ALL_ACCESS。得到进程的句柄。
然后通过进程的句柄读进程中的数据ReadProcessMemory因为虚拟内存共有4gb  后2gb是系统用,还有前多少K(不同系统不一样)也系统用。所以我们只搜索前两gb ,但是前面那些系统的我们就忽略了,毕竟是小数,不在乎多读那点了。
ReadProcessMemory这个函数第一个参数是进程handle,第二个参数 是基址(即从那个位置开始读,是一个地址),第三个参数是读出的buff 第四个是读的大小。 由于内存页是4kb 我们为了读的速度快 所以我们每次就读4kb。 读出这4kb 放入buff中 然后 拿我们要找的数值比如是100,(我们假定我们的数是2字节),在4kb中1字节1字节的向后走,两字节两字节的比较 如果等于100则加入链表
DWORD dOneGB=1024*1024*1024;//1gb的地址
 DWORD dBase=0;//基址是0
 DWORD dOnePage=4*1024;//一个内存页4kb
 BYTE buffer[4*1024];//装一个内存也
 WORD value;
 CString str;
 int pos=0;
 POSITION listpos;
//得到我们窗口上输入的值 value
 GetDlgItem(IDC_EDIT_INPUT)->GetWindowText(str);
 value=_wtoi(str);
 for (dBase;dBase<dOneGB*2;dBase+=dOnePage)//遍历2gb每次 加一页  4kb
 {
  if(ReadProcessMemory(hProcess,(LPCVOID)dBase,buffer,4*1024,NULL))//读一个页,因为这个读取是不一定成功的所以加if(有的内存系统不让你读)
  { 
//进行比较 如果相同加入链表CList m_Data;
   for(DWORD b=0;b<dOnePage-1;b++)
   {
    WORD tempword=*((WORD *)(buffer+b));
    if (tempword==value)
    {
     if (pos==0)//如果是头结点就 加在头上,之后就加在后边
     {
      listpos = m_Data.AddHead(dBase+b);
      pos++;
     }
     else
     {
      listpos = m_Data.InsertAfter(listpos,dBase+b);
     }
    }
   }
  }
 }

这样这个第一次搜索就完成了。搜出了一堆 等于100的值 的地址,放入了链表
下次就是   改变100为150,然后再链表中搜索等于150的。
int dataCount=m_Data.GetCount();
 pp=m_Data.GetHeadPosition();
  for (int i=0;i<dataCount;i++)
  {
   DWORD tempvalue=m_Data.GetNext(pp);
//根据基址读出两个字节的数,然后跟value比较
   ReadProcessMemory(hProcess,(LPCVOID)tempvalue,&buff,2,NULL);
   if(buff==value)
   {
   if (head)
   {
    li.AddHead(tempvalue);
    head=FALSE;
   }
   else
   {
    li.AddTail(tempvalue);
   }
   }
  }
哈哈,然后最后就搜到了那个值得地址,,然后根据这个地址改变 其中的值就行了

WriteProcessMemory(hProcess,(LPVOID)address,&newValue,2,NULL);
思路倒是很简单,写的时候总会出错误,或是内存错误或是中断的,要耐心调调。
为了植物大战讲师的无限阳光,吼吼。go


 


陈晓 2011-08-09 15:06 发表评论

相关 [spy 游戏修改] 推荐:

spy++和游戏修改器

- 大宝PKU - C++博客-首页原创精华区
这几天做了两个东西,spy++ 和游戏修改器. spy++ 就是模仿 vs的那个工具spy++. 游戏修改器,就是暴力搜索内存,找到我们关心的数据,然后进行更改. 总之这些东西做过之后感觉就是都不难,但是在做的时候多少会感觉点吃力. 闲下来无事,记录下它们的过程吧. spy++ 分析(用vs2005做的——).

iOS遥控摄像车:Rover Spy Tank

- 阳阳 - 爱…稀奇~{新鲜:科技:创意:有趣}
各位,坐好了,今天要介绍的,将是一件拥有逆天级战斗力的玩具:. iOS遥控摄像车(Rover Spy Tank),有着超级牛逼的四大梦幻特性,(1)支持几乎全系列iOS设备,包括iPhone、iTouch和iPad,搭配免费的专用APP,即可以实现远程遥控操作;(2)拉轰的履带式结构,车体流线得堪比路虎极光,估计一般的坑洼是难不倒它的;(3)自带摄像头,并且可以将拍摄到的音频和视频实时回传至iOS设备上.

【总算上架】期待已久的“零零鼠”:Spy Mouse

- Mr.aa - 爱Apps - www.iapps.im
精选限时免费应用,由 AppPusher 为您送达. 无限精彩,尽在 爱Apps - www.iapps.im. 本站原创内容,转载时请务必注明出处,谢谢. 大小: 199 MB 系统: 3.0+. 正如昨晚预告的一样,现中国区已上架,想要血拼的朋友可以上了. 另外,美国区似乎还没有上架,根据EA的习惯,很可能会分开单独上架,请大家帮忙关注一下美国区的情况,谢谢.