Assemblage d'apprentissage [fermé]

102

J'ai décidé d'apprendre le langage d'assemblage. La principale raison de le faire est de pouvoir comprendre du code désassemblé et peut-être d'être capable d'écrire des parties de code plus efficaces (par exemple, via C ++), de faire des choses comme des grottes de code, etc. J'ai vu qu'il y avait des millions de saveurs d'assemblage différentes , alors, aux fins que je mentionne, comment dois-je commencer? Quel genre d'assemblage dois-je apprendre? Je veux apprendre en faisant d'abord quelques programmes simples (c'est-à-dire une calculatrice), mais le but lui-même sera de m'y mettre pour comprendre le code affiché, par exemple, par IDA Pro.

J'utilise Windows (si cela fait une différence).

edit: Donc, il semble que tout le monde pointe vers MASM. Bien que j'aie compris qu'il a des capacités de haut niveau, tout est bon pour le programmeur de code d'assemblage, ce n'est pas ce que je recherche. Il semble avoir des instructions if, invoke, etc. non affichées dans les désassembleurs populaires (comme IDA). Donc, ce que j'aimerais entendre si possible, c'est l'opinion de quiconque utilise l'ASM aux fins que je demande (lire le code d'exe désassemblé dans IDA), pas seulement les programmeurs d'assemblage «généraux».

modifier: OK. J'apprends déjà l'assemblage. J'apprends le MASM, sans utiliser les trucs de haut niveau qui ne m'importent pas. Ce que je fais en ce moment, c'est essayer mon code sur les directives __asm ​​en c ++, donc je peux essayer les choses beaucoup plus rapidement que si je devais tout faire à partir de zéro avec MASM.

dévoré d'elysium
la source
Question similaire à stackoverflow.com/questions/1355524/…
TrueWill
Oui, je lisais celui-là aussi. Mais ma question est un peu plus «ciblée», je dirais.
dévoré l'elysium le
Si vous êtes sous Windows, la cible (c'est-à-dire le processeur, et donc le jeu d'instructions) est x86 ou x86-64. Sauf si vous obtenez une autre machine ou une carte MCU ou utilisez un émulateur. Alors, est la question quel assembleur dois-je utiliser? Ou demandez-vous vraiment quelle architecture cibler? Personnellement, j'adore les belles instructions orthogonales définies sur les puces de la série m68k, hélas, hélas.
dmckee --- ex-moderator kitten
2
"Il semble avoir des instructions if, invoke, etc" - Ce sont des macros (le 'M' dans "MASM") et vous n'avez pas à les utiliser même si l'assembleur les supporte.
ChrisW
3
Ce fut une décision difficile de donner à la question son 65e vote positif, 64 est un si beau nombre. . .
735Tesla

Réponses:

40

Commencez avec MASM32 et à partir de là, regardez FASM . Mais vous vous amuserez avec MASM.

Soie de midi
la source
J'ai entendu parler de MASM. Si je ne me trompe pas, il a beaucoup de fonctionnalités "de haut niveau", que je ne vois pas quand je regarde du code dissambled. J'aimerais avoir à programmer quelque chose qui ressemble exactement au code de sortie de la plupart des désassembleurs, si cela a du sens.
dévoré l'elysium le
1
Ce serait essentiellement comme écrire des codes opérationnels, ce qui n'a pas vraiment de sens. L'apprentissage de MASM32 vous aidera à comprendre à quoi ressemble le code dans un débogueur. Vous pouvez également consulter OllyDbg: ollydbg.de
Noon Silk
7
Vous ne comprenez pas l'assemblage. Vous devez le comprendre. Un opcode est un nombre. Les débogueurs tenteront de résoudre les opcodes selon leurs instructions (parfois c'est difficile). Vous devez comprendre les instructions de base. Apprendre MASM vous aidera à le faire. Plus besoin d’en dire plus.
Noon Silk
5
Vous n'êtes pas obligé d'utiliser toutes les fonctionnalités MASM simplement parce qu'elles sont là; vous pouvez rendre les choses aussi difficiles à lire que vous le souhaitez, si vous pensez en apprendre davantage de cette façon.
JasonTrue
3
MASM, avec ses bizarreries, ses bugs et ses fonctionnalités dites de haut niveau, a fait plus pour confondre les programmeurs d'assemblage - débutants et experts - plus que tout ce à quoi je peux penser.
IJ Kennedy
44

J'ai fait cela plusieurs fois et je continue de le faire. Dans ce cas où votre objectif principal est de lire et non d'écrire l'assembleur, je pense que cela s'applique.

Écrivez votre propre désassembleur. Pas dans le but de fabriquer le prochain plus grand désassembleur, celui-ci est strictement pour vous. Le but est d'apprendre le jeu d'instructions. Si j'apprends l'assembleur sur une nouvelle plateforme, je me souviens d'assembleur pour une plateforme que je connaissais autrefois. Commencez avec seulement quelques lignes de code, en ajoutant des registres par exemple, et en faisant un ping-pong entre le démontage de la sortie binaire et l'ajout d'instructions de plus en plus compliquées côté entrée:

1) apprendre le jeu d'instructions pour le processeur spécifique

2) Apprenez les nuances sur la façon d'écrire du code dans l'assemblage pour ledit processeur de sorte que vous puissiez agiter chaque bit d'opcode dans chaque instruction

3) vous apprenez mieux le jeu d'instructions que la plupart des ingénieurs qui utilisent ce jeu d'instructions pour gagner leur vie

Dans votre cas, il y a quelques problèmes, je recommande normalement le jeu d'instructions ARM pour commencer, il y a plus de produits basés sur ARM expédiés aujourd'hui que tout autre (ordinateurs x86 inclus). Mais la probabilité que vous utilisiez ARM maintenant et que vous ne connaissiez pas suffisamment l'assembleur pour qu'il puisse écrire du code de démarrage ou d'autres routines sachant ARM peut ou non aider ce que vous essayez de faire. La deuxième et la plus importante raison pour ARM d'abord est que les longueurs d'instructions sont de taille fixe et alignées. Démonter des instructions de longueur variable comme x86 peut être un cauchemar comme votre premier projet, et le but ici est d'apprendre le jeu d'instructions pour ne pas créer un projet de recherche. Third ARM est un jeu d'instructions bien fait, les registres sont créés égaux et n'ont pas de nuances particulières individuelles.

Vous devrez donc déterminer avec quel processeur vous souhaitez démarrer. Je suggère d'abord le msp430 ou ARM, puis le premier ou le second ARM, puis le chaos de x86. Quelle que soit la plate-forme, toute plate-forme qui vaut la peine d'être utilisée dispose de fiches techniques ou de manuels de référence pour les programmeurs gratuits du fournisseur qui incluent le jeu d'instructions ainsi que le codage des opcodes (les bits et les octets du langage machine). Dans le but d'apprendre ce que fait le compilateur et comment écrire du code avec lequel le compilateur n'a pas à lutter, il est bon de connaître quelques jeux d'instructions et de voir comment le même code de haut niveau est implémenté sur chaque jeu d'instructions avec chaque compilateur avec chaque optimisation réglage. Vous ne voulez pas vous lancer dans l'optimisation de votre code uniquement pour constater que vous l'avez amélioré pour un compilateur / plateforme mais bien pire pour tous les autres.

Oh pour désassembler les jeux d'instructions de longueur variable, au lieu de simplement commencer par le début et de désassembler tous les quatre octets linéairement à travers la mémoire comme vous le feriez avec l'ARM ou tous les deux octets comme le msp430 (Le msp430 a des instructions de longueur variable mais vous pouvez toujours vous en tirer aller linéairement dans la mémoire si vous commencez aux points d'entrée de la table des vecteurs d'interruption). Pour une longueur variable, vous voulez trouver un point d'entrée basé sur une table vectorielle ou des connaissances sur le démarrage du processeur et suivre le code dans l'ordre d'exécution. Vous devez décoder complètement chaque instruction pour savoir combien d'octets sont utilisés, alors si l'instruction n'est pas une branche inconditionnelle, supposez que l'octet suivant après cette instruction est une autre instruction. Vous devez également stocker toutes les adresses de succursales possibles et supposer que ce sont les adresses d'octet de départ pour plus d'instructions. La seule fois où j'ai réussi, j'ai fait plusieurs passages dans le binaire. En commençant au point d'entrée, j'ai marqué cet octet comme le début d'une instruction, puis décodé linéairement à travers la mémoire jusqu'à ce qu'il atteigne une branche inconditionnelle. Toutes les cibles de branche ont été marquées comme adresses de départ d'une instruction. J'ai fait plusieurs passages dans le binaire jusqu'à ce que je n'ai trouvé aucune nouvelle cible de branche. Si à tout moment vous trouvez, disons, une instruction de 3 octets mais que pour une raison quelconque vous avez marqué le deuxième octet comme le début d'une instruction, vous avez un problème. Si le code a été généré par un compilateur de haut niveau, cela ne devrait pas arriver à moins que le compilateur fasse quelque chose de mal, si le code a un assembleur écrit à la main (comme disons un vieux jeu d'arcade), il est tout à fait possible qu'il y ait des branches conditionnelles qui ne peuvent jamais arriver comme r0 = 0 suivi d'un saut sinon zéro. Vous devrez peut-être les modifier à la main hors du binaire pour continuer. Pour vos objectifs immédiats qui, je suppose, seront sur x86, je ne pense pas que vous aurez un problème.

Je recommande les outils gcc, mingw32 est un moyen simple d'utiliser les outils gcc sous Windows si x86 est votre cible. Sinon mingw32 plus msys est une excellente plate-forme pour générer un compilateur croisé à partir de sources binutils et gcc (généralement assez facile). mingw32 a quelques avantages par rapport à cygwin, comme des programmes nettement plus rapides et vous évitez l'enfer des dll cygwin. gcc et binutils vous permettront d'écrire en C ou en assembleur et de désassembler votre code et il y a plus de pages Web que vous ne pouvez en lire pour vous montrer comment faire l'un ou l'autre des trois. Si vous prévoyez de faire cela avec un jeu d'instructions de longueur variable, je vous recommande vivement d'utiliser un jeu d'outils qui comprend un désassembleur. Un désassembleur tiers pour x86 par exemple va être un défi à utiliser car vous ne savez jamais vraiment s'il s'est démonté correctement. Une partie de cela dépend également du système d'exploitation, l'objectif est de compiler les modules dans un format binaire contenant des instructions de marquage d'informations à partir de données afin que le désassembleur puisse faire un travail plus précis. Votre autre choix pour cet objectif principal est d'avoir un outil qui peut compiler directement vers l'assembleur pour votre inspection, puis espérez que lorsqu'il se compile dans un format binaire, il crée les mêmes instructions.

La réponse courte (d'accord un peu plus courte) à votre question. Écrivez un désassembleur pour apprendre un jeu d'instructions. Je commencerais par quelque chose de risqué et facile à apprendre comme ARM. Une fois que vous connaissez un jeu d'instructions, d'autres deviennent beaucoup plus faciles à saisir, souvent en quelques heures, par le troisième jeu d'instructions, vous pouvez commencer à écrire du code presque immédiatement en utilisant la fiche technique / manuel de référence pour la syntaxe. Tous les processeurs à utiliser ont une fiche technique ou un manuel de référence qui décrit les instructions jusqu'aux bits et octets des opcodes. Apprenez un processeur RISC comme ARM et un CISC comme x86 suffisamment pour avoir une idée des différences, des choses comme devoir passer par des registres pour tout ou être capable d'effectuer des opérations directement sur la mémoire avec moins ou pas de registres. Trois instructions d'opérande contre deux, etc. Lorsque vous réglez votre code de haut niveau, compilez pour plus d'un processeur et comparez la sortie. La chose la plus importante que vous apprendrez est que, quelle que soit la qualité de l'écriture du code de haut niveau, la qualité du compilateur et les choix d'optimisation effectués font une énorme différence dans les instructions réelles. Je recommande llvm et gcc (avec binutils), ni produireexcellent code, mais ils sont multi-plateformes et multi-cibles et tous deux ont des optimiseurs. Et les deux sont gratuits et vous pouvez facilement créer des compilateurs croisés à partir de sources pour divers processeurs cibles.

old_timer
la source
Merci pour la réponse. Mais je ne sais même pas comment écrire un désassembleur.
dévoré l'elysium le
8
«Écrivez votre propre désassembleur» - je suis d'accord, c'est comme ça que j'ai le mieux appris. (Qu'est-ce qui se passe avec "Mais je ne sais même pas comment écrire un désassembleur"?) LOL.
slashmais
Je vais avec vous! Je viens d'acheter un MSP430 et un livre dessus ... :)
Pepe
1
J'ai quelques exemples de msp430 github.com/dwelch67 plus quelques simulateurs de jeu d'instructions pour expérimenter l'inclusion de l'apprentissage asm, etc.
old_timer
J'aime vraiment, vraiment cette idée.
Millie Smith
33

L'assembly que vous écririez à la main et l'assembly généré par un compilateur sont souvent très différents lorsqu'ils sont visualisés à un niveau élevé. Bien sûr, les entrailles du programme seront très similaires (il n'y a que tellement de façons différentes d'encoder a = b + c, après tout), mais ce n'est pas le problème lorsque vous essayez de faire de l'ingénierie inverse. Le compilateur ajoutera une tonne de code standard à des exécutables même simples: la dernière fois que j'ai comparé, "Hello World" compilé par GCC faisait environ 4 Ko, alors que s'il était écrit à la main dans l'assembly, il était d'environ 100 octets. C'est pire sous Windows: la dernière fois que j'ai comparé (certes, c'était au siècle dernier) le plus petit "Hello World" que je pouvais générer avec mon compilateur Windows était de 52 Ko! Habituellement, ce passe-partout n'est exécuté qu'une seule fois, voire pas du tout, donc cela n'affecte pas beaucoup la vitesse du programme - comme je l'ai dit ci-dessus, le cœur du programme, la partie où le plus de temps d'exécution est passé, est généralement assez similaire, qu'il soit compilé ou écrit à la main.

En fin de compte, cela signifie qu'un programmeur d' assemblage expert et un désassembleur expert sont deux spécialités différentes. Ils sont généralement trouvés chez la même personne, mais ils sont vraiment séparés, et apprendre à être un excellent codeur d'assemblage ne vous aidera pas beaucoup à apprendre l'ingénierie inverse.

Ce que vous voulez faire est de récupérer les manuels d'architecture IA-32 et AMD64 (les deux sont traités ensemble) d' Intel et d' AMD , et de parcourir les premières sections sur les instructions et les opcodes. Peut-être lisez un ou deux tutoriels sur le langage assembleur, juste pour obtenir les bases du langage assembleur. Ensuite, prenez un petitexemple de programme qui vous intéresse et démontez-le: parcourez son flux de contrôle et essayez de comprendre ce qu'il fait. Voyez si vous pouvez le patcher pour faire autre chose. Ensuite, essayez à nouveau avec un autre programme et répétez jusqu'à ce que vous soyez suffisamment à l'aise pour essayer d'atteindre un objectif plus utile. Vous pourriez être intéressé par des choses comme "crackmes", produites par la communauté de la rétro-ingénierie, qui sont des défis pour les personnes intéressées par la rétro-ingénierie à essayer et, espérons-le, à apprendre quelque chose en cours de route. Ils varient en difficulté de basique (commencez ici!) À impossible.

Surtout, il vous suffit de pratiquer . Comme dans beaucoup d'autres disciplines, avec l'ingénierie inverse, la pratique rend parfait ... ou du moins mieux .

kquinn
la source
Je sais que lorsque vous compilez quoi que ce soit avec un langage de haut niveau, vous obtiendrez beaucoup de code "garbage" qui ne serait pas nécessaire s'il était codé directement dans l'assembly. Je comprends également qu'il y a une différence entre un programmeur d'assemblage expert et un désassembleur expert. Mais on pourrait dire la même chose de presque tout le reste.
dévoré l'elysium le
3
Ce qui me préoccupe, c'est qu'en théorie, je pourrais lire les journaux et comprendre ce qu'ils signifient, jusqu'à ce que je commence à écrire moi-même, je ne crois pas que je les comprendrai vraiment. Vous dites que je peux commencer par changer de petites parties de code, mais pour ce faire, je dois d'abord savoir quel type d'assemblage "saveur" IDA pro, par exemple, utilise.
dévoré l'elysium le
En outre, qu'utilise MSVC ++ pour le code d'assembly en ligne? MASM?
dévoré l'elysium le
15

Je vais aller à l'encontre de la plupart des réponses et recommander la variante MMIX de Knuth de l'architecture MIPS RISC. Ce ne sera pas aussi pratique que les langages d'assemblage x86 ou ARM (non pas qu'ils soient eux-mêmes cruciaux dans la plupart des emplois réels de nos jours ... ;-), mais cela vous débloquera la magie du dernier de Knuth version du plus grand chef-d'œuvre jamais réalisé sur la compréhension profonde des algorithmes et des structures de données - TAOCP , «The Art of Computer Programming». Les liens des deux URL que j'ai citées sont un excellent moyen de commencer à explorer cette possibilité!

Alex Martelli
la source
12

(Je ne sais pas pour vous mais j'étais excité par l'assemblage)

Un outil simple pour expérimenter l'assemblage est déjà installé sur votre ordinateur.

Allez dans le menu Démarrer-> Exécuter et tapezdebug

debug (commande)

debug est une commande sous DOS, MS-DOS, OS / 2 et Microsoft Windows (uniquement les versions x86, pas x64) qui exécute le programme debug.exe (ou DEBUG.COM dans les anciennes versions de DOS). Le débogage peut agir en tant qu'assembleur, désassembleur ou programme de vidage hexadécimal permettant aux utilisateurs d'examiner de manière interactive le contenu de la mémoire (en langage d'assemblage, hexadécimal ou ASCII), d'apporter des modifications et d'exécuter de manière sélective COM, EXE et d'autres types de fichiers. Il a également plusieurs sous-commandes qui sont utilisées pour accéder à des secteurs de disque spécifiques, des ports d'E / S et des adresses mémoire. Le débogage MS-DOS s'exécute à un niveau de processus 16 bits et par conséquent, il est limité aux programmes informatiques 16 bits . FreeDOS Debug a également une version "DEBUGX" prenant en charge les programmes DPMI 32 bits.

Tutoriels:


Si vous souhaitez comprendre le code que vous voyez dans IDA Pro (ou OllyDbg ), vous devrez apprendre comment le code compilé est structuré. Je recommande le livre Reversing: Secrets of Reverse Engineering

J'ai expérimenté quelques semaines avec debugquand j'ai commencé à apprendre l'assemblage (il y a 15 ans).
Notez que cela debugfonctionne au niveau de la machine de base, il n'y a pas de commandes d'assemblage de haut niveau.

Et maintenant un exemple simple:

donnez apour commencer à écrire du code d'assemblage - tapez le programme ci-dessous - et enfin donnez-le gpour l'exécuter.

texte alternatif


( INT 21afficher à l'écran le caractère ASCII stocké dans le DLregistre si le AHregistre est réglé sur 2- INT 20met fin au programme)

Nick Dandoulakis
la source
J'ai dû appuyer sur ctrl-c, avant de pouvoir entrer "g".
ericp
2
@ericp, vous n'avez pas besoin d'appuyer sur ctrl-c. Par exemple, vous tapez a& [enter] pour commencer à écrire le code d'assemblage. Si vous appuyez deux fois sur [entrée], vous quittez le mode d'assemblage. g& [entrée] pour l'exécuter (offset 100 par défaut).
Nick Dandoulakis
cela provoque-t-il réellement un débordement de pile ou l'écrit-il simplement à l'écran?
Janus Troelsen
1
@user, il écrit juste le nom de ce site :-)
Nick Dandoulakis
@JanusTroelsen ces nombres (53, 74, 61, etc.) sont les codes ASCII pour 'S' 't' 'a' ... Chaque appel Int21 imprime un caractère à la fois! C'est pourquoi l'assemblage n'est PAS plus rapide :)
doug65536
8

J'ai trouvé Hacking: The Art of Exploitation comme un moyen intéressant et utile d'entrer dans ce sujet ... je ne peux pas dire que j'ai déjà utilisé directement les connaissances, mais ce n'est vraiment pas la raison pour laquelle je l'ai lu. Cela vous donne une appréciation beaucoup plus riche des instructions sur lesquelles votre code se compile, ce qui a parfois été utile pour comprendre des bogues plus subtils.

Ne soyez pas rebuté par le titre. La majeure partie de la première partie du livre est "Hacking" au sens Eric Raymond du mot: des moyens créatifs, surprenants, presque sournois de résoudre des problèmes difficiles. Moi (et peut-être vous) étais beaucoup moins intéressé par les aspects de sécurité.

mblackwell8
la source
7

Je ne me concentrerais pas sur essayer d'écrire des programmes en assemblage, du moins pas au début. Si vous êtes sur x86 (ce que je suppose que vous êtes, puisque vous utilisez Windows), il y a des tonnes de cas spéciaux étranges qu'il est un peu inutile d'apprendre. Par exemple, de nombreuses instructions supposent que vous opérez sur un registre que vous ne nommez pas explicitement, et d'autres instructions fonctionnent sur certains registres mais pas sur d'autres.

J'apprendrais juste assez sur votre architecture prévue pour que vous compreniez les bases, puis sautez directement et essayez de comprendre la sortie de votre compilateur. Armez-vous des manuels Intel et plongez directement dans la sortie de votre compilateur. Isolez le code d'intérêt dans une petite fonction pour être sûr de bien comprendre le tout.

Je considérerais que les bases sont:

  • registres: combien y en a-t-il, quels sont leurs noms et quelles sont leurs tailles?
  • Ordre des opérandes: add eax, ebxsignifie "Ajouter ebx à eax et stocker le résultat dans eax".
  • FPU: apprenez les bases de la pile en virgule flottante et comment vous convertissez vers / depuis fp.
  • modes d'adressage: [base + offset * multiplicateur], mais le multiplicateur ne peut être que 1, 2 ou 4 (ou peut-être 8?)
  • conventions d'appel: comment les paramètres sont-ils passés à une fonction?

Souvent, ce que le compilateur émet sera surprenant. Faites-en un puzzle pour savoir pourquoi diable le compilateur a pensé que ce serait une bonne idée. Cela vous apprendra beaucoup.

Cela vous aidera probablement également à vous armer des manuels d'Agner Fog , en particulier celui qui répertorie les instructions. Il vous indiquera à peu près le coût de chaque instruction, bien que cela soit plus difficile à quantifier directement sur les processeurs modernes. Mais cela aidera à expliquer pourquoi, par exemple, le compilateur fait tout son possible pour éviter d'émettre unidiv instruction.

Mon seul autre conseil est de toujours utiliser la syntaxe Intel au lieu d'AT & T lorsque vous avez le choix. J'étais plutôt neutre sur ce point, jusqu'au jour où j'ai réalisé que certaines instructions sont totalement différentes entre les deux (par exemple, movslqdans la syntaxe AT&T est movsxddans la syntaxe Intel). Puisque les manuels sont tous écrits en utilisant la syntaxe Intel, tenez-vous-en à cela.

Bonne chance!

Josh Haberman
la source
3

J'ai commencé par apprendre MIPS qui est une architecture 32 bits très compacte. C'est un jeu d'instructions réduit, mais c'est ce qui le rend facile à comprendre pour les débutants. Vous serez toujours en mesure de comprendre le fonctionnement de l'assemblage sans être submergé par la complexité. Vous pouvez même télécharger un joli petit IDE, qui vous permettra de compiler votre code MIPS: clicky Une fois que vous aurez compris, je pense qu'il serait beaucoup plus facile de passer à des architectures plus complexes. Au moins c'est ce que je pensais :) À ce stade, vous aurez les connaissances essentielles de l'allocation et de la gestion de la mémoire, du flux logique, du débogage, des tests, etc.


la source
3

La suggestion d'utiliser le débogage est amusante, de nombreuses astuces intéressantes peuvent être faites avec cela. Cependant, pour un système d'exploitation moderne, l'apprentissage de l'assemblage 16 bits peut être légèrement moins utile. Envisagez plutôt d'utiliser ntsd.exe. Il est intégré à Windows XP (il a été supprimé dans Server 2003 et au-dessus, malheureusement), ce qui en fait un outil pratique à apprendre car il est si largement disponible.

Cela dit, la version originale de XP souffre d'un certain nombre de bogues. Si vous voulez vraiment l'utiliser (ou cdb ou windbg, qui sont essentiellement des interfaces différentes avec la même syntaxe de commande et le même back-end de débogage), vous devez installer les outils de débogage Windows gratuits package .

Le fichier debugger.chm inclus dans ce package est particulièrement utile lorsque vous essayez de comprendre la syntaxe inhabituelle.

L'avantage de ntsd est que vous pouvez le faire apparaître sur n'importe quelle machine XP près de chez vous et l'utiliser pour l'assembler ou le démonter. Il fait un outil d'apprentissage d'assemblage / great / X86. Par exemple (en utilisant cdb car il est en ligne dans l'invite dos, c'est par ailleurs identique):

(erreurs de symboles ignorées car elles ne sont pas pertinentes - aussi, j'espère que ce formatage fonctionne, c'est mon premier message)

C:\Documents and Settings\User>cdb calc

Microsoft (R) Windows Debugger Version 6.10.0003.233 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: calc
Symbol search path is: *** Invalid ***
Executable search path is:
ModLoad: 01000000 0101f000   calc.exe
ModLoad: 7c900000 7c9b2000   ntdll.dll
ModLoad: 7c800000 7c8f6000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 7c9c0000 7d1d7000   C:\WINDOWS\system32\SHELL32.dll
ModLoad: 77dd0000 77e6b000   C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e70000 77f02000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fe0000 77ff1000   C:\WINDOWS\system32\Secur32.dll
ModLoad: 77f10000 77f59000   C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e410000 7e4a1000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77c10000 77c68000   C:\WINDOWS\system32\msvcrt.dll
ModLoad: 77f60000 77fd6000   C:\WINDOWS\system32\SHLWAPI.dll
(f2c.208): Break instruction exception - code 80000003 (first chance)
eax=001a1eb4 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c90120e esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c90120e cc              int     3
0:000> r eax
eax=001a1eb4
0:000> r eax=0
0:000> a eip
7c90120e add eax,0x100
7c901213
0:000> u eip
ntdll!DbgBreakPoint:
7c90120e 0500010000      add     eax,100h
7c901213 c3              ret
7c901214 8bff            mov     edi,edi
7c901216 8b442404        mov     eax,dword ptr [esp+4]
7c90121a cc              int     3
7c90121b c20400          ret     4
ntdll!NtCurrentTeb:
7c90121e 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c901224 c3              ret
0:000> t
eax=00000100 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c901213 esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!DbgUserBreakPoint+0x1:
7c901213 c3              ret
0:000>`

Aussi - pendant que vous jouez avec IDA, assurez-vous de consulter le livre IDA Pro de Chris Eagle (dissocié car StackOverflow ne veut pas me laisser publier plus de deux liens pour mon premier message). C'est de loin la meilleure référence là-bas.

Jordan
la source
1
+1 pour le livre de Chris Eagle. Je dois mettre un peu d'amour là-dedans pour le Sk3wl de r00t;)
mrduclaw
3

J'ai récemment suivi un cours sur les systèmes informatiques. L'un des sujets était l'assemblage en tant qu'outil de communication avec le matériel.

Pour moi, la connaissance de l'assemblage n'aurait pas été complète sans comprendre les détails du fonctionnement des systèmes informatiques. Comprendre cela apporte une nouvelle compréhension de la raison pour laquelle les instructions d'assemblage sur une architecture de processeur sont excellentes mais sont terribles sur une autre architecture.

Compte tenu de cela, je suis enclin à recommander mon manuel de classe:

Systèmes informatiques: point de vue d'un programmeur .

Systèmes informatiques: le point de vue d'un programmeur
(source: cmu.edu )

Il couvre l'assemblage x86 mais le livre est beaucoup plus large que cela. Il couvre le canal du processeur et la mémoire en tant que cache, le système de mémoire virtuelle et bien plus encore. Tout cela peut affecter la façon dont l'assemblage pourrait être optimisé pour les fonctionnalités données.

Frank V
la source
2

Je pense que vous voulez apprendre les mnémoniques d'opcode ASCII-ized (et leurs paramètres), qui sont générés par un désassembleur et qui sont compris par (peut être utilisé comme entrée) un assembleur.

N'importe quel assembleur (par exemple MASM) ferait l'affaire.

Et / ou il vaudrait peut-être mieux que vous lisiez un livre à ce sujet (il y a eu des livres recommandés sur SO, je ne me souviens pas lesquels).

ChrisW
la source
2

Faites-vous d'autres travaux de développement sur Windows? Sur quel IDE? Si c'est VS, alors il n'y a pas besoin d'un IDE supplémentaire juste pour lire le code désassemblé: déboguez votre application (ou attachez-la à une application externe), puis ouvrez la fenêtre de désassemblage (dans les paramètres par défaut, c'est Alt + 8). Parcourez et regardez la mémoire / les registres comme vous le feriez avec un code normal. Vous voudrez peut-être aussi garder une fenêtre de registres ouverte (Alt + 5 par défaut).

Intel fournit des manuels gratuits , qui donnent à la fois un aperçu de l'architecture de base (registres, unités de processeur, etc.) et une référence d'instructions complète. Au fur et à mesure que l'architecture mûrit et devient de plus en plus complexe, les manuels de «l'architecture de base» deviennent de moins en moins lisibles. Si vous pouvez mettre la main sur une version plus ancienne, vous aurez probablement un meilleur point de départ (même les manuels P3 - ils expliquent mieux la même chose) environnement d'exécution de base).

Si vous souhaitez investir dans un livre, voici un joli texte d'introduction. Recherchez «x86» dans Amazon et vous en obtiendrez beaucoup d'autres. Vous pouvez obtenir plusieurs autres directions à partir d'une autre question ici .

Enfin, vous pouvez bénéficier d' un peu de lecture des bas - niveau blogs. Ces bits d'information de taille octet fonctionnent le mieux pour moi, personnellement.

Ofek Shilon
la source
2

Cela ne vous aidera pas nécessairement à écrire du code efficace!

Les codes op i86 sont plus ou moins un format «hérité» qui persiste à cause du volume de code et des binaires exécutables pour Windows et Linux.

C'est un peu comme les anciens savants écrivant en latin, un locuteur italien comme Galilée écrivait en latin et son article pourrait être compris par un locuteur polonais comme Copernic. C'était toujours le moyen le plus efficace de communiquer, même si niether était particulièrement bon en latin, et le latin est une langue de rebut pour exprimer des idées mathématiques.

Ainsi, les compilateurs génèrent du code x86 par défaut, et les puces modernes lisent les codes anceint Op et transforment ce qu'elles voient en instructions risc parallèles, avec une exécution réorganisée, une exécution spéculative, un pipelining, etc., en plus d'utiliser pleinement les 32 ou 64 registres du processeur. a en fait (par opposition au pathétique 8 que vous voyez dans les instructions x86.)

Maintenant, tous les compilateurs d'optimisation savent que c'est ce qui se passe réellement, donc ils codent des séquences de codes OP dont ils savent que la puce peut optimiser efficacement - même si certaines de ces séquences sembleraient inefficaces pour un programmeur .asm vers 1990.

À un moment donné, vous devez accepter que les dizaines de milliers d'années de travail que les rédacteurs de compilateurs ont déployées ont porté leurs fruits, et faites-leur confiance.

Le moyen le plus simple et le plus simple d'obtenir un runtime plus efficace consiste à acheter le compilateur Intel C / C ++. Ils ont un marché de niche pour les compilateurs efficeint, et ils ont l'avantage de pouvoir interroger les concepteurs de puces sur ce qui se passe à l'intérieur.

James Anderson
la source
Votre histoire suggère quelque peu que les processeurs CISC sont devenus en interne des processeurs RISC. J'ai peut-être mal compris, mais ce n'est tout simplement pas vrai. Et le pathétique 8? Les processeurs modernes (disons, depuis 1999) en incluent beaucoup plus: 10 gpr: EAX-EFLAGS, 80 bits FP0-FP7, 64 bits MMX0-MMX7, 128 bits XMM0-XMM7, segment: CS-GS, spéciaux: CR0-CR4 , DR0-DR7, TR3-TR7, GDTR, IDTR, LDTR, MSR et sur x86-64 également R8-R15. Tous ne sont pas accessibles à partir de ring-3, mais la plupart le sont et la plupart sont utilisés par les compilateurs GCC / VC ++ récents (post-2006). Au total un peu plus que le "pathétique 8";).
Abel
2

Pour faire ce que vous voulez faire, j'ai juste pris la référence du jeu d'instructions Intel (peut-être pas celle que j'ai utilisée, mais cela semble suffisant) et quelques programmes simples que j'ai écrits dans Visual Studio et j'ai commencé à les lancer dans IDAPro / Windbg . Lorsque j'ai dépassé mes propres programmes, le logiciel de crackmes a été utile.

Je suppose que vous avez une compréhension de base de la façon dont les programmes s'exécutent sur Windows. Mais vraiment, pour lire l'assemblage, il n'y a que quelques instructions à apprendre et quelques saveurs de ces instructions (par exemple, il y a une instruction de saut, le saut a quelques saveurs comme jump-if-equal, jump-if-ecx-is-zero , etc). Une fois que vous avez appris les instructions de base, il est assez simple de comprendre l'essentiel de l'exécution du programme. La vue graphique d'IDA est utile, et si vous tracez le programme avec Windbg, il est assez simple de comprendre ce que font les instructions si vous n'êtes pas sûr.

Après un peu de jeu comme ça, j'ai acheté Hacker Disassembly Uncovered . En général, je reste à l'écart des livres avec le mot "Hacker" dans le titre, mais j'ai vraiment aimé la façon dont celui-ci expliquait en profondeur comment le code compilé avait l'air désassemblé. Il aborde également les optimisations du compilateur et certains trucs d'efficacité qui étaient intéressants.

Tout dépend vraiment de la profondeur à laquelle vous voulez être en mesure de comprendre le programme aussi. Si vous procédez à la rétro-ingénierie d'une cible à la recherche de vulnérabilités, si vous écrivez du code d'exploitation ou si vous analysez des logiciels malveillants emballés pour des capacités, vous aurez besoin de plus de temps de démarrage pour vraiment faire avancer les choses (en particulier pour les logiciels malveillants plus avancés. ). D'un autre côté, si vous voulez simplement pouvoir changer le niveau de votre personnage sur votre jeu vidéo préféré, vous devriez vous en sortir dans un laps de temps relativement court.

mrduclaw
la source
1

L'un des langages d'assemblage pédagogiques standard est MIPS. Vous pouvez obtenir des simulateurs MIPS (spim) et divers matériels pédagogiques pour cela.

Personnellement, je ne suis pas fan. J'aime plutôt IA32.

Paul Nathan
la source
MIPS est sympa. 68000 l'est aussi, et si vous apprenez 68000, vous pouvez écrire des binaires qui s'exécutent dans MAME. :-)
Nosredna
1

Mon préféré est le NASM, principalement parce qu'il est multi-plateforme, et qu'il compile MMX, SSE, 64 bits ...

J'ai commencé à compiler un simple fichier source C avec gcc et à "trans-coder" l'instruction assembleur du format gcc au format NASM. Ensuite, vous pouvez modifier de petites portions de code et vérifier l'amélioration des performances qu'il apporte.

La documentation du NASM est vraiment complète, je n'ai jamais eu besoin de rechercher des informations dans des livres ou d'autres sources.

GB
la source
0

Beaucoup de bonnes réponses ici. La programmation de bas niveau, l'assemblage, etc. sont populaires dans la communauté de la sécurité, il vaut donc la peine d'y rechercher des conseils et des astuces une fois que vous y êtes. Ils ont même de bons tutoriels comme celui-ci sur l'assemblage x86 .

Brian Lyttle
la source
0

Pour atteindre réellement votre objectif, vous pouvez envisager de commencer par l'EDI dans lequel vous vous trouvez. La fenêtre est généralement une fenêtre de désassembleur, vous pouvez donc faire un pas à pas dans le code. Il y a généralement une vue quelconque pour vous permettre de voir les registres et de regarder dans les zones de mémoire.

L'examen du code c / c ++ non optimisé aidera à créer un lien dans le type de code que le compilateur génère pour vos sources. Certains compilateurs ont une sorte de mot réservé ASM qui vous permet d'insérer des instructions machine dans votre code.

Mon conseil serait de jouer avec ce genre d'outils pendant un certain temps et de se mouiller les pieds, puis de monter? vers le bas? au code assembleur direct sur la plate-forme sur laquelle vous exécutez.

Il existe de nombreux outils formidables, mais vous trouverez peut-être plus amusant d'éviter la courbe d'apprentissage abrupte au début.

EvilTeach
la source
0

Nous avons appris l'assemblage avec un kit de développement de microcontrôleur (Motorola HC12) et une fiche technique épaisse.

te
la source
0

Hors sujet, je sais, mais puisque vous êtes un programmeur Windows, je ne peux pas m'empêcher de penser que cela peut être une utilisation plus appropriée et / ou meilleure de votre temps pour apprendre MSIL. Non, ce n'est pas l'assemblage, mais c'est probablement plus pertinent dans cette ère .NET.

slf
la source
0

Connaître l'assembly peut être utile pour le débogage, mais je ne serais pas trop enthousiaste à l'idée de l'utiliser pour optimiser votre code. Les compilateurs modernes sont généralement bien meilleurs pour optimiser qu'un humain de nos jours.

Adam Pierce
la source
Hmm. Vous pouvez toujours tordre un peu plus d'assemblage de codage vous-même, mais il faut plus de travail pour battre le compilateur qu'auparavant.
Nosredna
0

Vous pouvez consulter le cours vidéo d'assemblage xorpd x86 . (Je l'ai écrit). Le cours lui-même est payant, mais les exercices sont open source, sur github. Si vous avez une certaine expérience en programmation, je pense que vous devriez être capable de travailler uniquement avec les exercices et de tout comprendre.

Notez que le code est pour la plate-forme Windows et est écrit à l'aide de l' assembleur Fasm . Le cours et les exercices ne contiennent pas de constructions de haut niveau, cependant vous pouvez utiliser Fasm pour créer des macros très compliquées, si vous le souhaitez.

xorpd
la source