C#写的QQ找茬外挂

    技术2022-05-13  7

     

          这个暑假转眼就要过完了。本来打算在学校干两件事:学车和竞赛,结果竞赛没能杀进全国总决赛,想想也是意料中的事。学车就更郁闷了,从上学期开学报名到科目一考试,足足等了近五个月。终于摸到真车了,结果每天冒着酷暑跑到北校去,真正开车的时间还不到来回走路的时间!这也就算了,断断续续学了几次,到现在还没安排考试,真是无语。

             虽说那个竞赛没抱多大希望,但终究感觉有点遗憾。那个项目断断续续花了我一个学期的时间,一有空就到网上找资料、敲代码、调试,从刚开始的毫无头绪,到后来终成雏形,确实花了我不少心血。虽然没进决赛,也学到了很多东西。初赛结果出来后,一直没精打采的,连老师交代的最后论文也懒得写了,每天感觉浑浑噩噩的,不知道该干啥。好几次拿起那本人工神经网络的书,看了几行就撑不下去了。有时有随便翻翻数字图像处理的书,Silverlight的书也看了几页,总觉得没多大动力。这几天实在闲得无聊了,突然想起曾经打算写的QQ找茬外挂,当时由于各种原因搁下了。闲着也是闲着,那就动手吧。

             以前也看到室友用过一个外挂,它必须将游戏窗口对准到屏幕左上角,感觉有点不方便,另外下了一个,必须在全屏下才能使用。何不自己写一个呢?要解决的核心问题主要有:

             一、截取活动窗口(就是游戏窗口)的图片;

           二、图像对比;

             三、图像差别提示;

             四、监视全局键盘事件;

            

    由于我用的是C#语言,而以上问题牵涉到很多平台底层的调用,因此用到了托管平台和非托管平台的互操作。第一个问题好解决,首先用GetForegroundWindow()获取当前活动窗口,也就是游戏窗口的句柄,然后计算出它的屏幕坐标,再用PicPick截图工具里的坐标轴工具量出了找茬窗口里的两张图片的坐标,再用BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, UInt32 dwRop)函数截取桌面某个矩形区域并保存为Bitmap。这个问题的关键是要算准坐标位置,误差不能太大,否则后面的图像对比就有很大问题。这个可以通过保存两张截图到同一目录下,然后用图片查看器连续翻看两张图片,确定两张图片大部分是重合来解决。不行的话再微调。

    两张图片都截下来后,进入第二个问题。先把两张图片相减,得到差图,再二值化,最后计算差图里有多少个连通区域,这些区域就是要找的茬。这里要把握好二值化的阈值,太大了会使区域面积变小,那个茬就不明显了。连通区域找到后,返回这些区域的矩形表示,为后面的差别提示做准备。这些操作可以自己写代码,但我用的是AForge.net,一个开源的数字图像处理框架,里面包含了大部分的图像处理算法的实现,拿来用就是了。在这里顺便崇拜一下框架的作者Andrew Kirillov,写出了这么优秀的库。有空一定多看看框架的源码。

    前面两步完成后,最大的问题来了:怎么在游戏窗口里的美女图片上显示这些“茬”呢?关于这个问题,我做了N多尝试,GoogleN次,终于在一个英文论坛里找到了比较合适的解决办法。最先想到的是直接在桌面上找准位置,然后绘图。但是,这个方法致命的缺点是画面保存不了,原因是游戏窗口是不停地发生重绘的,这导致桌面也发生重绘,那么你画 的图自然就被擦掉了。那么能不能用循环,让它多画几次,这样就能长时间显示呢?答案是不行,这样会导致严重的闪烁,而且内存消耗很大。这让我想到了窗口的Paint事件,在Paint事件处理函数内画图,就会让图形保持。但桌面是个什么东西?是不是Form?有点像,但又不太正宗。况且,怎么获得一个桌面的Form对象?桌面的句柄可以通过GetDC()获取,但从句柄创建Form对象就不好弄了。虽然Form类的父类Control有个FromHandle方法,可以返回Control对象,但如果用这种方法直接从桌面句柄创建Form对象,编译器会说这是“未将对象的引用设置到对象的实例”,也就是说这样产生的不是实例。找了很久都没发现怎么创建桌面Form对象,于是只好放弃这个方法。之后,我又尝试着为每个“茬”的矩形区域处放置一个窗口,当然这是一个没有标题栏和状态栏的Form,然后添加鼠标事件处理,让鼠标一进入就隐藏窗口,以便可以点击到窗口下面的图像。这个办法太笨了,貌似行得通,但有很多细节问题会让你头大。最后还是放弃了。昨天,在一个英文论坛上,偶然看到一个帖子,正好是解决如何在桌面绘图并保持的。这里插一句,用Google中文搜不到时,尝试一下英文,可能会有你意想不到的收获。那位仁兄的解决办法是这样的:创建一个透明窗口!然后在上面画图!就这么简单!我马上尝试了这个办法,果然有效,设置FormTransparentKey属性为某种颜色,那么窗口客户区内这种颜色的区域将会透明,不仅透明,还可以用鼠标操作窗口背后的窗口,而这正是我想要的!把“茬”区域用某种颜色绘制到透明窗口上,然后设置它的TransparentKey属性,再将它的背景色设置成其他颜色,透明度调节一下,否则这些区域背后的图就看不到了。这样一来,只有“茬”区域完全透明显示,而且可以用鼠标点击游戏图片,其他区域半透明,并且挡住了鼠标。另外要注意的就是要将透明窗口设置为总在最前面(用SetWindowPos() API,就像视频播放器那样,否则一点图片就看不到它了。这样找茬就方便了!

    最后一个问题(其实按解决顺序并不是最后一个),要用Windows全局钩子来实现。关于钩子(Hook)编程,孙鑫老师有很详细的讲解,看看他的视频教程就好了。Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。又是互操作,在新线程中设定钩子,一直监视键盘行为,当敲打空格键时(我设定的),执行自动找茬工作,所有的不同点一目了然!玩家要做的,点击鼠标而已。当然,也有失效的时候,当只是颜色相差不大时,有时会找不到。

         至此,大功告成!现在,找茬变得再简单不过了。偶尔作下弊,感受一下虚荣心,嘿嘿。

     

     

     


    最新回复(0)