镇北看雪 发表于 2020-5-8 20:48

Window扫雷逆向破解与外挂教程

本帖最后由 镇北看雪 于 2020-5-9 08:40 编辑

最近在学习hook技术与DLL注入技术,所以就做了个扫雷辅助来练习一下顺便和大家分享一下。
(觉得不错记得pf,快升级了哦)
——————————————————————————————————————————————



[*]工具:CE,OD


[*]破解思路:


[*]先用CE打开程序,想要破解掉扫雷的计时需要找到时间存储到内存的什么地方。
   利用CE我们找到时间存在0x0100579C ,如果我们要想改变时间只需改变此内存地址下的值即可。



   2.我们用OD打开程序,由0x0100579C 存放时间的内存入手。我们在od的数据窗口搜索此内存地址,此时没有开始游戏其值为0。
      我们再此地址处设置内存写入断点,然后运行程序。(我们知道只要没有踩到雷子,时间值会一直增加的,我们需要知道其值增加处的逻辑)



   3.运行程序后点击任意一个方块,游戏开始后程序暂停。我们发现这里是游戏计时的初始化逻辑,
   当时间内存值加1后,通过SetTimer()设置一个计时器, 每一秒发送一条WM_TIME消息来达到计时的目的。



    4.我们继续运行程序,程序又暂停下来了。这里就应该是时间值增加处的逻辑了。
    此处逻辑为:当 0x01005164内存处的值不为0 或者 时间没有超过999时,时间值加1。
   时间没有超过999时,时间加1我们可以理解。但是0x01005164 的值不为0时,时间值加1是什么意思呢?
   我们知道当我们踩到雷游戏结束时,时间会停止。那意思是不是0x01005164的值为1表示游戏是否结束呢?我们验证一下。



    5. 为了验证0x01005164 处的值为0表示我们踩到雷子游戏结束,我们需要在数据窗口跟踪此地址的值。
      因为我们才点击一个方块,所以不可能踩到雷子。此时此地址处值为1,我们先取消时间内存处的内存写入断点继续运行程序,并点击方块知道踩到雷子为止。



      当踩到雷子游戏结束时,我们发现0x01005164 地址处的值变成了0,所以我们的猜想是正确的。



    6.现在我们在0x01005164地址处下内存写入断点,重新运行程序。不断点击方块当踩到雷子时,程序暂停。
      我们发现 暂停处指令为:and dword ptr ds:,0x0 此地址处的内存的值将被设置为0,意味着游戏将结束。


    我们返回上层函数(栈中对应函数右击反汇编跟随),发现主要逻辑。在关键跳转处下断点,再次运行程序并使踩到雷时程序停在此关键判断处。
    当跳转执行时就会跳到使 内存0x01005164 值为0的代码处(表示踩到了雷,游戏结束)。而此跳转要想不执行需要内存0x010057a4地址处的值为0,
   我们在数据窗口中查看此地址处值为3,正好为我们已经消除的方格。(意思是如果是第一次点击,那么即使踩到雷也不爆)所以我们知道了为什么我们第一次点击永远不会踩到雷的原因了。


   我们继续往上看此处代码,我们发现je 01003595代码可以跳过使内存0x01005164 值为0的代码(表示踩到了雷,游戏结束),意思就是我们没有踩到雷。
   分析此处代码:其是将0x1005340 + esi + ecx 内存处的值与0x80进行与运算,如果等于0表示没有踩到雷。

01003512/$8B4424 08   mov eax,dword ptr ss:
01003516|.53            push ebx
01003517|.55            push ebp
01003518|.56            push esi
01003519|.8B7424 10   mov esi,dword ptr ss:
0100351D|.8BC8          mov ecx,eax
0100351F|.C1E1 05       shl ecx,0x5
01003522|.8D9431 405300>lea edx,dword ptr ds:
01003529|.F602 80       test byte ptr ds:,0x80
0100352C|.57            push edi
0100352D|.74 66         je X01003595                              ;winmine.01003595
0100352F|.833D A4570001>cmp dword ptr ds:,0x0
01003536|.75 50         jnz X01003588                               ;winmine.01003588


    7.我们在关键判断处下断点,重新运行程序并在数据窗口中搜索0x1005340。


    重新运行程序后,点击一个方格。当程序停在此断点时,我们看到对应0x1005340 + esi + ecx 内存处的值为0 ,其与0x80与运算的值为0。
    跳转将会执行,所以表示此次点击处无雷。




   我们需要知道esi与ecx是怎么计算得来的,我们发现 ecx与esi都是由两个参数计算得到的,那这俩个参数代表什么意思呢?
   
    我们在反汇编窗口中查看上一层函数后,在函数入口下断点。然后重新运行程序,并点击方格。程序停在此处发现两个参数分别是eax, ecx。
    我们继续往上层函数回溯。发现到达了消息回调函数处。





我们发现其相应的是鼠标左键松开,我们先在对应函数入口下断点,然后重新运行程序,点击方块来到此断点处。    F7进入此函数分析ecx与eax怎么产生的。

F7进入此函数后F8向下单步我们发现ecx == ,eax ==



   我们重新运行,在数据窗口中中搜索这两处地址,并设置内存写入断点。

   并点击方块。程序会停止,此处应该是两处地址初始化代码。


继续执行,程序在一个函数中再次断下。发现参数1(arg.1) == ,参数2(arg.2 ) == .

我们回溯到上层函数看参数1,和参数2是怎么产生的。
发现参数1和参数2的算法。我们在函数入口下断点。


我们重新运行程序,点击方块后程序停在此处。可以看到参数1和参数2的算法,arg.4是消息回调函数的参数4(lParam).
因为此处是点击鼠标左键的消息,所以参数4表示鼠标点击的坐标,我们可以得知,参数1和参数2实际是我们点击方格在坐标。



致辞我们可以得知0x1005340 + esi + ecx   的esi与ecx是由我们点击方格行和列产生的,所以0x1005340地址处就是和方格一一对应的。




0x10应该表示墙,但是当其值为0x80时才表示无雷,为什么好多都是0x0f和0x8f呢?(说明在判断之前还进行了判断。)我们在第一个方格处设置内存写入断点。
第一个方格对应的内存地址为0x10005361.然后我们重新运行程序,并点击第一个方格。程序暂停
因为只有0x1005361地址处的值为0x80才表示无雷,我们由此处算法可得:当对应方块原始的值为0xf时经过运算会使其地址处值为0x80,如果原始值为0x8f则经过运算后会使其地址处值为0。


所以我们得:如果方块对应的地址处的值为0xf则表示此处无雷。如果为0x8f则表示有雷。




程序分析完了:下面就是外挂破解思路,很简单。
F3一键通关思路:
我们通过判断对应地址是否为0xf(是否无雷),决定是否向程序发送单击消息。
F4清零时间:
直接改变对应时间内存的值为0
效果:



下面是游戏链接,和外挂dll文件以及源程序,以及我自己写的dll注入工具。(全部都打包了)
dll注入成功,按F3一键通关,F4清零时间
链接:https://pan.baidu.com/s/1j0o7geZyUmOEO0VbXU-xEg
提取码:jrng

8204118 发表于 2020-6-7 20:03

我的提示这个 打不开

llxpeter 发表于 2020-5-8 21:09

没想到扫雷都有外挂了{:1_886:}

hongshen233 发表于 2021-6-14 10:22

楼主,网盘文件失效了。能否重发一下?另外期待你的DLL注入器的编写教程

细水流长 发表于 2020-5-8 21:02

拉玛西亚 发表于 2020-5-8 21:08

啥都能分享的非常透彻,新的例子可以参照一下自己尝试研究了

镇北看雪 发表于 2020-5-8 21:08

细水流长 发表于 2020-5-8 21:02
将je 01003595 这段nop掉是不是也可以呢?表示即使踩到了雷也不会结束

玩法多了,主要看你想怎么玩。这里直接nop不可以,因为下面还有一处跳转

CQLYES 发表于 2020-5-8 21:10

扫雷也要教程呀,哈哈

javporn 发表于 2020-5-8 21:16

深爱我的女孩 发表于 2020-5-8 21:17

有文字教程真好,先收藏,改天抽时间学习!

badou0332 发表于 2020-5-8 21:19

谢谢楼主分享

xiao5603 发表于 2020-5-8 21:21

楼主威武
{:1_893:}
页: [1] 2 3 4 5 6
查看完整版本: Window扫雷逆向破解与外挂教程