Auteur : Wan Yuxin de Jingdong Industry
Je crois que beaucoup de gens ont joué à des jeux de démineur depuis leur plus jeune âge. À cette époque où il n'y avait pas beaucoup de jeux informatiques, le démineur est devenu l'un des jeux les plus populaires. Plus tard, j'ai aussi eu envie de le faire une fois. Grâce au débogage dynamique, à l'ingénierie inverse et à C pour écrire un outil auxiliaire de dragueur de mines pour améliorer les compétences d'ingénierie inverse et de codage.
Débogage dynamique (analyse)
Tout d'abord, effectuez un débogage dynamique (analyse) du programme de dragueur de mines :
Ouvrez OD ( outil ollydebug ), faites glisser et déposez le démineur dans OD , F9 pour l'exécuter ; ctrl+G pour saisir l'expression à suivre, saisissez rand , cliquez sur [OK] pour passer à l'appel de la fonction, F2 pour définir un point d'arrêt, ce deuxième est de trouver une percée grâce à la fonction API rand . Cliquez n'importe où dans le champ de mines de la fenêtre du dragueur de mines (où 2 apparaît dans l'image ), puis cliquez sur Restaurer (bouton [Smiley] - ), comme indiqué dans la figure ci-dessous :

À ce moment, l'OD se cassera au point d'arrêt au rand juste défini , comme indiqué dans la figure ci-dessous :

En trouvant la fonction aléatoire rand , la pile suivante revient en arrière et revient à la fonction de niveau supérieur pour trouver les paramètres de push (push into the stack), c'est-à-dire que la fonction de génération aléatoire ( rand ) est générée aléatoirement en hauteur, largeur et tonnerre. Cliquez sur K (pile d'appels) pour faire apparaître la fenêtre de pile d'appels K , afficher les informations de la fenêtre de pile, trouver l'adresse de retour, double-cliquer sur l' adresse de retour dans la fenêtre de pile d'appels K et revenir à la couche précédente. Ce processus est appelé retour en arrière de la pile. Observez attentivement les informations de la pile 010036D2 (adresse de retour) dans la figure ci-dessous .



F8 en une seule étape , observez les changements de registre, de fenêtre de données et de fenêtre de pile, dword ptr ss:[esp+0x4] ou dword ptr ds:[XXX] valeur de suivi de la fenêtre de données ( la valeur 000DFC44 est 09 ), comme indiqué ci-dessous :

Après être revenu à la fonction de niveau supérieur, analysez les instructions à l'intérieur et connaissez la largeur ( 09 ) générée par le rand aléatoire tout à l'heure , comme indiqué dans la figure ci-dessous, faites attention à l'adresse 010036C7 .

Tout d'abord, analysez eax à partir du résultat renvoyé par cette fonction . Après une seule étape, vous pouvez voir qu'un numéro 09 est poussé dans la pile (adresse 010036D2 ) , comme le montre la figure ci-dessous :

Grâce à l'analyse ci-dessus, on peut fondamentalement deviner que la génération de rand de fonction aléatoire environnante est élevée, le nombre de tonnerre. Vous pouvez essayer de modifier les paramètres de déminage (champs de mines personnalisés), comme indiqué dans la figure ci-dessous, pour localiser avec précision la fonction rand et passer les paramètres, cliquez sur [OK], puis cliquez sur le bouton [Restaurer (visage souriant - )].

Observez le diamètre extérieur , comme indiqué dans la figure ci-dessous :

On trouve que push 0C ( la valeur de 000DFC84 est 0C ), on peut déterminer que le push 0C de cette fonction rand est la hauteur du champ de mines. Dans le même temps, vous pouvez clairement voir un graphique grossier de champ de mines dans la zone de mémoire.Grâce à la méthode ci-dessus, vous pouvez approximativement deviner que 0x80 est un champ de mines. Ou analysez avec IDA , grâce à l'analyse statique, vous pouvez voir la logique du programme de manière plus intuitive. Obtenez les données suivantes : adresse de base, numéro de mine et autres informations, comme indiqué dans la figure ci-dessous :



Le code ci-dessus signifie probablement que les variables de largeur globale 0x09 , hauteur 0x0C et nombre de tonnerre 0x0A sont définies en premier , et la largeur et la hauteur sont générées de manière aléatoire en jugeant deux couches de boucles. Obtenir l'adresse de base de la carte : 0x01005340 . En analysant la figure ci-dessous, nous savons qu'aucune mine n'est 0x0F , la mienne est 0x8F et le mur est 0x10 .


Grâce aux adresses de largeur et de hauteur, la zone de déminage et le nombre de mines sont imprimés, et les parois latérales et les mines peuvent être distinguées plus intuitivement.
Ensuite, commençons à comprendre comment marquer Lei. En supposant que la fonction GetDC est vue dans WinProc (retour en arrière dans la pile jusqu'à la fonction de rappel de message) , on devine à peu près que Bitblt sera utilisé . Dans OD , entrez l'expression à suivre par ctrl+g , et entrez " BitBlt ", appuyez sur F2 pour définir un point d'arrêt, cliquez sur n'importe quelle position dans la zone de déminage, et l'OD se cassera à la position BitBlt .
Il existe également une fonction BitBlt dans BitBlt .Le jugement préliminaire est qu'il utilise une double mise en mémoire tampon pour dessiner.
BitBlt(hDestDC,// Destination DC XDest, // Destination x coordonnée YDest, // Destination y coordonnée 10, // 10, // Hauteur et largeur de la zone de redessin hSrcDC, // Source DC 0, 0, SRCCOPY); / / Spécifiez la méthode d'opération pour calculer les coordonnées de la mine (cliquez sur le premier carré de déminage pour afficher les coordonnées), vous devez faire attention au mur latéral, comme indiqué ci-dessous :


Soustrayez la valeur des parois latérales :
-0x04=0x0C(12)-0x10(16)
0x27=0x37(55)-0x10(16)
Obtenez la formule de coordonnées : x ( XDest:12 ) =1*0x10(16)-0x04(4) , y ( YDest:55 ) =1*0x10(16)+0x27(39).
écriture de code
Grâce à l'analyse approximative ci-dessus, le code peut être écrit,



réalisation

Entrez 3 emplacements de mines terrestres pour obtenir une mine terrestre ( 10 murs, 8F mine terrestre, 0F pas de mine)

Entrez 2 pour éliminer automatiquement les mines, marquer les mines et ouvrir la carte

A travers ce petit projet, premièrement, une sorte de réflexion inversée sur le logiciel s'est renforcée, du genre : en voyant ce genre de panneau, j'ai probablement deviné qu'il est implémenté avec un tableau, et deuxièmement, la disposition du mien est aléatoire généré, puis grâce au débogage dynamique, nous pouvons comprendre La méthode de mise en œuvre (une idée de mise en œuvre du développeur), peut trouver l'adresse de base clé, plusieurs états (pas de tonnerre, tonnerre, mur), la dernière étape de codage peut comprendre le fonctionnement de la mémoire, plusieurs API importantes, FindWindow pour obtenir le handle, OpenProcess ouvre le handle, ReadProcessMemory lit les informations mémoire, PostMessage mode message asynchrone, CloseHandle ferme le handle. Une partie de l'analyse est erronée ou n'est pas en place, veuillez rechercher des briques. Plus inversement, l'analyse du code est très utile, non seulement vous pouvez élargir votre réflexion et votre niveau de programmation et de test, mais aussi découvrir, développer et exploiter des failles dans le programme ou patcher le programme, etc. J'espère que mes amis travailleront dur et s'encourageront mutuellement dans ce voyage long et ardu.