Sources.RU Magazine Поиск по журналу
 

TopList

Сапер изнутри..

Автор: x2er0

Сегодня мы будем играть в замечательную игру "Сапер". Она идет вместе с ОС (У меня XP). Правила у нее просты - тыкай пока не проиграешь =))

Я пошутил - играть мы не будем, мы напишем АнтиСапер, т.е. программку, которая будет разминировать минное поле этого самого сапера!!!

Поехали..

Для начала скопируем из системной папки сам файл winmine.exe. Сначала осмотрим его внешне. Потыкаем по полю на угад .... ты попал на мину - проиграл, ну ладно, не беда! Смотрим верхнее меню, там есть пункт "Новая игра". Нажимаем и видим, что поле заполнено по новому!!! Давайте посмотрим, что происходит по выбору этого пункта....

Загружаем Сапера в W32Dasm:

видим, что ID этого пункта меню равен [ID=01FEh]. В поиске вбиваем это значениеи ищем... находим это:


01001DD3 |.3D FE010000 CMP EAX, 1FE
01001DD8 |.0F84 EA000000 JE 01001EC8

именно тут и происходит выбор ашего пункта, идем по этому адресу. А тут:


01001EC8 |>E8 AD170000 CALL 0100367A

Хорошо идем в эту процедуру... Она начинается так:


0100367A /$A1 AC560001 MOV EAX, DWORD PTR DS:[10056AC]
0100367F |.8B0D A8560001 MOV ECX, DWORD PTR DS:[10056A8]

По этим адресам лежат число клеток по X и Y, они (эти адреса нам понадобятся!). Шагая по этой подпрограмме можно найти адрес с которого начинается рэндомно запоняющаяся карта... у меня он равен: 01005360h. Ну и начиная с этого адреса идут клетки поля, если в них находиться значение 8F, значит тут мина, иначе стоит FF, а начало и конец строки определяются как 10h, причем строчки находятся друг от дргуа на интервале 20h.

Этого нам достаточно для написания программы, приступим:

на форме находится sg: TStringGrid...

Вот код:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TPole = record
    x: Byte;
    y: Byte;
  End;

type
  TForm1 = class(TForm)
    Button1: TButton;
    sg: TStringGrid;
    procedure Button1Click(Sender: TObject);
  private
    SapMap: Tpole;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var
  hWn: HWND;
  PID, hProc, dwReaded: DWord;
  buf: Byte;
  i, r: Dword;
  StartAddr: Dword;
begin
  hWn := HWND(FindWindow(nil, PChar('Сапер')));
  If IsWindow(hWn) Then
  Begin
     GetWindowThreadProcessId(hWn, PID);
     hProc := OpenProcess(PROCESS_VM_READ, False, PID);
     Try
     If (hProc <> 0) Then
     Begin
        ReadProcessMemory(hProc, ptr($10056AC), @buf, 1, dwReaded);
        SapMap.x := buf;
        ReadProcessMemory(hProc, ptr($10056A8), @buf, 1, dwReaded);
        SapMap.y := buf;

        sg.ColCount := SapMap.x;
        sg.RowCount := SapMap.y;
        For i := 0 To (sg.ColCount - 1) Do
           For r := 0 To (sg.RowCount - 1) Do sg.Cells[i,r] := ' ';

        StartAddr := $01005361;
        For i := 0 To (SapMap.y - 1) Do
        Begin
          For r := 0 To (SapMap.x - 1) Do
          Begin
             ReadProcessMemory(hProc, ptr((i*$20) + StartAddr + r), @buf, 1, dwReaded);
             If (buf = $8F) Then sg.Cells[r, i] := 'X';
          End;
        End;

     End;
     Finally
       CloseHandle(hProc);
     End;
  End;
end;

end.

А вот результат ее работы (на рисунке):


Удачи!!!



 Design by Шишкин Алексей (Лёха)  ©2004-2008 by sources.ru