技术交流,DH讲解.

本来之前就在写这个文章,还写了War3挂的教程,后来因为一些事就没有弄了.
现在过年在家又没有事就继续把这个写完吧.哈哈.
不要以为写个挂很容易,要想写个挂肯定要了解游戏呀.
我们现在来了解下地雷是怎么产生的?
其实只是我自己猜想的,毕竟这个游戏不是我写的...
1 用户选择了多大的棋盘,多少地雷后
棋盘应该是用一个二维数组来存储的,地雷数肯定是用一个全局变量来存储的.这点儿有异议没有?
没有我就继续往下说了...
2 生成地雷,肯定是随机的,那么一定会调用Rand函数咯.
a.首先判断地雷数是否为0 ---是0->结束生成过程
      |
   不是0
      |
b.Rand产生X,Rand产生Y                                       
      |                                                                 
c.判断二维数组中(X,Y)的值是否为有雷值---不是-->转到b
      |
     是
      |
d.雷数减一---------->转到a
整个流程看懂了吧. 
那么我们来实际分析呀,OD Time,从上面看我bp Rand然后进入步骤b,只要到了步骤c我们就能知道雷的内存区域了,是吧?
我们遍历区域就知道哪些格子是雷了塞.
下断点: 
当断点断下来了后  我们可以看到堆栈窗口:
 
选中第一个,然后回车.返回:

1
2
3
4
5
01003940  /$  FF15 B0110001 call    dword ptr [<&msvcrt.rand>]       ; [rand
01003946  |.  99            cdq
01003947  |.  F77C24 04     idiv    dword ptr [esp+4]
0100394B  |.  8BC2          mov     eax, edx
0100394D  \.  C2 0400       retn    4

有点儿基础的朋友可以看出来,这里是它写了一个函数,先Rand一个数,然后整除另一个数,返回取余的结果.
其中这2个数是什么,上面那图我们看见2个返回到,是吧?那么选中第二个回车呗.
 
下断,单步走:我们就会发现压入栈的是1E=29,那么应该是30个,我们看一下是行还是列.
 
也就是这个这个函数传入的参数是行列数,哈哈因为这个C++的,所以PUSH那一下就是在传参数.好的看具体参数:
 
现在可以看出来,rand函数的参数用的返回地址,$010036D2,而rand出来值再对行列数取余,也就是[esp+4]就是这个30,这样就保证,最后这个值肯定小于30咯.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
010036C7  |> /FF35 34530001 push    dword ptr [1005334]              ;  将列数压入栈,发现存列的内存地址了
010036CD  |. |E8 6E020000   call    01003940                         ;  返回X
010036D2  |. |FF35 38530001 push    dword ptr [1005338]              ;  将行压入栈,发现存行的内存地址
010036D8  |. |8BF0          mov     esi, eax                         ;  esi就是X
010036DA  |. |46            inc     esi                              ;  因为rand是0~n-1,所以这里就要+1
010036DB  |. |E8 60020000   call    01003940                         ;  返回Y
010036E0  |. |40            inc     eax
010036E1  |. |8BC8          mov     ecx, eax                         ;  ecx就是Y
010036E3  |. |C1E1 05       shl     ecx, 5                           ;  将Y*32,这样就转换成一维数组
010036E6  |. |F68431 405300>test    byte ptr [ecx+esi+1005340], 80   ;  我们这里发现数组的基址了.$80就是有雷咯
010036EE  |.^ 75 D7         jnz     short 010036C7
010036F0  |. |C1E0 05       shl     eax, 5
010036F3  |. |8D8430 405300>lea     eax, dword ptr [eax+esi+1005340]
010036FA  |. |8008 80       or      byte ptr [eax], 80
010036FD  |. |FF0D 30530001 dec     dword ptr [1005330]              ;  减少雷总数
01003703  |.^\75 C2         jnz     short 010036C7

我们知道上面这些,我们就来看看具体某一个雷,当我们插了小旗子后有什么变化没有:
我们执行到010036E1这句时候发现:esi是$10也就是16,ecx是3,那么16-3是雷.我们让游戏运行起来.
 
将这个设置成有雷后,这个内存的值就是8F了.点上红旗后:
 
有雷且有红旗这个值就是$8E.那么要是没有雷又被点了红旗会是什么值呢?
 
哈哈,$0E吧.记住了吧.我们来整理下.
1 有雷 $8F
2 无雷 $0F
3 红旗 $FE
1和3进行或,2和3进行或.
好,该Delphi了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
procedure TForm3.Button1Click(Sender: TObject);
var
  pid:Integer;
  h:Cardinal;
  x,y:Integer;
  readed:Cardinal;
  Count:Cardinal;
  I: Integer;
  j: Integer;
  buf:array of Byte;
begin
  edt1.Text:='';
  edt2.Text:='';
  mmo1.Clear;
  //查找扫雷游戏的PID
  ProcessList.Snap;
  pid:=ProcessList.FindPID('winmine.exe');
  if pid = -1 then
    Exit;
  //打开进程
  h:=OpenProcess(PROCESS_ALL_ACCESS,False,pid);
  if h = 0 then
    Exit;
  try
    //取得游戏的行列数
    readed:=0;
    ReadProcessMemory(h,Pointer($1005334),@Count,4,readed);
    if readed>0 then
    begin
      edt1.Text:=IntToStr(Count);
      x:=Count;
    end;
    readed:=0;
    ReadProcessMemory(h,Pointer($1005338),@Count,4,readed);
    if readed>0 then
    begin
      edt2.Text:=IntToStr(Count);
      y:=Count;
    end;
    //获取雷数组内存区域的大小
    Count:=Y shl 5 + X;
    SetLength(buf,Count);
    //读取雷内存
     ReadProcessMemory(h,Pointer($1005340),buf,Count,readed);
    //循环判断
    for I := 1 to do
      for j := 1 to do
        if buf[32*J + I] = $8F then
        begin
          mmo1.Lines.Add(Format('雷:列:%D,行:%D',[i,j]));
          buf[32*J + I]:= $8E;
        end;
    //写回去,这样小红旗都标记出来了....
    WriteProcessMemory(h,Pointer($1005340),buf,Count,readed);
  finally
    CloseHandle(h);
  end;
end;

 
哈哈,读取出来了吧.这里只是显示.下一篇文章,我们去寻找点击的call,然后实现自动点击.嘿嘿,秒杀.

我是DH,今天就讲这么多了.

http://www.cnblogs.com/huangjacky/archive/2010/02/20/1669643.html

Delphi - XP扫雷外挂制作的更多相关文章

  1. 【QT】找茬外挂制作

    找茬外挂制作 找茬游戏大家肯定都很熟悉吧,两张类似的图片,找里面的不同.在下眼神不大好,经常瞪图片半天也找不到区别.于是乎决定做个辅助工具来解放一下自己的双眼. 一.使用工具 Qt:主要是用来做界面的 ...

  2. C#简单游戏外挂制作(以Warcraft Ⅲ为例)

    网上有很多外挂制作的教程,大多是讲针对大型网络游戏的,主要包含一些抓包.反汇编.C++的知识综合.事实也如此,常见的外挂都是使用VC++写的,从来没有过C#或者其他.NET语言编写的外挂. 作为微软. ...

  3. 在XP下基于VHD版XP 2003 win7制作的RAMOS心得

    在XP下基于VHD版win7制作的RAMOS心得1.用DiskGenius创建1.85G的VHD固定磁盘文件,以win7prosen.vhd为例,然后进行分区格式化,格式化时启用NTFS压缩.2.为了 ...

  4. 扫雷游戏制作过程(C#描述):第二节、界面设计

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 扫雷界面设计 界面的设计,首先需要创建一个菜单栏.具体方法在左边找到工具箱窗口,展开其中的菜单和工具栏,找到MenuStrip选项,双 ...

  5. 扫雷游戏制作过程(C#描述):第五节、菜单操作(续)

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 发布版已经分享到百度网盘 菜单操作(续) 接着节前一章节的内容,我们继续完善菜单栏的功能. 我们首先,先完善Rank的选项,我们希望我 ...

  6. 扫雷游戏制作过程(C#描述):第一节、创建项目

    前言 起初做扫雷是同学在做,我也跟着做了.做的比较low,其实第一次做这种东西,自己对自己的要求也不高,注重在了解一下,一个app应用程序是怎么产生的..net开发平台,用c#敲的.建议大家一些不懂的 ...

  7. 《windows程序设计》学习_3.3:利用xp扫雷资源

    #include<windows.h> #include "resource.h" LRESULT CALLBACK WndProc (HWND, UINT, WPAR ...

  8. 扫雷游戏制作过程(C#描述):第四节、菜单操作

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 菜单操作 我们现在的程序单击菜单的时候不会有任何反应,这一节我们主要介绍菜单的相关代码,使得菜单能够正常使用. 现在我们希望在对应级别 ...

  9. 扫雷游戏制作过程(C#描述):第三节、雷区绘制

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 绘制雷区 这一节我们主要涉及界面中雷区的绘制.绘制雷区需要三个变量来保存雷区行数.列数.以及地雷的数量.而且我们希望能够自动获取上次游 ...

随机推荐

  1. iOS 开发 Message Digest Algorithm 5(MD5加密)

    MD5的全称是Message Digest Algorithm 5(消息摘要算法第五版),是计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.在90年代初由MIT Laboratory ...

  2. java实现文件夹(包括其中的子文件夹、子文件)的复制——递归

    这是学校java课的一道实验题,题目如下:编程,根据指定的源和目标位置,完成指定文件或文件夹(包括其中的子文件夹.子文件)的复制. 以下是我的实现,使用了递归: package com.simon.m ...

  3. C++获取当前时间和计算程序运行时间的方法

    C++获取当前时间和计算程序运行时间的方法 获取当前时间: #include <iostream> #include <Windows.h> using namespace s ...

  4. Cin、Cout 加快效率方法

    std::ios::sync_with_stdio(false); 在main 函数中加上这么一句话. 可以打消iostream的输入输出缓存,可以节省许多时间,使效率与scanf与printf相差无 ...

  5. POJ 2479 不相交最大子段和

    题目意思还是很好理解的,在一个数列中,找出不相交的两个子串使得其和最大. 解题思路: 对于每个i来说,求出[0 ~ i - 1] 的最大子段和以及[i ~ n - 1]的最大子段和,在加起来,求最大的 ...

  6. jquery ajax json 数据的遍历

    需求:进行ajax请求后,后台传递回来以下json数据 { "data":[ {","name":"选择A","valu ...

  7. JavaEE Tutorials (3) - 企业bean

    3.1什么是企业bean383.1.1企业bean的好处393.1.2何时使用企业bean393.1.3企业bean类型393.2什么是会话bean393.2.1会话bean类型403.2.2何时使用 ...

  8. QTP的基本功能介绍

    • QTP的基本功能介绍 HP QuickTest Professional 支持功能測试和回归測试自己主动化,用于每一个主要软件应用程序和环境.此解决方式使用keyword驱动的測试概念,简化了測试 ...

  9. 网页制作之html基础学习5-background-position用法

    我们知道在用图片作为背景的时候,css要这样写,以div容器举例子,也可以是body.td.p等的背景,道理一样. 代码: div{ background:#FFF url(image) no-rep ...

  10. C++的运算符

    C++的运算符十分丰富,使得C++的运算十分灵活方便.例如把赋值号(=)也作为运算符处理,这样,a=b=c=4就是合法的表达式,这是与其他语言不同的.C++提供了以下运算符: 算术运算符+(加)  - ...