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

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

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

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

  1. '_killboom.bas
  2. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
  3. ByVal lpWindowName As String) As Long
  4. Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, _
  5. lpdwProcessId As Long) As Long
  6. Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
  7. ByVal bInheritHandle As Long, _
  8. ByVal dwProcessId As Long) As Long
  9. Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, _
  10. lpBaseAddress As Any, _
  11. lpBuffer As Any, _
  12. ByVal nSize As Long, _
  13. lpNumberOfBytesWritten As Long) As Long
  14. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
  15. Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, _
  16. ByVal hdc As Long) As Long
  17. Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
  18. Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, _
  19. ByVal wMsg As Long, _
  20. ByVal wParam As Long, _
  21. ByVal lParam As Long) As Long
  22. Private Const PROCESS_ALL_ACCESS = &H1F0FFF
  23. Private Const WM_LBUTTONDOWN = &H201
  24. Private Const WM_LBUTTONUP = &H202
  25. Private Const WM_RBUTTONDOWN = &H204
  26. Private Const WM_RBUTTONUP = &H205
  27. '这些既是雷区的基址
  28. Private Const total_addr = &H10056A4
  29. Private Const height_addr = &H10056A8
  30. Private Const width_addr = &H10056AC
  31. Private Const area_addr = &H1005361
  32.  
  33. Public Function KillBoom() As Boolean
  34. '这个就是驱雷的函数了,废话 o.O!!
  35. Dim hwnd As Long
  36.  
  37. hwnd = FindWindow("扫雷", vbNullString)
  38. If hwnd = Then
  39. KillBoom = False
  40. Exit Function
  41. End If
  42.  
  43. Dim pid As Long
  44. Dim hp As LongCall GetWindowThreadProcessId(hwnd, pid)
  45. hp = OpenProcess(PROCESS_ALL_ACCESS, &, pid)
  46.  
  47. Dim total As Long
  48. Dim height As Long
  49. Dim width As Long
  50.  
  51. Call ReadProcessMemory(hp, ByVal total_addr, ByVal VarPtr(total), &, &)
  52. Call ReadProcessMemory(hp, ByVal height_addr, ByVal VarPtr(height), &, &)
  53. Call ReadProcessMemory(hp, ByVal width_addr, ByVal VarPtr(width), &, &)
  54.  
  55. Dim size As Long
  56. Dim mem() As Byte
  57.  
  58. size = * height +
  59. ReDim mem(size) As Byte
  60. Call ReadProcessMemory(hp, ByVal area_addr, ByVal VarPtr(mem()), size, &)
  61.  
  62. Dim i As Long
  63. Dim x As Long
  64. Dim y As Long
  65.  
  66. For i = To size -
  67. '至于为什么这么算,我也忘了,因为写这个代码时候太久远了
  68. '应该是一点点测算出来的
  69. '比如,16是距离窗体左侧的距离
  70. '97是距离窗体上方的距离
  71. x = i Mod
  72. y = i \
  73.  
  74. x = + x *
  75. y = + y * -
  76. If mem(i) = &H8F Then
  77. '如是雷,就插小红旗
  78. Call PostMessage(hwnd, WM_RBUTTONDOWN, &, MakeParam(x, y))
  79. Call PostMessage(hwnd, WM_RBUTTONUP, &, MakeParam(x, y))
  80. Else
  81. '不是雷,就点开它吧
  82. Call PostMessage(hwnd, WM_LBUTTONDOWN, &, MakeParam(x, y))
  83. Call PostMessage(hwnd, WM_LBUTTONUP, &, MakeParam(x, y))
  84. End If
  85. Next
  86.  
  87. Erase mem
  88. Call CloseHandle(hp)Call SetForegroundWindow(hwnd)
  89. KillBoom = True
  90. End Function
  91.  
  92. Private Function MakeParam(ByVal LoWord As Long, ByVal HiWord As Long) As Long
  93. MakeParam = (HiWord * &H10000) Or (LoWord And &HFFFF&)
  94. End Function

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

  1. '_hotkey.bas
  2. '这个模块就是在网上找到,链接如下
  3. '@http://www.cnblogs.com/rosesmall/archive/2012/09/19/2693707.html
  4. Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, _
  5. ByVal nIndex As Long, _
  6. ByVal dwNewLong As Long) As Long
  7. Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _
  8. ByVal nIndex As Long) As Long
  9. Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
  10. ByVal hwnd As Long, _
  11. ByVal Msg As Long, _
  12. ByVal wParam As Long, _
  13. ByVal lParam As Long) As Long
  14. Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, _
  15. ByVal id As Long, _
  16. ByVal fskey_Modifiers As Long, _
  17. ByVal vk As Long) As Long
  18. Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long
  19.  
  20. Public Const WM_HOTKEY = &H312
  21. Public Const MOD_ALT = &H1
  22. Public Const MOD_CONTROL = &H2
  23. Public Const MOD_SHIFT = &H4
  24. Public Const GWL_WNDPROC = (-)
  25. Private Type taLong
  26. ll As Long
  27. End Type
  28. Private Type t2Int
  29. lWord As Integer
  30. hword As Integer
  31. End Type
  32.  
  33. Public preWinProc As Long
  34. Public Modifiers As Long, uVirtKey As Long, idHotKey As Long
  35.  
  36. Public Function CallbackWndproc(ByVal hwnd As Long, _
  37. ByVal Msg As Long, _
  38. ByVal wParam As Long, _
  39. ByVal lParam As Long) As Long
  40. If Msg = WM_HOTKEY Then
  41. If wParam = idHotKey Then
  42. Dim lp As taLong, i2 As t2Int
  43. lp.ll = lParam
  44. LSet i2 = lp
  45. If (i2.lWord = Modifiers) And i2.hword = uVirtKey Then
  46. Call KillBoom
  47. End If
  48. End If
  49. End If
  50. CallbackWndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
  51. End Function

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

  1. Private Sub Form_Load()
  2. 'this code refered from following link
  3. '@http://www.cnblogs.com/rosesmall/archive/2012/09/19/2693707.html
  4. preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
  5. Call SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf CallbackWndproc)
  6. idHotKey = 'in the range &h0000 through &hBFFF
  7. Modifiers = MOD_ALT + MOD_SHIFT
  8. uVirtKey = vbKeyK
  9. Call RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
  10. Call Me.Hide
  11. End Sub
  12.  
  13. Private Sub Form_Unload(Cancel As Integer)
  14. Call SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
  15. Call UnregisterHotKey(Me.hwnd, uVirtKey)
  16. 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. Struts2 控制文件上传下载

    之前介绍servlet3.0新特性的时候有提到过servlet API提供了一个part类来实现对文件的上传和保存,Struts其实是在其基础上做了进一步的封装,更加简单易用.至于文件下载,Strut ...

  2. 实现图标Icon+文字在div里自动中心居中(水平垂直居中)

    已知div行高设置text-align:center文字会自动居中. 通过:before来设置icon的地址和高宽. 需要设置图片默认的垂直居中条件,与文字一致,为text-bottom. 设置图片行 ...

  3. 详解Centos默认磁盘分区

    对于有经验的Linux系统管理员,在安装系统之前都会对系统的分区进行规划:针对这一需求,下面就通过默认的Centos分区与大家分享一些关于Linux系统的知识.Linux系统的磁盘命名规范:硬盘类型标 ...

  4. git底层原理(二)

    git对象模型 在git系统中有四种类型的对象,所有的Git操作都是基于这四种类型的对象:"blob":这种对象用来保存文件的内容."tree":可以理解成一个 ...

  5. Spring 5.0.0.RC1 - CORS Support 【译文】

    3 CORS支持 3.1 介绍 出于安全考虑,浏览器禁止对当前源之外的资源进行AJAX调用.例如,当你在一个标签页检查你的银行账户时,你可以在另一个标签页打开evil.com的网站.在evil.com ...

  6. js的addEvertLIstener方法

    简介 “DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener() 和 removeEventListener(). public override f ...

  7. sql备份(.mdf文件备份)

    第一步: 右键需要备份的数据库(这里以MyDB为例),选择“属性”. 第二步: 选择“文件”,复制路径 第三步: 打开文件所在目录,复制MyDB.mdf和MyDB_log.ldf 第四步: 把数据库停 ...

  8. 网页中使用CSS和JS阻止用户选择内容

    CSS实现 body{ -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; ...

  9. 用js获取页面颜色值怎么比较?

    一般情况下,我们通过十六进制的方式设置页面颜色值 如#64e164 但当我们通过js获取这个dom颜色值的时候,返回的值却可能不是十六进制的,所以比较的时候需要分浏览器进行 在火狐和谷歌浏览器中,返回 ...

  10. myeclipse导入项目时出现Exploded location overlaps an existing deployment错误解决方法

    版权声明:本文为博主原创文章,转载时请注明原文链接. 今天拿别人的项目,在自己的软件上配置,通过tomcat添加项目时出现了 Exploded location overlaps an existin ...