Как мне найти в памяти структуру данных, представляющую мой макет «Сапера»?

94

Я пытаюсь изучить реверс-инжиниринг, используя Minesweeper в качестве примера приложения. Я нашел эту статью MSDN о простой команде WinDbg, которая обнаруживает все мины, но она устарела, не объясняется подробно и действительно не то, что я ищу.

У меня есть дизассемблер IDA Pro и отладчик WinDbg, и я загрузил winmine.exe в оба из них. Может ли кто-нибудь дать несколько практических советов для любой из этих программ с точки зрения определения местоположения структуры данных, представляющей минное поле?

В WinDbg я могу устанавливать точки останова, но мне трудно представить, в какой момент устанавливать точку останова и в каком месте памяти. Точно так же, когда я просматриваю статический код в IDA Pro, я не уверен, где даже начать искать функцию или структуру данных, представляющую минное поле.

Есть ли в Stackoverflow обратные инженеры, которые могут указать мне правильное направление?

КорольНестор
источник
27
Какая отличная идея для задания для студентов. Это что-то вроде анатомической лаборатории с тральщиком в роли кота.
ojblass
3
для наших международных читателей, которые могут быть сбиты с толку, «тральщик» - это американская версия веселой игры по поиску цветов, которая поставляется с Windows Vista. microsoft.blognewschannel.com/index.php/archives/2006/09/28/…
Кип
16
Счастливая игра по поиску цветов? О_о Политкорректность зашла слишком далеко.
Eugene
10
Ну, по крайней мере, в шведской версии Vista по умолчанию используется версия с тральщиком. Я полагаю, что они по умолчанию используют версию «счастливые цветы» в тех местах, где мины на самом деле имеют свойство разносить детей на куски.
JesperE
1
Итак ... просто щелкать по некоторым случайным квадратам, чтобы проверить, не являются ли они минами, не поможет, а?
Smandoli

Ответы:

125

Часть 1 из 3


Если вы серьезно относитесь к реверс-инжинирингу - забудьте о трейнерах и чит-движках.

Хороший реверс-инженер должен сначала узнать ОС, основные функции API, общую структуру программы (что такое цикл выполнения, структуры окон, процедуры обработки событий), формат файла (PE). Классика Петцольда «Программирование Windows» может помочь (www.amazon.com/exec/obidos/ISBN=157231995X), а также онлайновый MSDN.

Сначала вы должны подумать о том, где можно вызвать процедуру инициализации минного поля. Я подумал о следующем:

  • Когда вы запускаете игру
  • Когда вы нажимаете счастливое лицо
  • Когда вы нажимаете Game-> New или нажимаете F2
  • Когда вы меняете уровень сложности

Решил проверить команду акселератора F2.

Чтобы найти код обработки ускорителя, вам нужно найти процедуру обработки оконных сообщений (WndProc). Это можно отследить по вызовам CreateWindowEx и RegisterClass.

Читать:

Откройте IDA, окно импорта, найдите «CreateWindow *», перейдите к нему и используйте команду «Перейти по внешней ссылке к операнду (X)», чтобы увидеть, где он вызывается. Звонок должен быть только один.

Теперь найдите функцию RegisterClass и ее параметр WndClass.lpfnWndProc выше. В моем случае я уже назвал функцию 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

Нажмите Enter на имени функции (используйте 'N', чтобы переименовать его во что-нибудь получше)

Теперь посмотрим на

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

Это идентификатор сообщения, который при нажатии кнопки F2 должен содержать значение WM_COMMAND. Вы должны найти, где он сравнивается с 111h. Это можно сделать либо путем отслеживания edx в IDA, либо путем установки условной точки останова. в WinDbg и нажатия F2 в игре.

В любом случае приводит к чему-то вроде

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

Щелкните правой кнопкой мыши 111h и выберите «Символьная константа» -> «Использовать стандартную символьную константу», введите WM_ и Enter. Теперь у вас должно быть

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

Это простой способ узнать значения идентификаторов сообщений.

Чтобы понять работу с ускорителем, ознакомьтесь с:

Достаточно много текста для одного ответа. Если интересно, могу написать еще пару постов. Короче говоря, минное поле хранится в виде массива байтов [24x36], 0x0F показывает, что байт не используется (играет меньшее поле), 0x10 - пустое поле, 0x80 - мое.

Часть 2 из 3


Хорошо, давайте продолжим с кнопкой F2.

В соответствии с использованием ускорителей клавиатуры при нажатии кнопки F2 функция wndProc

... получает сообщение WM_COMMAND или WM_SYSCOMMAND. Младшее слово параметра wParam содержит идентификатор ускорителя.

Хорошо, мы уже нашли, где обрабатывается WM_COMMAND, но как определить соответствующее значение параметра wParam? Вот где в игру вступает ресурсный хакер . Накормите его двоичным кодом, и он вам все покажет. Нравится таблица ускорителей для меня.

альтернативный текст http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg

Вы можете видеть здесь, что кнопка F2 соответствует 510 в wParam.

Теперь вернемся к коду, который обрабатывает WM_COMMAND. Он сравнивает wParam с разными константами.

.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

Это приводит к фрагменту кода, который вызывает некоторую процедуру и завершает работу 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 ('bp 01003696'; на break '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

Я был полностью уверен, что нашел массив минных полей. Причина цикла, который начинается с массива длиной 360 байт (dword_1005340) с 0xF.

Почему 360h = 864? Ниже приведены некоторые подсказки, что строка занимает 32 байта, а 864 можно разделить на 32, поэтому массив может содержать 27 * 32 ячеек (хотя пользовательский интерфейс допускает максимальное поле 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 может предоставить вам классный дамп минного поля (нестандартный размер 9x9). Проверьте границы!

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  ................................

Хм, похоже мне понадобится еще один пост, чтобы закрыть тему

Станислав
источник
1
@ Станислав, хороший ответ Станислав. Если вы вообще можете уточнить это, сделайте это. Эти длинные информативные ответы лучше всего. Может быть, немного подробнее о том, как вы сосредоточились на структуре данных минного поля?
KingNestor
@Stanislav, я принял ваш ответ, потому что награда в 250 человек подошла к концу. Поздравляю!
KingNestor
1
@Stanislav, я отредактировал ваш ответ из нескольких частей в один ответ. Вы не приблизились к пределу размера своего единственного ответа, и я думаю, что обычно предпочтительнее иметь один ответ, чем публиковать несколько. Не стесняйтесь редактировать свой исходный ответ (этот) и добавлять к нему по своему усмотрению.
mmcdole
2
Также эпический ответ Станислав. Большое спасибо за ваш труд!
mmcdole
15

Похоже, вы пытаетесь разобрать исходный код, но вам нужно посмотреть объем памяти запущенной программы. В шестнадцатеричном редакторе HxD есть функция, которая позволяет вам это сделать.

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

Как только вы окажетесь в области памяти, вам нужно будет сделать снимки памяти, пока вы возитесь с платой. Изолируйте, что меняется, а что нет. Если вы думаете, что знаете, где находится структура данных в шестнадцатеричной памяти, попробуйте отредактировать ее, пока она находится в памяти, и посмотрите, изменится ли в результате плата.

Процесс, который вам нужен, мало чем отличается от создания «трейнера» для видеоигры. Обычно они основаны на обнаружении в памяти таких значений, как здоровье и боеприпасы, и их изменении на лету. Возможно, вы сможете найти несколько хороших руководств по созданию игровых трейнеров.

Джеймс МакМахон
источник
2
Что ж, вы ~ можете ~ определить местоположение памяти с помощью статической разборки. Вы можете следовать инструкциям по сборке, ища такие вещи, как функции rand (), вызываемые для генерации минного поля, а затем проследить оттуда, чтобы увидеть, в каком месте хранится поле в памяти (и как).
mmcdole
Оба подхода сложны. Раньше я пытался разобрать приложения, и это было очень болезненно. Как именно определить функцию rand ()?
Джеймс МакМахон,
Спасибо за ответ nemo.
KingNestor
11

Ознакомьтесь с этой статьей проекта кода, она немного глубже, чем упомянутая вами запись в блоге.

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 (упомянутый Ником Д.) и прочтите руководство, с которым он поставляется.

Киршштейн
источник
9

«В WinDbg я могу устанавливать точки останова, но мне трудно представить, в какой момент установить точку останова и в каком месте памяти. Точно так же, когда я просматриваю статический код в IDA Pro, я не уверен, с чего даже начать найти функцию или структуру данных, представляющую минное поле ".

В яблочко!

Что ж, вы можете поискать подпрограммы вроде random (), которые будут вызываться во время построения таблицы mines. Эта книга очень помогла мне, когда я экспериментировал с реверс-инжинирингом. :)

В общем, хорошие места для установки точек останова - это вызовы окон сообщений, вызовы воспроизведения звука, таймеры и другие подпрограммы Win32 API.

Кстати, я сейчас сканирую тральщик с OllyDbg .

Обновление: nemo напомнил мне отличный инструмент Cheat Engine от Эрика «Dark Byte» Хейнена.

Cheat Engine (CE) - отличный инструмент для наблюдения и изменения пространства памяти других процессов. Помимо этого основного средства, CE имеет больше специальных функций, таких как просмотр дизассемблированной памяти процесса и внедрение кода в другие процессы.

( настоящая ценность этого проекта в том, что вы можете загрузить исходный код -Delphi- и посмотреть, как были реализованы эти механизмы - я сделал это много лет назад: o)

Ник Дандулакис
источник
5

Хорошую статью по этой теме можно найти на Uninformed . Он довольно подробно описывает реверсирование Minesweeper (как введение в обратное проектирование приложений Win32) и представляет собой отличный ресурс.

mrduclaw
источник
4

Этот веб-сайт может быть более полезным:

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

Общий способ сделать это:

  1. Как-нибудь получить исходный код.
  2. Разберите и надейтесь, что оставшиеся символы помогут вам.
  3. Угадайте тип данных и попытайтесь манипулировать им и использовать сканер памяти, чтобы ограничить возможности.

В ответ на Bounty

Что ж, при втором чтении кажется, что вам нужно руководство по использованию отладчика, такого как WinDBG, а не обычный вопрос о том, как выполнить обратное проектирование. Я уже показал вам веб-сайт, на котором указаны значения, которые нужно искать, поэтому вопрос в том, как вы их искать?

В этом примере я использую Блокнот, потому что у меня не установлен Minesweeper. Но идея та же.

альтернативный текст

Вы печатаете

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

Нажмите «?», А затем «s», чтобы увидеть справку.

После того, как вы нашли нужный шаблон памяти, вы можете нажать alt + 5, чтобы вызвать средство просмотра памяти для красивого отображения.

альтернативный текст

К WinDBG нужно привыкнуть, но он не хуже любого другого отладчика.

Неизвестно
источник
1
«Как-нибудь получить исходный код» - глупое утверждение, поскольку «Сапер» отправляется без исходного кода. И реверс-инжиниринг с исходным кодом - это не реверс-инжиниринг ... это анализ исходного кода.
mrduclaw
@mrduclaw есть приложения, которые могут декомпилировать сборку в исходный язык. Нет термина «анализ исходного кода».
Неизвестный,
1
@Unknown Существуют приложения, которые пытаются восстановить программу на исходном языке из заданного скомпилированного двоичного файла. Но вы не можете получить «исходный код» с комментариями и цитатами автора из скомпилированного двоичного файла. Конечно, некоторые из этих «декомпиляторов» работают лучше, чем другие, но они не предоставляют вам код, написанный автором (код, оптимизированный для компилятора, часто сильно отличается от кода программиста). А вы никогда не проводили тестирование качества? Что делают такие инструменты, как PREfast и Sparse? Статический анализ исходного кода.
mrduclaw
Статический анализ исходного кода в PREfast и Sparse полностью отличается от ручного чтения декомпилированного кода с целью его взлома. Я не думаю, что кто-то будет путать эти две разные идеи друг с другом.
Unknown
@Unknown Я иду дальше и согласен с тем, что вы не должны путать дизассемблирование обратного инжиниринга с просмотром исходного кода (декомпилированного или иного, если у вас есть источник, из которого вы выполняете анализ исходного кода). В этом вся моя точка зрения. Так что, пожалуйста, перестаньте путать их. :)
mrduclaw
0

Хороший момент для начала трассировки в отладчике - это навести курсор мыши. Итак, найдите процедуру главного окна (я думаю, что такие инструменты, как spyxx, могут проверять свойства окон, и адрес обработчика событий является одним из них). Зайдите в него и найдите, где он обрабатывает события мыши - там будет переключатель, если вы сможете распознать его в ассемблере (посмотрите значение WM_XXX для мыши вверх в windows.h).

Поместите там точку останова и начните действовать. Где-то между моментом, когда вы отпустите кнопку мыши и обновлением экрана, victum получит доступ к структуре данных, которую вы ищете.

Будьте терпеливы, попытайтесь определить, что делается в любой момент времени, но не утруждайтесь слишком глубоким изучением кода, который, по вашему мнению, не представляет интереса для вашей текущей цели. Чтобы решить эту проблему, может потребоваться несколько запусков отладчика.

Также помогает знание обычного рабочего процесса приложений win32.

Евгений
источник
0

Мины, вероятно, будут храниться в виде двумерного массива. Это означает, что это либо массив указателей, либо единственный массив логических значений в стиле C.

Всякий раз, когда форма получает событие «вверх», на эту структуру данных делается ссылка. Индекс будет рассчитываться с использованием координаты мыши, возможно, с использованием целочисленного деления. Это означает, что вам, вероятно, следует искать cmpинструкцию или аналогичную инструкцию, в которой один из операндов вычисляется с использованием смещения, а xгде x- результат вычисления, включающего целочисленное деление. Тогда смещение будет указателем на начало структуры данных.

Йорген Фог
источник
0

Вполне разумно предположить, что информация о минах размещена в памяти непрерывно, по крайней мере, для строк (т.е. это 2D-массив или массив-массив). Таким образом, я бы попытался открыть несколько соседних ячеек в одной строке, создавая дампы памяти процесса по мере продвижения, а затем различать их и искать любые повторяющиеся изменения в той же области памяти (т.е. 1 байт изменен на первом шаге, следующий байт изменился на точно такое же значение на следующем шаге и т. д.).

Также есть вероятность, что это упакованный битовый массив (3 бита на каждую должно быть достаточно для записи всех возможных состояний - закрыто / открыто, мое / нет, помечено / не помечено), поэтому я бы тоже обратил внимание на это ( шаблоны также будут повторяться, хотя их труднее обнаружить). Но это не очень удобная структура, и я не думаю, что использование памяти было узким местом для Minesweeper, поэтому маловероятно, что подобные вещи будут использоваться.

Павел Минаев
источник
0

Хотя это не совсем «инструмент реверс-инженера», а скорее игрушка, которую мог бы использовать даже такой идиот, как я, попробуйте Cheat Engine . Это несколько упрощает отслеживание того, какие части памяти были изменены, когда, и даже имеет положения для отслеживания измененных частей памяти с помощью указателей (хотя вам, вероятно, это не нужно). Включен хороший интерактивный учебник.

Иван Вучица
источник