我想了解关于逆向工程,使用的扫雷作为一个样本应用程序。我发现这个 MSDN文章 在一个简单的WinDbg命令,揭示了所有的地雷,但它是旧的,不是解释中的任何细节和真的不是我要找的。

IDA Pro解器WinDbg调试器 我已经加载winmine.exe 进入他们两个。有人可以提供一些实用的技巧,无论这些程序在条款中找到位置的数据结构表示雷场?

在WinDbg我可以断点,但是很难想象在什么时候要设置一个断点和存在什么位置。同样,当我看静的码在IDA亲,我不知道从哪里开始找到的功能或数据的结构表示的雷场。

是否有任何逆向工程师在计算器,可以点我在正确的方向?

有帮助吗?

解决方案

第1部分3


如果你是认真的进入反向工程忘了培训员和欺骗的引擎。

良好的反向工程,首先应了解操作系统、核心API职能,程序一般结构(什么是运行环,windows结构,事件的处理程序),文件格式(PE)。Petzold的经典"的编程窗",可以帮助(www.amazon.com/exec/obidos/ISBN=157231995X)以及在线MSDN。

首先你应该想一想,那里的雷区初始化程序可以被称为。我想如下:

  • 当你开启游戏
  • 当你点击高兴的脸
  • 当你点击游戏->新的或按F2
  • 当你改变水平的困难

我决定退F2加速器的命令。

找到加速处理代码你找到窗口信息处理程序(WndProc).它可以追溯到下通过如下和RegisterClass话。

阅读:

打开了开发协会,进口窗口,寻找"方法*",跳到它并且利用"跳外部参照以操作数(X)"的命令,看看它被称为。应该只有一个电话。

现在看上文对RegisterClass功能和它的参数WndClass.到.我已经叫功能mainWndProc在我的情况。

.text:0100225D                 mov     [ebp+WndClass.lpfnWndProc], offset mainWndProc
.text:01002264                 mov     [ebp+WndClass.cbClsExtra], edi
.text:01002267                 mov     [ebp+WndClass.cbWndExtra], edi
.text:0100226A                 mov     [ebp+WndClass.hInstance], ecx
.text:0100226D                 mov     [ebp+WndClass.hIcon], eax

.text:01002292                 call    ds:RegisterClassW

打输入功能,名称(使用'N',将其重命名为更好的东西)

现在看看

.text:01001BCF                 mov     edx, [ebp+Msg]

这是消息id,这种情况下F2按下按钮应该包含WM_COMMAND值。你是要找到它是比111h.它可以通过追查下edx在开发协会或通过 设定条件断点 在WinDbg和按F2在游戏中。

无论哪种方式导致的东西喜欢

.text:01001D5B                 sub     eax, 111h
.text:01001D60                 jz      short loc_1001DBC

右击111h和使用"象征性恒定的"->"使用标准符号常数",类WM_和进入。你现在应该有

.text:01001D5B                 sub     eax, WM_COMMAND
.text:01001D60                 jz      short loc_1001DBC

这是一个简单的方法,以找出消息id值。

了解加速处理检查:

这是一个相当大量的文字对于一个单一的答案。如果你有兴趣我可以写另一对夫妇的员额。长话短雷储存,作为一系列的字节[24x36],0x0F显示的字节不是使用(挥较小的领域),0x10空领域,0x80-我的。

第2部分3


好吧,让我们去F2按钮。

根据 使用键盘的促进剂 当F2按钮被按下wndProc功能

...收到WM_COMMAND或WM_SYSCOMMAND 信息。低阶的词 例如执行参数包含的 标识符的促进剂。

好吧,我们已经找到其中WM_COMMAND是处理,但如何确定相对应的参数包含的价值?这是哪里 资源的黑客 来发挥作用。喂它与二,它显示了你的一切。像是加速器表对我来说。

alt文本http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg

你可以在这里看到,这F2按钮相当于510中包含.

现在让我们回到代码,用于处理WM_COMMAND.它比较了包含不同的常数。

.text:01001DBC HandleWM_COMMAND:                       ; CODE XREF: mainWndProc+197j
.text:01001DBC                 movzx   eax, word ptr [ebp+wParam]
.text:01001DC0                 mov     ecx, 210h
.text:01001DC5                 cmp     eax, ecx
.text:01001DC7                 jg      loc_1001EDC
.text:01001DC7
.text:01001DCD                 jz      loc_1001ED2
.text:01001DCD
.text:01001DD3                 cmp     eax, 1FEh
.text:01001DD8                 jz      loc_1001EC8

使用上下文的菜单或'H'快捷键于显示小数值,并可以看到我们跳

.text:01001DBC HandleWM_COMMAND:                       ; CODE XREF: mainWndProc+197j
.text:01001DBC                 movzx   eax, word ptr [ebp+wParam]
.text:01001DC0                 mov     ecx, 528
.text:01001DC5                 cmp     eax, ecx
.text:01001DC7                 jg      loc_1001EDC
.text:01001DC7
.text:01001DCD                 jz      loc_1001ED2
.text:01001DCD
.text:01001DD3                 cmp     eax, 510
.text:01001DD8                 jz      loc_1001EC8 ; here is our jump

它导致码块,一些proc和出口wndProc.

.text:01001EC8 loc_1001EC8:                            ; CODE XREF: mainWndProc+20Fj
.text:01001EC8                 call    sub_100367A     ; startNewGame ?
.text:01001EC8
.text:01001ECD                 jmp     callDefAndExit  ; default

是的功能,发起新的游戏?找到了在最后的部分!敬请关注。

第3部分3

让我们看一看第一部分的功能

.text:0100367A sub_100367A     proc near               ; CODE XREF: sub_100140C+CAp
.text:0100367A                                         ; sub_1001B49+33j ...
.text:0100367A                 mov     eax, dword_10056AC
.text:0100367F                 mov     ecx, uValue
.text:01003685                 push    ebx
.text:01003686                 push    esi
.text:01003687                 push    edi
.text:01003688                 xor     edi, edi
.text:0100368A                 cmp     eax, dword_1005334
.text:01003690                 mov     dword_1005164, edi
.text:01003696                 jnz     short loc_10036A4
.text:01003696
.text:01003698                 cmp     ecx, dword_1005338
.text:0100369E                 jnz     short loc_10036A4

有两个值(dword_10056AC,uValue)读取到寄存器eax和ecx的且相比另一个两值(dword_1005164,dword_1005338).

看一看实际值使用WinDBG('bp01003696';在破'p eax;p ecx')-他们看起来像雷区的维我。玩的定义雷区的大小显示,第一对新的维和第二流的尺寸。让我们设置的新名称。

.text:0100367A startNewGame    proc near               ; CODE XREF: handleButtonPress+CAp
.text:0100367A                                         ; sub_1001B49+33j ...
.text:0100367A                 mov     eax, newMineFieldWidth
.text:0100367F                 mov     ecx, newMineFieldHeight
.text:01003685                 push    ebx
.text:01003686                 push    esi
.text:01003687                 push    edi
.text:01003688                 xor     edi, edi
.text:0100368A                 cmp     eax, currentMineFieldWidth
.text:01003690                 mov     dword_1005164, edi
.text:01003696                 jnz     short loc_10036A4
.text:01003696
.text:01003698                 cmp     ecx, currentMineFieldHeight
.text:0100369E                 jnz     short loc_10036A4

有点晚新的价值观复盖当前和子程序被称为

.text:010036A7                 mov     currentMineFieldWidth, eax
.text:010036AC                 mov     currentMineFieldHeight, ecx
.text:010036B2                 call    sub_1002ED5

当我看到它

.text:01002ED5 sub_1002ED5     proc near               ; CODE XREF: sub_1002B14:loc_1002B1Ep
.text:01002ED5                                         ; sub_100367A+38p
.text:01002ED5                 mov     eax, 360h
.text:01002ED5
.text:01002EDA
.text:01002EDA loc_1002EDA:                            ; CODE XREF: sub_1002ED5+Dj
.text:01002EDA                 dec     eax
.text:01002EDB                 mov     byte ptr dword_1005340[eax], 0Fh
.text:01002EE2                 jnz     short loc_1002EDA

我完全相信,我发现雷阵。因为周期的其inits360h字节的长度阵列(dword_1005340)与0xF.

为什么360h=864?还有一些提示以下行需要32个字节和864可分为32个,因此阵列可以保持27*32细胞(虽然UI允许最大的24*30个外地,有一个字周围的填充阵列边界)。

以下代码生成的雷区,顶部和底部边界(0x10字节)。我希望你可以看回路迭代,混乱;)我不得不用纸和笔

.text:01002EE4                 mov     ecx, currentMineFieldWidth
.text:01002EEA                 mov     edx, currentMineFieldHeight
.text:01002EF0                 lea     eax, [ecx+2]
.text:01002EF3                 test    eax, eax
.text:01002EF5                 push    esi
.text:01002EF6                 jz      short loc_1002F11    ; 
.text:01002EF6
.text:01002EF8                 mov     esi, edx
.text:01002EFA                 shl     esi, 5
.text:01002EFD                 lea     esi, dword_1005360[esi]
.text:01002EFD
.text:01002F03 draws top and bottom borders
.text:01002F03 
.text:01002F03 loc_1002F03:                            ; CODE XREF: sub_1002ED5+3Aj
.text:01002F03                 dec     eax
.text:01002F04                 mov     byte ptr MineField?[eax], 10h ; top border
.text:01002F0B                 mov     byte ptr [esi+eax], 10h       ; bottom border
.text:01002F0F                 jnz     short loc_1002F03
.text:01002F0F
.text:01002F11
.text:01002F11 loc_1002F11:                            ; CODE XREF: sub_1002ED5+21j
.text:01002F11                 lea     esi, [edx+2]
.text:01002F14                 test    esi, esi
.text:01002F16                 jz      short loc_1002F39

其余的子程序引左右边界

.text:01002F18                 mov     eax, esi
.text:01002F1A                 shl     eax, 5
.text:01002F1D                 lea     edx, MineField?[eax]
.text:01002F23                 lea     eax, (MineField?+1)[eax+ecx]
.text:01002F23
.text:01002F2A
.text:01002F2A loc_1002F2A:                            ; CODE XREF: sub_1002ED5+62j
.text:01002F2A                 sub     edx, 20h
.text:01002F2D                 sub     eax, 20h
.text:01002F30                 dec     esi
.text:01002F31                 mov     byte ptr [edx], 10h
.text:01002F34                 mov     byte ptr [eax], 10h
.text:01002F37                 jnz     short loc_1002F2A
.text:01002F37
.text:01002F39
.text:01002F39 loc_1002F39:                            ; CODE XREF: sub_1002ED5+41j
.text:01002F39                 pop     esi
.text:01002F3A                 retn

聪明的使用情况的WinDBG命令可以提供很酷的雷区甩(定义的尺寸9×9).检查边界!

0:000> db /c 20 01005340 L360
01005340  10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005360  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005380  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053a0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053c0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010053e0  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005400  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005420  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005440  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005460  10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
01005480  10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054a0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054c0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................
010054e0  0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f  ................................

嗯,看起来像我需要另一个后关闭的主题

其他提示

好像你正在试图拆开来源,但是你需要做的就是看看的存储空间的运行的程序。第六编 HxD 有一个功能,可以让你是这样。

http://www.freeimagehosting.net/uploads/fcc1991162.png

一旦你的存储空间中,这是一个问题采取的快照记忆的话你周围的混乱。隔离什么样的变化和哪些不可行。当你认为你有一个处理上数据的结构在于在六角的存储器,试图编辑,而它在存储器,并看看如果委员会改变为一个结果。

这个过程中你需要的不是不同于建设一个'训练'一个视频游戏。这些都是通常的基础上寻找其价值,如医疗和弹药生活在记忆和改变他们的飞行。你可能能够找到一些很好的教程,如何建立游戏培训。

看看这个代码项目的文章,它是一个小小的更深入的比博客你提到过。

http://www.codeproject.com/KB/trace/minememoryreader.aspx

编辑

和这一条,虽然不是关于扫雷的直接给你一个很好的一步一步的指导,狩猎通过存储器使用WinDbg:

http://www.codingthewheel.com/archives/extracting-hidden-text-with-windbg

编辑2

再一次,这不是关于扫雷,但它肯定已经给了我一些思考的食粮于我的记忆调试,有多种多样的教程:

http://memoryhacking.com/forums/index.php

此外,下载 CheatEngine (所提到的由尼克D)和工作,通过教程。

"在WinDbg我可以断点,但 这是我很难想象在 什么时候要设置一个断点并在 什么存储位置。同样,时 我看静的码在IDA亲我 不知道从哪里开始找 功能或datastructure, 表示雷场"。

确切地!

好吧,你可以看看程序就像是随机的()将调在建设的地雷表。此 本书 帮助我很多的时候我正在尝试逆向工程。:)

在一般情况下,良好的地方设置的断裂点的呼叫信息框中,呼吁发挥的声音、定时器和其他win32API程序。

顺便说一句,我的扫描扫雷,现在 OllyDbg.

更新: 尼莫 让我想起了一个伟大的工具, 欺骗动机 由Eric"黑字节"Heijnen.

欺骗动机(CE)是一个伟大的工具,用于观察和修改的其他进程的存储空间。在那之外 基本的 设施、CE有更多的特殊特点喜欢观看的拆卸存储的过程和注射代码成为其他进程。

(的 真的 值的,该项目是的,你可以下载的源代码-Delphi-和怎么看这些机制实施了-我没有,许多年前:o)

一个很好的文章在这个非常主题,可以发现在 不知情.它涵盖了扭转扫雷(作为一介绍向工程Win32应用程序)中相当详细和周围到处都是一个非常伟大的资源。

这个网站可能更有帮助:

http://www.subversity.net/reversing/hacking-minesweeper

一般的方式去这样做是:

  1. 在某种程度上得到源代码。
  2. 拆卸和希望剩下的符号可以帮助你。
  3. 猜测的数据类型,并试图操纵和利用记忆扫描仪,以限制的可能性。

在应对赏金

好吧,在二读时,它表现为虽然你想要一个指导如何使用一个调试器喜欢WinDBG而不是通常的问题是如何扭转工程师。我已经展示了你的网站,告诉你的价值你需要搜索,因此问题是,如何做你的搜索吗?

我使用的记事本,在这个例子因为我没有扫雷安装。但这个想法是相同的。

alt text

你的类型

s <options> <memory start> <memory end> <pattern>

新闻"?"然后"s"看到的帮助。

一旦你发现存储器模式要你想,你可以随后按alt+5带来了存储器的一个很好的展示。

alt text

WinDBG需要一些得到使用,但它不如任何其他调试器。

一个好的点开始追查在调试器,将是对老鼠。因此,找到主窗口程序(我认为工具,如spyxx可以检查窗户性质和事件的处理程序的地址是他们中的一个).打破这一点,并找到其它处理鼠标的事件--将有一个开关,如果您能认可它在汇编(看看值的WM_XXX对于小鼠在窗。h)。

把一个断点有和开始踏。之间的某个地方的时候,你获释的鼠标按钮和屏幕,更新royce将访问datastructure你正在寻找。

要有耐心,试图确定什么是正在做在任何给定的时间,但是不要打扰在找太深入的代码你怀疑是无用的,用于当前的目标。这可能需要几个运行调试器的指甲下来。

知识的正常win32工作流程应用程序也有帮助。

地雷可能会储存某些种类的两个维阵列。这意味着它可以是一系列指针或一个单C风格列布尔.

每当的形式收到的老鼠一起事件,这些数据结构上被引用。该指数将使用计算鼠协调,可能使整数部门。这意味着,你也许应该寻找一个 cmp 或类似的指令,其中一个操作数的计算使用偏移和 x, ,哪里 x 是的计算结果涉及整数部门。偏移后将指针向初的数据结构。

这是相当合理的假设的信息有关地雷奠定了连续存在至少进行(即这是一个2D阵,或者一系列的阵).因此,我将尝试打开几个相邻的细胞在同一行,使得存储器转储的过程,因为我去,然后他们的差异和寻找任何重复的变化,在同一区域内存(即1字节的改变的第一步,下一个字改为完全相同的价值在下一个步骤,等等)。

还有种可能性,它的一个拥挤的位阵列(3位,每矿应足以记录所有可能的国家关闭/开放、地雷/未地雷、标记/不旗),因此我看出来,也(该模式也将是重复的,虽然很难spot)。但它不是一个方便的结构来处理,并且我不认为存储器的使用是一个瓶颈扫雷,因此,它是不可能的,这种事会使用。

而不是严格意义上的"反向工程师的工具",以及更多的玩具,甚至是白痴像我这样的可能使用,检查了 欺骗动机.这使得它有点容易跟踪哪些部分的记忆已经改变,当时,甚至有规定的用于跟踪更改的存储器零部件通过的指针(虽然你可能不需要那)。一个很好的交互式教程被包括在内。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top