Technical exchange, DH explanation.
Originally in writing this article, also wrote the War3 hanging tutorial, later because some things did not get.
Now the new year at home and nothing to continue to finish it. haha.
Do not think it is easy to write a hang, want to write a hang sure to understand the game AH.
Now let's see how the mines were produced.
Actually just I guess, after all, this game is not my writing ...
1 The user has chosen how much the chessboard, how many mines after
The chessboard should be stored in a two-dimensional array, and the number of mines must be stored with a global variable. Craved have any objections?
No, I went ahead and said ...
2 The generation of mines is definitely random, then the RAND function must be called.
A. First determine whether the number of mines is 0---is the 0-> end generation process
|
Not 0.
|
B.rand produces X,rand produces y
|
C. Determine if the value in the two-dimensional array (x, y) is a lightning value---not---go to B
|
Is
|
D. Number of mines minus one----------> go to a
The whole process is understood.
So let's actually analyze it, OD time, look at my BP rand from above and go to step B, as long as we get to step c, we'll know Ray's memory area, right?
We go through the area and we know which grids are thunder.
Next breakpoint:
When the breakpoint breaks down we can see the Stack window:
Select the first, and then enter. Return:
12345 |
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
|
A somewhat basic friend can be seen, here is it wrote a function, Rand one number first, and then divide the other number, return the result of the remainder.
Which of these 2 numbers is, the above figure we see 2 to return to, right? Then select the second carriage return chant.
Down, Single step: We will find that the stack is 1e=29, then it should be 30, we look at the row or column.
That is, this function passed in the parameter is the number of rows, haha, because of this C + +, so push that is in the pass parameter. Well, look at the specific parameters:
Now it can be seen that the RAND function parameters with the return address, $010036D2, and Rand out of the value of the number of rows to take the remainder, that is, [esp+4] is the 30, so that the final value is definitely less than 30.
12345678910111213141516 |
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
|
We know the above, and we'll take a look at a specific ray, what happens when we insert a little flag:
We executed to 010036E1 when we found out that ESI is $3 and 16,ecx is 16-3 is ray. We let the game run.
After this is set to a ray, the value of this memory is 8F. After the red flag is lit:
There's thunder and there's a red flag. This value is $8e. So what's the value of a red flag if there's no ray?
Haha, $0e. Remember. Let's get it sorted out.
1 with Thunder $8f
2 No Thunder $0f
3 Red Flag $FE
1 and 3 are carried out or, 2 and 3 are carried out or.
Well, it's Delphi.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
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
x
do
for j :=
1
to
y
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
;
|
Haha, read it out. Here's just the show. Next article, we go to find the click of call, and then implement auto-click. Hey, the second kill.
I'm DH and I'm talking so much today.
Http://www.cnblogs.com/huangjacky/archive/2010/02/20/1669643.html
DELPHI-XP Minesweeper Plug Making