很久之前,那时候我还不太会玩(现在也不厉害)扫雷这个游戏,同学总在我面前炫耀自己的技术有多叼。“高级,99颗雷,只需三分钟。。。”,如此这般。也许确实需要天赋,我总要排查个半天才敢点下左键,然后就BOOM!

偶然一天,在网上浏览网页看到了一篇关于“扫雷外挂”的文章,记得那个人是用汇编写的,没记错的话应该是MASM32。文章大概意思是雷的布局是有标志的,雷区内目标值为0x8F的就是雷。要想找到所有雷的坐标,前提是先找到雷区的边界,即起始点、宽度和长度。如果不会反汇编(最起码能看懂二进制码),恐怕很难搞清楚。幸运的是那个高手就是这样的:他提供了雷区的基址。我这样的菜手只好拾人牙慧,拿来改改,用VB6实现了个“扫雷克星”。

注意:雷区的分布应该是在你点击第一下之后才确立的,所以玩的时候先打开扫雷随便点一个,再使用“扫雷克星”。

原理很简单,就不在赘述了,直接上代码:

'_killboom.bas
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, _
lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, _
lpBaseAddress As Any, _
lpBuffer As Any, _
ByVal nSize As Long, _
lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, _
ByVal hdc As Long) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205
'这些既是雷区的基址
Private Const total_addr = &H10056A4
Private Const height_addr = &H10056A8
Private Const width_addr = &H10056AC
Private Const area_addr = &H1005361 Public Function KillBoom() As Boolean
'这个就是驱雷的函数了,废话 o.O!!
Dim hwnd As Long hwnd = FindWindow("扫雷", vbNullString)
If hwnd = Then
KillBoom = False
Exit Function
End If Dim pid As Long
Dim hp As LongCall GetWindowThreadProcessId(hwnd, pid)
hp = OpenProcess(PROCESS_ALL_ACCESS, &, pid) Dim total As Long
Dim height As Long
Dim width As Long Call ReadProcessMemory(hp, ByVal total_addr, ByVal VarPtr(total), &, &)
Call ReadProcessMemory(hp, ByVal height_addr, ByVal VarPtr(height), &, &)
Call ReadProcessMemory(hp, ByVal width_addr, ByVal VarPtr(width), &, &) Dim size As Long
Dim mem() As Byte size = * height +
ReDim mem(size) As Byte
Call ReadProcessMemory(hp, ByVal area_addr, ByVal VarPtr(mem()), size, &) Dim i As Long
Dim x As Long
Dim y As Long For i = To size -
'至于为什么这么算,我也忘了,因为写这个代码时候太久远了
'应该是一点点测算出来的
'比如,16是距离窗体左侧的距离
'97是距离窗体上方的距离
x = i Mod
y = i \ x = + x *
y = + y * -
If mem(i) = &H8F Then
'如是雷,就插小红旗
Call PostMessage(hwnd, WM_RBUTTONDOWN, &, MakeParam(x, y))
Call PostMessage(hwnd, WM_RBUTTONUP, &, MakeParam(x, y))
Else
'不是雷,就点开它吧
Call PostMessage(hwnd, WM_LBUTTONDOWN, &, MakeParam(x, y))
Call PostMessage(hwnd, WM_LBUTTONUP, &, MakeParam(x, y))
End If
Next Erase mem
Call CloseHandle(hp)Call SetForegroundWindow(hwnd)
KillBoom = True
End Function Private Function MakeParam(ByVal LoWord As Long, ByVal HiWord As Long) As Long
MakeParam = (HiWord * &H10000) Or (LoWord And &HFFFF&)
End Function

为了更优雅些,再加上热键。这样玩的时候,输入快捷键(Alt+Shift+K)就秒杀,哈哈(略邪恶):

'_hotkey.bas
'这个模块就是在网上找到,链接如下
'@http://www.cnblogs.com/rosesmall/archive/2012/09/19/2693707.html
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, _
ByVal id As Long, _
ByVal fskey_Modifiers As Long, _
ByVal vk As Long) As Long
Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long Public Const WM_HOTKEY = &H312
Public Const MOD_ALT = &H1
Public Const MOD_CONTROL = &H2
Public Const MOD_SHIFT = &H4
Public Const GWL_WNDPROC = (-)
Private Type taLong
ll As Long
End Type
Private Type t2Int
lWord As Integer
hword As Integer
End Type Public preWinProc As Long
Public Modifiers As Long, uVirtKey As Long, idHotKey As Long Public Function CallbackWndproc(ByVal hwnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
If Msg = WM_HOTKEY Then
If wParam = idHotKey Then
Dim lp As taLong, i2 As t2Int
lp.ll = lParam
LSet i2 = lp
If (i2.lWord = Modifiers) And i2.hword = uVirtKey Then
Call KillBoom
End If
End If
End If
CallbackWndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function

最后是窗体部分,注册热键然后隐藏自己:

Private Sub Form_Load()
'this code refered from following link
'@http://www.cnblogs.com/rosesmall/archive/2012/09/19/2693707.html
preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
Call SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf CallbackWndproc)
idHotKey = 'in the range &h0000 through &hBFFF
Modifiers = MOD_ALT + MOD_SHIFT
uVirtKey = vbKeyK
Call RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
Call Me.Hide
End Sub Private Sub Form_Unload(Cancel As Integer)
Call SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
Call UnregisterHotKey(Me.hwnd, uVirtKey)
End Sub

搞定收工!另外,那个汇编大神请原谅我,因为实在记不清你文章的网址了,这里就没法贴出来了。

贴张图炫耀下:

终于能打败我同学了,可惜我已经毕业了。。。

PS:差点忘了,最好还是另外注册个热键(如Alt+Shift+Q)关闭自己,否则窗体隐藏了你也许会忘掉它的存在。我因为是在调试模式下,所以不需要 Orz

VB6之扫雷克星的更多相关文章

  1. jquery在线扫雷

    <扫雷>是一款大众类的益智小游戏,于1992年发行.游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷. 在线试玩 http://hovertree.com/te ...

  2. wpf版扫雷游戏

    近来觉得wpf做出来的界面很拉风,自己也很喜欢搞些小游戏,感觉这做出来的会很炫,很装逼,(满足自己的一点小小的虚荣心)于是就去自学,发现感觉很不错,可是属性N多,太多了,而且质料也少,很多不会用,只会 ...

  3. VB6史无前例的子类化之透明按钮

    [原创文章,转发请保留版权信息] 作者:mezstd 文章地址:http://www.cnblogs.com/imez/p/3299728.html 效果图: 请原谅笔者无耻地称之为史无前例,至少在笔 ...

  4. VB6与VB.NET对照表

    VB6与VB.NET对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1.It ...

  5. 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解

    '*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...

  6. VB6.0中,DTPicker日期、时间控件不允许为空时,采用文本框与日期、时间控件相互替换赋值(解决方案)

    VB6.0中,日期.时间控件不允许为空时,采用文本框与日期.时间控件相互替换赋值,或许是一个不错的选择. 实现效果如下图: 文本框txtStopTime1 时间框DTStopTime1(DTPicke ...

  7. VB6.0 和VB.NET 函数对比

    VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...

  8. MODI与VB6

    作者:马健邮箱:stronghorse_mj@hotmail.com主页:http://www.comicer.com/stronghorse发布:2016.12.16 在我写的<用MODI O ...

  9. vb6保存项目到c盘的安装目录

    工程保存在安装目录("C:\Program Files (x86)\Microsoft Visual Studio\VB98\errhandler1.vbp")里. 文件管理器找不 ...

随机推荐

  1. servlet context 和 servlet config

    servletConfig Servlet容器初始化一个servlet对象时,会为这个servlet对象创建一个servletConfig对象,该对象中包含了servlet的<init-para ...

  2. 开涛spring3(2.2) - IoC 容器基本原理及其helloword

    2.2.1  IoC容器的概念 IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IoC ...

  3. OpenCV探索之路(十六):图像矫正技术深入探讨

    刚进入实验室导师就交给我一个任务,就是让我设计算法给图像进行矫正.哎呀,我不太会图像这块啊,不过还是接下来了,硬着头皮开干吧! 那什么是图像的矫正呢?举个例子就好明白了. 我的好朋友小明给我拍了这几张 ...

  4. 详解Linux进程(作业)的查看和杀死

    目录: 引入进程 进程 线程 PS命令 TOP命令 其他查看进程命令 进程的优先级 作业控制机制 kill命令 一.引入进程 1.内存划分为:用户空间和内核空间 1.在用户空间里运行的进程,就是用户进 ...

  5. (数字IC)低功耗设计入门(六)——门级电路低功耗设计优化

    三.门级电路低功耗设计优化 (1)门级电路的功耗优化综述 门级电路的功耗优化(Gate Level Power Optimization,简称GLPO)是从已经映射的门级网表开始,对设计进行功耗的优化 ...

  6. linux新学篇

    [学会使用快捷键] Ctrl + C:这个是用来终止当前命令的快捷键,当然你也可以输入一大串字符,不想让它运行直接Ctrl + C,光标就会跳入下一行. Tab: 这个键是最有用的键了,也是笔者敲击概 ...

  7. android Activity Application Context 的区别

    用了这么久的Context,对于Context究竟是个什么玩意一直不是很明白.看了网上十几篇文章的介绍 加上自己的理解总结一下.(自己想法,不对勿喷,不想照搬网上一些文字说法来糊弄自己,自己理解的就这 ...

  8. jsp+servlet实现模糊查询和分页效果

    ---恢复内容开始--- 1.DAO+MVC包 2.DAO接口方法定义 package com.wanczy.dao; import java.math.BigDecimal;import java. ...

  9. 关于oracle数据库备份还原-impdp,expdp

    初始化: -- 创建表空间 CREATE TABLESPACE 表空间名 DATAFILE '文件名.dat' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNL ...

  10. Java基础——继承

    学习Java继承之前,我们想回忆一下Java面向对象需要特别注意的几个关键点. 面向对象是将复杂的事情简单化了,它通过封装的方式使得代码的重用性更高和安全性更强.平时我们要学会用面向对象的方式去思考, ...