Comment puis-je trouver la structure de données qui représente la mise en page de la mine de démineur en mémoire?

StackOverflow https://stackoverflow.com/questions/931257

Question

Je suis en train d'apprendre sur le reverse engineering, en utilisant Démineur comme exemple d'application. J'ai trouvé cet article MSDN sur une simple commande WinDbg qui révèle toutes les mines, mais il est vieux, n'est pas expliqué en détail et est vraiment pas ce que je cherche.

Je IDA Pro désassembleur et débogueur WinDbg et j'ai chargé winmine.exe dans les deux. Quelqu'un peut-il fournir des conseils pratiques pour l'un de ces programmes en termes de trouver l'emplacement de la structure de données qui représente le champ de mines?

Dans WinDbg je peux mettre des points d'arrêt, mais il est difficile pour moi d'imaginer à quel moment de mettre un point d'arrêt et à quel emplacement mémoire. De même, quand je considère le code statique IDA Pro, je ne suis pas sûr où commencer même à trouver la structure de fonction ou des données qui représente le champ de mines.

Y at-il des ingénieurs inverse sur Stackoverflow qui peut me diriger dans la bonne direction?

Était-ce utile?

La solution

Partie 1 de 3


Si vous êtes sérieux dans l'ingénierie inverse - oublier les formateurs et les moteurs de tricher.

bon ingénieur inverse doit d'abord apprendre à connaître OS, les fonctions API de base, programme structure générale (ce qui est la boucle de fonctionner, les structures de fenêtres, les routines de gestion des événements), le format de fichier (PE). classiques de Petzold "Programmation Windows" peut aider (www.amazon.com/exec/obidos/ISBN=157231995X) ainsi que MSDN en ligne.

D'abord, vous devriez penser à où la routine d'initialisation du champ de mines peut être appelé. Je pensais à ce qui suit:

  • Lorsque vous lancez le jeu
  • Lorsque vous cliquez sur le visage heureux
  • Lorsque vous cliquez sur Jeu-> Nouveau ou appuyez sur F2
  • Lorsque vous modifiez niveau de difficulté

J'ai décidé de vérifier la commande d'accélérateur F2.

Pour trouver le code de manipulation d'accélérateur, vous devez trouver un message de fenêtre procédure de traitement (WndProc). Il peut être retracée par des appels CreateWindowEx et registerClass.

A lire:

Ouvrez IDA, fenêtre importations, trouver « CreateWindow * », sauter et utiliser « Jump xref à l'opérande (X) » commande pour voir où elle est appelée. Il devrait y avoir un seul appel.

Maintenant, regardez ci-dessus pour la fonction RegisterClass et il est paramètre WndClass.lpfnWndProc. Je l'ai déjà nommé la fonction MainWndProc dans mon cas.

.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

Appuyez sur Entrée sur le nom de la fonction (utilisez « N » pour le renommer à quelque chose de mieux)

Maintenant, prenez un coup d'oeil à

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

est id message, qui, en cas de pression sur le bouton F2 doit contenir la valeur WM_COMMAND. Vous devez trouver où il est comparé à 111h. Il peut se faire soit en traçant vers le bas EDX dans l'IDA ou par mise en point d'arrêt conditionnel en WinDbg et en appuyant sur F2 dans le jeu.

De toute façon conduit à quelque chose comme

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

Faites un clic droit sur 111h et utiliser « constante symbolique » -> « Utilisez constante symbolique standard », le type WM_ et Entrée. Vous devriez maintenant avoir

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

Il est un moyen facile de trouver des valeurs id message.

Pour comprendre vérifier la manipulation d'accélérateur sur:

Il est tout à fait beaucoup de texte pour une seule réponse. Si vous êtes intéressé je peux écrire un autre couple de postes. Longue histoire courte champ de mines stockées sous forme d'un tableau d'octets [24x36], 0x0F montre que l'octet n'est pas utilisé (terrain de jeu plus petit), 0x10 - champ vide, 0x80 -. Mien

Partie 2 de 3

Ok, allons-y avec le bouton F2.

Selon En utilisant Raccourcis clavier lorsque le bouton est pressé F2 fonction WNDPROC

  

... reçoit un WM_COMMAND ou WM_SYSCOMMAND   message. Le mot d'ordre faible de la   paramètre wParam contient la   identifiant de l'accélérateur.

Ok, nous avons déjà trouvé où WM_COMMAND est traité, mais comment déterminer la valeur correspondante du paramètre wParam? C'est là Resource Hacker entre en jeu. Nourrissez avec binaire et il vous montre tout. Comme table accélérateurs pour moi.

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

Vous pouvez voir ici, ce bouton F2 correspond à 510 wParam.

Maintenant, revenons au code, qui gère WM_COMMAND. Il compare wParam avec des constantes différentes.

.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

Utilisez le menu contextuel ou raccourci clavier « H » pour afficher les valeurs décimales et vous pouvez voir notre saut

.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

Il conduit à gros morceau de code qui appelle une proc et sort WNDPROC.

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

Est-ce que la fonction qui initie nouveau jeu? Trouvez que dans la dernière partie! Restez à l'écoute.

Partie 3 de 3

Jetons un coup d'oeil à la première partie de cette fonction

.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

Il existe deux valeurs (dword_10056AC, UValue) lu dans les registres EAX et ECX et par rapport à deux autres valeurs (dword_1005164, dword_1005338).

Jetez un oeil à l'aide de valeurs réelles WinDBG ( « pb 01003696 », en cas de rupture « p EAX, p ECX ») - ils semblaient comme les dimensions des champs de mines pour moi. Jouer avec la taille du champ de mines personnalisé a montré que la première paire sont de nouvelles dimensions et seconde - dimensions actuelles. Fixons nouveaux noms.

.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

Un peu plus tard, de nouvelles valeurs écrasent actuelles et sous-programme est appelé

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

Et quand je l'ai vu

.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

Je suis complètement sûr que j'ai trouvé tableau de champs de mines. Cause du cycle qui INITs tableau de longueur 360h octets (de dword_1005340) avec 0xF.

Pourquoi 360h = 864? Il y a des indices ci-dessous de cette ligne prend 32 octets et 864 peut être divisée par 32, de sorte que matrice peut contenir 27 * 32 cellules (bien que l'interface utilisateur permet max 24 * 30 domaine, il y a un rembourrage d'octets autour de matrice pour les frontières).

code suivant génère dessus des champs de mines et les bordures inférieures (0x10 octets). J'espère que vous pouvez voir itération de la boucle dans ce désordre;) je devais utiliser du papier et un stylo

.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

Et le reste du sous-programme dessine les frontières gauche et droite

.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

Utilisation intelligente des commandes WinDBG peut vous fournir dump champ de mines fraîche (taille personnalisée 9x9). Consultez les frontières!

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

Hmm, on dirait que je vais avoir besoin d'un autre poste pour fermer le sujet

Autres conseils

Il semble que vous essayez de démonter la source, mais ce que vous devez faire est de regarder l'espace mémoire du programme en cours d'exécution. L'éditeur hexadécimal HxD a une fonctionnalité qui vous permet de tout cela.

Une fois que vous êtes dans l'espace mémoire, il est question de prendre des photos de la mémoire pendant que vous mess avec le conseil d'administration. Isoler ce qui change par rapport à ce qui ne fonctionne pas. Quand vous pensez que vous avez une poignée sur laquelle la structure de données se trouve dans la mémoire hexagonale, essayez de la modifier pendant qu'il est en mémoire et voir si les modifications du conseil d'administration en conséquence.

Le processus que vous voulez est un peu comme la construction d'un « formateur » pour un jeu vidéo. Ceux-ci sont généralement basées sur la recherche où des valeurs telles que la santé et Munitions en mémoire et les changer à la volée. Vous pourrez peut-être trouver quelques bons tutoriels sur la façon de construire des formateurs de jeu.

Consultez cet article du projet de code, il est un peu plus en profondeur que le billet de blog que vous avez mentionné.

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

Modifier

Et cet article, mais pas directement démineur, vous donne une bonne étape par étape sur la chasse à travers la mémoire en utilisant WinDbg:

http://www.codingthewheel.com/archives/extracting- caché texte avec-windbg

Edit 2

Encore une fois, on ne parle pas démineur, mais il m'a certainement donné quelques éléments de réflexion pour mon débogage mémoire, il y a une foule de tutoriels ici:

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

En outre, téléchargez cheatengine (mentionné par Nick D.) et de travailler à travers le tutoriel, il est livré avec.

  

"Dans WinDbg je peux définir des points d'arrêt, mais   il est difficile pour moi d'imaginer à   quel point de mettre un point d'arrêt et à   quel endroit la mémoire. De même, lorsque   Je considère le code statique Pro IDA, je suis   pas sûr où même commencer à trouver   la fonction ou structure de données qui   représente le champ de mines ».

Exactement!
Eh bien, vous pouvez rechercher des routines comme aléatoire () qui seront appelés lors de la construction de la table des mines. Cette livre m'a beaucoup aidé quand je faisais des expériences avec l'ingénierie inverse. :)

En général, de bons endroits pour définir des points d'arrêt sont des appels à des boîtes de message, appelle à jouer un son, des minuteries et d'autres routines API win32.
BTW, je balayais démineur en ce moment avec OllyDbg .

Mise à jour: nemo m'a rappelé un excellent outil, Cheat moteur par Eric "Dark Byte" Heijnen.
Cheat Engine (CE) est un excellent outil pour regarder et modifier d'autres processus de l'espace mémoire. Au-delà base établissement, CE dispose de fonctionnalités plus spécifiques comme l'affichage de la mémoire démontées d'un processus et d'injection de code dans d'autres processus.
( real valeur de ce projet est que vous pouvez télécharger le code source -Delphi- et voir comment ces mécanismes ont été mis en œuvre - je l'ai fait il y a plusieurs années: o)

Un très bon article sur ce sujet très peut être trouvé à l'adresse Uninformed. Il couvre l'inversion Démineur (comme une introduction à l'ingénierie inverse des applications Win32) dans assez détail et tout autour d'une assez grande ressource.

Ce site pourrait être plus utile:

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

La façon générale d'aller sur le faire est:

  1. obtenir le code source une certaine façon.
  2. Démontez et l'espoir symboles restants peuvent vous aider.
  3. Devinez le type de données et essayer de le manipuler et utiliser un scanner de mémoire pour limiter les possibilités.

En réponse à Bounty

Eh bien, en deuxième lecture, il apparaît comme si vous vouliez un guide sur la façon d'utiliser un débogueur comme WinDBG plutôt que la question habituelle de savoir comment désosser. Je vous ai déjà montré le site qui vous indique les valeurs que vous devez rechercher, la question est, comment cherchez-vous cela?

J'utilise le Bloc-notes dans cet exemple parce que je ne l'ai pas installé Démineur. Mais l'idée est la même.

text alt

Vous tapez

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

Appuyez sur "?", Puis "s" pour voir l'aide.

Une fois que vous avez trouvé le modèle de mémoire que vous voulez, vous pouvez appuyer sur alt + 5 pour afficher la visionneuse de la mémoire pour un affichage agréable.

text alt

WinDBG prend un certain temps pour s'y habituer, mais il est aussi bon que tout autre débogueur là-bas.

Un bon point pour commencer le traçage dans débogueur serait sur place de la souris. Donc, trouver la procédure de la fenêtre principale (je pense que des outils tels que spyxx peut inspecter les propriétés des fenêtres et l'adresse de gestionnaire d'événements est l'un d'entre eux). Cassez pour trouver et où il gère les événements de souris - il y aura un interrupteur, si vous pouvez le reconnaître en assembleur (regarder la valeur de WM_xxx jusqu'à la souris dans windows.h)

.

Mettez un point d'arrêt et commencer à y Intervenir. Quelque part entre le moment où vous avez relâché le bouton de la souris et l'écran mis à jour le victum accédera à la structure de données que vous recherchez.

Soyez patient, essayez d'identifier ce qui est fait à un moment donné, mais ne cherchez pas trop profondément dans le code que vous soupçonnez d'être sans intérêt pour votre objectif actuel. Il peut prendre plusieurs pistes Débogueur pour clouer vers le bas.

La connaissance du déroulement normal des travaux des applications win32 aide aussi.

Les mines seront probablement stockées dans une sorte de tableau à deux dimensions. Cela signifie qu'il est soit un tableau de pointeurs ou d'un seul tableau de style C de booléens.

Chaque fois que la forme reçoit un événement de souris cette structure de données est référencée. L'indice sera calculé à l'aide de coordonnées souris, en utilisant probablement la division entière. Cela signifie que vous devriez probablement pour une cmp ou une instruction similaire, où l'un des opérandes est calculée à partir d'un décalage et x, où x est le résultat d'un calcul impliquant la division entière. Le décalage sera alors le pointeur au début de la structure de données.

Il est assez raisonnable de supposer que des informations sur les mines est aménagé de manière contiguë à la mémoire, au moins pour les lignes (à savoir, il est un tableau 2D, ou un tableaux-of-array). Ainsi, je voudrais essayer d'ouvrir plusieurs cellules adjacentes dans la même rangée, ce qui rend les décharges de mémoire du processus que je vais, puis les diff et chercher tout changement de répétition dans la même région de mémoire (par exemple 1 octet modifié lors de la première étape, la prochaine octet modifié pour exactement la même valeur à l'étape suivante, etc).

Il y a aussi la possibilité que c'est un tableau de bits emballé (3 bits par mine devrait être suffisante pour enregistrer tous les états possibles - fermé / ouvert, moi / non-moi, marqué / non battant pavillon), donc je regarderais pour que trop (les modèles seraient également reproductibles, bien que plus difficile à repérer). Mais ce n'est pas une structure pratique pour traiter, et je ne pense pas que l'utilisation de la mémoire est un goulot d'étranglement pour Démineur, il est donc peu probable que ce genre de chose serait utilisé.

Bien que pas strictement un « outil d'ingénierie inverse », et plus d'un jouet, même un idiot comme moi pourrait utiliser, consultez Cheat moteur. Il rend un peu facile de suivre les parties de la mémoire ont changé, quand et a même des dispositions pour le suivi des parties de mémoire modifiées par des pointeurs (si vous n'avez pas besoin probablement). Un joli tutoriel interactif est inclus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top