Lernversammlung [geschlossen]


102

Ich beschloss, die Assemblersprache zu lernen. Der Hauptgrund dafür ist, disassemblierten Code verstehen zu können und möglicherweise effizientere Teile des Codes schreiben zu können (z. B. über c ++), Dinge wie Code-Höhlen usw. zu tun. Ich habe gesehen, dass es zig verschiedene Arten von Assemblierungen gibt Also, für die Zwecke, die ich erwähne, wie soll ich anfangen? Welche Art von Montage soll ich lernen? Ich möchte lernen, indem ich zuerst einige einfache Programme (z. B. einen Taschenrechner) mache, aber das Ziel selbst wird darin bestehen, sich damit vertraut zu machen, damit ich den Code verstehen kann, der beispielsweise von IDA Pro angezeigt wird.

Ich benutze Windows (wenn das einen Unterschied macht).

edit: Also, anscheinend zeigt jeder auf MASM. Obwohl ich den Punkt verstehe, dass es über Funktionen auf hohem Niveau verfügt, die alle gut für den Assembler-Code-Programmierer sind, ist das nicht das, wonach ich suche. Es scheint Anweisungen zu haben, die in gängigen Deassemblern (wie IDA) nicht angezeigt werden. Was ich also nach Möglichkeit hören möchte, ist die Meinung von jedem, der ASM für die von mir gewünschten Zwecke verwendet (Lesen des zerlegten exe-Codes in IDA), nicht nur von "allgemeinen" Assembly-Programmierern.

bearbeiten: OK. Ich lerne bereits Montage. Ich lerne MASM und benutze nicht die hochrangigen Dinge, die mir egal sind. Was ich gerade mache, ist das Ausprobieren meines Codes in __asm-Direktiven in C ++, damit ich die Dinge viel schneller ausprobieren kann, als wenn ich alles von Grund auf mit MASM machen müsste.



Ja, das habe ich auch gelesen. Aber meine Frage ist etwas "fokussierter", würde ich sagen.
verschlungenes Elysium

Wenn Sie unter Windows arbeiten, ist das Ziel (das ist der Prozessor und damit der Befehlssatz) x86 oder x86-64. Es sei denn, Sie erhalten eine andere Maschine oder eine MCU-Karte oder verwenden einen Emulator. Ist die Frage, welchen Assembler ich verwenden soll? Oder fragen Sie sich wirklich, auf welche Architektur Sie abzielen sollen? Persönlich liebe ich den schönen orthogonalen Befehlssatz auf den Chips der m68k-Serie, leider, leider.
dmckee --- Ex-Moderator Kätzchen

2
"Es scheint Anweisungen für if, invoke usw. zu geben" - Dies sind Makros (das 'M' in "MASM"), und Sie müssen sie nicht verwenden, selbst wenn der Assembler sie unterstützt.
ChrisW

3
Es war eine schwierige Entscheidung, der Frage ihre 65. Gegenstimme zu geben, 64 ist eine so schöne Zahl. . .
735Tesla

Antworten:


40

Beginnen Sie mit MASM32 und schauen Sie sich von dort aus FASM an . Aber du wirst Spaß mit MASM haben.


Ich habe von MASM gehört. Wenn ich mich nicht irre, hat es viele "High Level" -Funktionen, die ich nicht sehe, wenn ich mir entschlüsselten Code anschaue. Ich möchte etwas programmieren müssen, das genau dem Ausgabecode der meisten Disassembler entspricht, wenn dies sinnvoll ist.
verschlungenes Elysium

1
Das wäre im Grunde wie das Schreiben von Op-Codes, was nicht wirklich Sinn macht. Wenn Sie MASM32 lernen, können Sie besser verstehen, wie Code in einem Debugger aussieht. Sie können auch OllyDbg überprüfen: ollydbg.de
Noon Silk

7
Sie verstehen die Montage nicht. Du musst es verstehen. Ein Opcode ist eine Zahl. Debugger versuchen, Opcodes gemäß ihren Anweisungen aufzulösen (manchmal ist es schwierig). Sie müssen die grundlegenden Anweisungen verstehen. Das Erlernen von MASM hilft Ihnen dabei. Mehr braucht man nicht zu sagen.
Mittag Seide

5
Sie müssen nicht alle MASM-Funktionen verwenden, nur weil sie vorhanden sind. Sie können das Lesen so schwierig machen, wie Sie möchten, wenn Sie glauben, dass Sie auf diese Weise mehr lernen werden.
JasonTrue

3
MASM mit seinen Macken, Fehlern und sogenannten High-Level-Funktionen hat Assembly-Programmierer - Anfänger und Experten gleichermaßen - mehr verwirrt als alles, was mir einfällt.
IJ Kennedy

44

Ich habe das schon oft gemacht und mache das auch weiterhin. In diesem Fall, in dem Ihr primäres Ziel darin besteht, Assembler zu lesen und nicht zu schreiben, gilt dies meines Erachtens.

Schreiben Sie Ihren eigenen Disassembler. Nicht für den Zweck, den nächstgrößeren Disassembler herzustellen, ist dieser ausschließlich für Sie. Ziel ist es, den Befehlssatz zu lernen. Ob ich Assembler auf einer neuen Plattform lerne, mich an Assembler für eine Plattform erinnere, die ich einmal kannte. Beginnen Sie mit nur wenigen Codezeilen, fügen Sie beispielsweise Register hinzu und pingen Sie zwischen dem Zerlegen des Binärausgangs und dem Hinzufügen immer komplizierterer Anweisungen auf der Eingabeseite.

1) Lernen Sie den Befehlssatz für den jeweiligen Prozessor

2) Lernen Sie die Nuancen des Schreibens von Code in Assembler für diesen Prozessor, so dass Sie jedes Opcode-Bit in jedem Befehl wackeln können

3) Sie lernen den Befehlssatz besser als die meisten Ingenieure, die diesen Befehlssatz verwenden, um ihren Lebensunterhalt zu verdienen

In Ihrem Fall gibt es ein paar Probleme. Normalerweise empfehle ich zunächst den ARM-Befehlssatz. Heute werden mehr ARM-basierte Produkte ausgeliefert als alle anderen (einschließlich x86-Computer). Die Wahrscheinlichkeit, dass Sie ARM jetzt verwenden und nicht genügend Assembler kennen, um Startcode oder andere Routinen zu schreiben, die ARM kennen, kann jedoch helfen oder auch nicht, was Sie versuchen. Der zweite und wichtigere Grund für ARM ist, dass die Befehlslängen eine feste Größe haben und ausgerichtet sind. Das Zerlegen von Anweisungen mit variabler Länge wie x86 kann als erstes Projekt ein Albtraum sein. Ziel ist es, den Befehlssatz zu erlernen, um kein Forschungsprojekt zu erstellen. Der dritte ARM ist ein gut gemachter Befehlssatz, Register werden gleich erstellt und haben keine individuellen Spezialnuancen.

Sie müssen also herausfinden, mit welchem ​​Prozessor Sie beginnen möchten. Ich schlage zuerst den msp430 oder ARM vor, dann zuerst den ARM oder dann das Chaos von x86. Unabhängig von der Plattform verfügt jede Plattform, die es wert ist, verwendet zu werden, über Datenblätter oder Referenzhandbücher für Programmierer, die vom Hersteller frei sind und den Befehlssatz sowie die Codierung der Opcodes (die Bits und Bytes der Maschinensprache) enthalten. Um zu lernen, was der Compiler tut und wie man Code schreibt, mit dem der Compiler nicht zu kämpfen hat, ist es gut, einige Befehlssätze zu kennen und zu sehen, wie bei jedem Optimierungssatz mit jedem Compiler bei jeder Optimierung derselbe Code auf hoher Ebene implementiert wird Rahmen. Sie möchten Ihren Code nicht nur optimieren, um festzustellen, dass Sie ihn für einen Compiler / eine Plattform besser, für jeden anderen jedoch viel schlechter gemacht haben.

Oh, zum Zerlegen von Befehlssätzen mit variabler Länge, anstatt einfach am Anfang zu beginnen und jedes 4-Byte-Wort linear durch den Speicher zu zerlegen, wie Sie es mit dem ARM oder alle zwei Bytes wie beim msp430 tun würden (Der msp430 verfügt über Befehle mit variabler Länge, aber Sie können trotzdem durchkommen linear durch den Speicher gehen, wenn Sie an den Einstiegspunkten aus der Interrupt-Vektortabelle beginnen). Für eine variable Länge möchten Sie einen Einstiegspunkt finden, der auf einer Vektortabelle oder dem Wissen darüber basiert, wie der Prozessor startet, und dem Code in der Ausführungsreihenfolge folgen. Sie müssen jeden Befehl vollständig dekodieren, um zu wissen, wie viele Bytes verwendet werden. Wenn der Befehl kein bedingungsloser Zweig ist, nehmen Sie an, dass das nächste Byte nach diesem Befehl ein anderer Befehl ist. Sie müssen auch alle möglichen Zweigadressen speichern und davon ausgehen, dass dies die Startbyte-Adressen für weitere Anweisungen sind. Als ich einmal erfolgreich war, habe ich mehrere Durchgänge durch die Binärdatei gemacht. Beginnend am Einstiegspunkt habe ich dieses Byte als Beginn eines Befehls markiert und dann linear durch den Speicher dekodiert, bis ich einen bedingungslosen Zweig getroffen habe. Alle Verzweigungsziele wurden als Startadressen einer Anweisung markiert. Ich habe mehrere Durchgänge durch die Binärdatei gemacht, bis ich keine neuen Verzweigungsziele gefunden hatte. Wenn Sie zu irgendeinem Zeitpunkt beispielsweise eine 3-Byte-Anweisung finden, aber aus irgendeinem Grund das zweite Byte als Beginn einer Anweisung markiert haben, liegt ein Problem vor. Wenn der Code von einem High-Level-Compiler generiert wurde, sollte dies nur geschehen, wenn der Compiler etwas Böses tut. Wenn der Code einen handgeschriebenen Assembler enthält (wie beispielsweise ein altes Arcade-Spiel), ist es durchaus möglich, dass es bedingte Verzweigungen gibt, die niemals wie r0 = 0 auftreten können, gefolgt von einem Sprung, wenn nicht Null. Möglicherweise müssen Sie diese aus der Binärdatei heraus bearbeiten, um fortzufahren. Für Ihre unmittelbaren Ziele, von denen ich annehme, dass sie auf x86 liegen, glaube ich nicht, dass Sie ein Problem haben werden.

Ich empfehle die gcc-Tools. Mingw32 ist eine einfache Möglichkeit, gcc-Tools unter Windows zu verwenden, wenn x86 Ihr Ziel ist. Wenn nicht, ist mingw32 plus msys eine hervorragende Plattform zum Generieren eines Cross-Compilers aus binutils und gcc-Quellen (im Allgemeinen ziemlich einfach). mingw32 hat einige Vorteile gegenüber Cygwin, wie deutlich schnellere Programme und Sie vermeiden die Hölle der Cygwin-DLL. Mit gcc und binutils können Sie in C oder Assembler schreiben und Ihren Code zerlegen. Es gibt mehr Webseiten als Sie lesen können, die Ihnen zeigen, wie Sie eine oder alle drei Methoden ausführen. Wenn Sie dies mit einem Befehlssatz variabler Länge tun, empfehle ich dringend, einen Werkzeugsatz zu verwenden, der einen Disassembler enthält. Ein Disassembler von Drittanbietern für x86 wird beispielsweise eine Herausforderung sein, da Sie nie wirklich wissen, ob er korrekt zerlegt wurde. Einiges davon hängt auch vom Betriebssystem ab. Ziel ist es, die Module in ein Binärformat zu kompilieren, das Anweisungen zum Markieren von Informationen aus Daten enthält, damit der Disassembler eine genauere Arbeit leisten kann. Ihre andere Wahl für dieses primäre Ziel ist es, ein Tool zu haben, das direkt zu Assembler für Ihre Inspektion kompiliert werden kann, und dann zu hoffen, dass es beim Kompilieren in ein Binärformat dieselben Anweisungen erstellt.

Die kurze (okay etwas kürzere) Antwort auf Ihre Frage. Schreiben Sie einen Disassembler, um einen Befehlssatz zu lernen. Ich würde mit etwas RISCY beginnen und leicht zu lernen wie ARM. Sobald Sie einen Befehlssatz kennen, lassen sich andere, oft in wenigen Stunden, viel einfacher erlernen. Mit dem dritten Befehlssatz können Sie fast sofort mit dem Schreiben von Code beginnen, indem Sie das Datenblatt / Referenzhandbuch für die Syntax verwenden. Alle Prozessoren, die es wert sind, verwendet zu werden, verfügen über ein Datenblatt oder ein Referenzhandbuch, das die Anweisungen bis auf die Bits und Bytes der Opcodes beschreibt. Lernen Sie einen RISC-Prozessor wie ARM und einen CISC wie x86 genug, um ein Gefühl für die Unterschiede zu bekommen, z. B. Register für alles durchlaufen zu müssen oder Operationen direkt im Speicher mit weniger oder keinen Registern ausführen zu können. Drei Operandenanweisungen gegen zwei usw. Während Sie Ihren High-Level-Code optimieren, Kompilieren Sie für mehr als einen Prozessor und vergleichen Sie die Ausgabe. Das Wichtigste, was Sie lernen werden, ist, dass unabhängig davon, wie gut der Code auf hoher Ebene geschrieben ist, die Qualität des Compilers und die getroffenen Optimierungsentscheidungen einen großen Unterschied in den tatsächlichen Anweisungen bewirken. Ich empfehle llvm und gcc (mit binutils), keine produzierenToller Code, aber sie sind Multi-Plattform und Multi-Target und beide haben Optimierer. Und beide sind kostenlos und Sie können problemlos Cross-Compiler aus Quellen für verschiedene Zielprozessoren erstellen.


Danke für die Antwort. Aber ich weiß nicht einmal, wie man einen Disassembler schreibt.
verschlungenes Elysium

8
"Schreiben Sie Ihren eigenen Disassembler" - ich stimme zu, so habe ich es am besten gelernt. (Was ist los mit "Aber ich weiß nicht einmal, wie man einen Disassembler schreibt"?) LOL.
Slashmais

Ich gehe mit dir! Habe gerade einen MSP430 und ein Buch darüber gekauft ... :)
Pepe

1
Ich habe einige msp430-Beispiele github.com/dwelch67 sowie einige Befehlssatzsimulatoren zum Experimentieren, einschließlich des Lernens von
Asm

Ich mag diese Idee wirklich sehr.
Millie Smith

33

Die Assembly, die Sie von Hand schreiben würden, und die von einem Compiler generierte Assembly unterscheiden sich häufig stark, wenn sie von einer hohen Ebene aus betrachtet werden. Natürlich sind die Innereien des Programms sehr ähnlich (es gibt schließlich nur so viele verschiedene Möglichkeiten zum Codieren a = b + c), aber sie sind nicht das Problem, wenn Sie versuchen, etwas zurückzuentwickeln. Der Compiler wird eine hinzufügen Tonne Standardcode zu selbst einfachen ausführbaren Dateien: letztes Mal , dass ich im Vergleich zu „Hallo Welt“ von GCC kompiliert wurde etwa 4 kB, während , wenn in der Montage von Hand geschrieben ist es rund 100 Bytes. Unter Windows ist es schlimmer: Beim letzten Vergleich (zugegebenermaßen war dies das letzte Jahrhundert) Die kleinste "Hallo Welt", die ich mit meinem Windows-Compiler meiner Wahl generieren konnte, war 52kB! Normalerweise wird dieses Boilerplate nur einmal ausgeführt, wenn überhaupt, so dass es die Programmgeschwindigkeit nicht wesentlich beeinflusst - wie ich oben sagte, ist der Kern des Programms, der Teil, in dem die meiste Ausführungszeit verbracht wird, normalerweise ziemlich ähnlich, ob kompiliert oder von Hand geschrieben.

Am Ende des Tages, bedeutet dies , dass eine fachgerechte Montage Programmierer und Experte Disassembler zwei verschiedene Spezialitäten. Normalerweise befinden sie sich in derselben Person, aber sie sind wirklich getrennt, und das Erlernen, wie man ein ausgezeichneter Baugruppencodierer ist, hilft Ihnen nicht so viel, um Reverse Engineering zu lernen.

Sie möchten lediglich die Architekturhandbücher IA-32 und AMD64 (beide werden zusammen behandelt) von Intel und AMD herunterladen und die ersten Abschnitte mit Anweisungen und Opcodes lesen. Lesen Sie vielleicht ein oder zwei Tutorials zur Assemblersprache, um die Grundlagen der Assemblersprache zu verstehen. Dann schnapp dir einen kleinenBeispielprogramm, an dem Sie interessiert sind, und Zerlegen: Durchlaufen Sie den Kontrollfluss und versuchen Sie zu verstehen, was es tut. Überprüfen Sie, ob Sie es patchen können, um etwas anderes zu tun. Versuchen Sie es dann erneut mit einem anderen Programm und wiederholen Sie den Vorgang, bis Sie sich wohl genug fühlen, um ein nützlicheres Ziel zu erreichen. Sie könnten an Dingen wie "Crackmes" interessiert sein, die von der Reverse Engineering-Community produziert werden. Dies sind Herausforderungen für Leute, die sich für Reverse Engineering interessieren, um sich zu versuchen und hoffentlich etwas auf dem Weg zu lernen. Sie reichen von einfach (hier anfangen!) Bis unmöglich.

Vor allem müssen Sie nur üben . Wie in vielen anderen Disziplinen macht beim Reverse Engineering die Übung den Meister ... oder zumindest besser .


Ich weiß, wenn Sie etwas mit einer Hochsprache kompilieren, erhalten Sie eine Menge "Müll" -Code, der nicht benötigt wird, da er direkt in der Assembly codiert wurde. Ich verstehe auch, dass es einen Unterschied zwischen einem erfahrenen Assembler-Programmierer und einem erfahrenen Disassembler gibt. Aber das Gleiche gilt für fast alles andere.
verschlungenes Elysium

3
Ich mache mir Sorgen, dass ich theoretisch die Zeitungen lesen und verstehen könnte, was sie bedeuten, bis ich anfange, Dinge selbst zu schreiben. Ich glaube nicht, dass ich es wirklich verstehen werde. Sie sagen, ich kann damit beginnen, kleine Teile des Codes zu ändern, aber dazu muss ich zuerst wissen, welche Art von Assembly "Flavour" IDA Pro zum Beispiel verwendet.
verschlungenes Elysium

Was verwendet MSVC ++ für den Inline-Assemblycode? MASMUS?
verschlungenes Elysium

15

Ich werde gegen den Strich der meisten Antworten gehen und Knuths MMIX- Variante der MIPS RISC-Architektur empfehlen . Es wird nicht so praktisch nützlich sein wie x86- oder ARM-Assemblersprachen (nicht, dass sie heutzutage in den meisten realen Jobs so wichtig sind ... ;-), aber es wird für Sie die Magie von Knuths neuesten freischalten Version des bisher größten Meisterwerks zum tiefen Verständnis von Algorithmen und Datenstrukturen auf niedriger Ebene - TAOCP , "The Art of Computer Programming". Die Links von den beiden URLs, die ich zitiert habe, sind eine großartige Möglichkeit, diese Möglichkeit zu erkunden!


12

(Ich weiß nichts über dich, aber ich war begeistert von der Montage)

Auf Ihrem PC ist bereits ein einfaches Tool zum Experimentieren mit Baugruppen installiert.

Gehen Sie zu Startmenü-> Ausführen und geben Sie eindebug

Debug (Befehl)

debug ist ein Befehl unter DOS, MS-DOS, OS / 2 und Microsoft Windows (nur x86-Versionen, nicht x64), mit dem das Programm debug.exe (oder DEBUG.COM in älteren DOS-Versionen) ausgeführt wird. Debug kann als Assembler-, Disassembler- oder Hex-Dump-Programm fungieren, mit dem Benutzer den Speicherinhalt (in Assemblersprache, Hexadezimal oder ASCII) interaktiv untersuchen, Änderungen vornehmen und selektiv COM-, EXE- und andere Dateitypen ausführen können. Es gibt auch mehrere Unterbefehle, mit denen auf bestimmte Festplattensektoren, E / A-Ports und Speicheradressen zugegriffen werden kann. MS-DOS Debug wird auf einer 16-Bit-Prozessebene ausgeführt und ist daher auf 16-Bit-Computerprogramme beschränkt . FreeDOS Debug hat eine "DEBUGX" -Version, die auch 32-Bit-DPMI-Programme unterstützt.

Tutorials:


Wenn Sie den Code verstehen möchten, den Sie in IDA Pro (oder OllyDbg ) sehen, müssen Sie lernen, wie kompilierter Code strukturiert ist. Ich empfehle das Buch Reversing: Secrets of Reverse Engineering

Ich habe ein paar Wochen lang experimentiert, debugals ich anfing, Montage zu lernen (vor 15 Jahren).
Beachten Sie, dass debugauf Basismaschinenebene keine Assembly-Befehle auf hoher Ebene vorhanden sind.

Und jetzt ein einfaches Beispiel:

Geben Sie aan, um mit dem Schreiben von Assembly-Code zu beginnen - geben gSie das folgende Programm ein - und geben Sie schließlich an, um es auszuführen.

Alt-Text


( INT 21Zeigen Sie auf dem Bildschirm das im DLRegister gespeicherte ASCII-Zeichen an , wenn das AHRegister auf 2- INT 20das Programm beendet) eingestellt ist.)


Ich musste Strg-C drücken, bevor ich "g" eingeben konnte.
Ericp

2
@ericp, du musst nicht Strg-C drücken. Sie geben beispielsweise a& [enter] ein, um mit dem Schreiben des Assemblycodes zu beginnen. Wenn Sie zweimal [Enter] drücken, verlassen Sie den Assembly-Modus. g& [Enter], um es auszuführen (standardmäßig Offset 100).
Nick Dandoulakis

Verursacht es tatsächlich einen Stapelüberlauf oder schreibt es ihn einfach auf den Bildschirm?
Janus Troelsen

1
@user, es schreibt nur den Namen dieser Seite :-)
Nick Dandoulakis

@JanusTroelsen Diese Nummern (53, 74, 61 usw.) sind die ASCII-Codes für 'S' 't' 'a' ... Jeder Int21-Aufruf druckt jeweils ein Zeichen! Dies ist, warum die Montage nicht schneller ist :)
Doug65536

8

Ich fand, dass Hacking: The Art of Exploitation ein interessanter und nützlicher Weg in dieses Thema ist ... ich kann nicht sagen, dass ich das Wissen jemals direkt genutzt habe, aber das ist wirklich nicht der Grund, warum ich es gelesen habe. Sie erhalten ein viel besseres Verständnis für die Anweisungen, nach denen Ihr Code kompiliert wird, was gelegentlich hilfreich war, um subtilere Fehler zu verstehen.

Lassen Sie sich vom Titel nicht abschrecken. Der größte Teil des ersten Teils des Buches ist "Hacking" im Sinne von Eric Raymond: kreative, überraschende, fast hinterhältige Wege, um schwierige Probleme zu lösen. Ich (und vielleicht Sie) waren viel weniger an den Sicherheitsaspekten interessiert.


7

Ich würde mich nicht darauf konzentrieren, Programme in Assembly zu schreiben, zumindest zunächst nicht. Wenn Sie auf x86 arbeiten (was ich vermute, da Sie Windows verwenden), gibt es unzählige seltsame Sonderfälle, deren Erlernen sinnlos ist. Beispielsweise setzen viele Anweisungen voraus, dass Sie mit einem Register arbeiten, das Sie nicht explizit benennen, und andere Anweisungen funktionieren mit einigen Registern, anderen jedoch nicht.

Ich würde gerade genug über Ihre beabsichtigte Architektur lernen, um die Grundlagen zu verstehen, dann einfach direkt hineinspringen und versuchen, die Ausgabe Ihres Compilers zu verstehen. Bewaffne dich mit den Intel-Handbüchern aus und tauchen Sie direkt in die Ausgabe Ihres Compilers ein. Isolieren Sie den Code von Interesse in eine kleine Funktion, damit Sie sicher sein können, das Ganze zu verstehen.

Ich würde die Grundlagen wie folgt betrachten:

  • Register: Wie viele gibt es, wie heißen sie und wie groß sind sie?
  • Operandenreihenfolge: add eax, ebxbedeutet "Fügen Sie ebx zu eax hinzu und speichern Sie das Ergebnis in eax".
  • FPU: Lernen Sie die Grundlagen des Gleitkommastapels und wie Sie in / von fp konvertieren.
  • Adressierungsmodi: [Basis + Offset * Multiplikator], aber der Multiplikator kann nur 1, 2 oder 4 sein (oder vielleicht 8?)
  • Aufrufkonventionen: Wie werden Parameter an eine Funktion übergeben?

In den meisten Fällen wird es überraschend sein, was der Compiler ausgibt. Machen Sie es zu einem Rätsel, herauszufinden, warum zum Teufel der Compiler dies für eine gute Idee hielt. Es wird dir viel beibringen.

Es wird wahrscheinlich auch hilfreich sein, sich mit den Handbüchern von Agner Fog zu bewaffnen , insbesondere mit der Anleitung, in der eine aufgeführt ist. Es wird Ihnen ungefähr sagen, wie teuer jeder Befehl ist, obwohl dies auf modernen Prozessoren schwieriger direkt zu quantifizieren ist. Aber es wird helfen zu erklären, warum zum Beispiel der Compiler so weit aus dem Weg geht, um die Ausgabe eines zu vermeidenidiv Anweisung .

Mein einziger anderer Rat ist, immer Intel-Syntax anstelle von AT & T zu verwenden, wenn Sie die Wahl haben. Ich war in diesem Punkt ziemlich neutral, bis mir klar wurde, dass einige Anweisungen zwischen den beiden völlig unterschiedlich sind (zum Beispiel movslqin der AT & T-Syntax movsxdin der Intel-Syntax). Da die Handbücher alle mit Intel-Syntax geschrieben sind, bleiben Sie einfach dabei.

Viel Glück!


3

Ich habe angefangen, MIPS zu lernen, eine sehr kompakte 32-Bit-Architektur. Es ist ein reduzierter Befehlssatz, aber das macht es für Anfänger leicht verständlich. Sie werden immer noch verstehen, wie die Montage funktioniert, ohne von der Komplexität überfordert zu sein. Sie können sogar eine nette kleine IDE herunterladen, mit der Sie Ihren MIPS-Code kompilieren können: clicky Sobald Sie den Dreh raus haben, ist es meiner Meinung nach viel einfacher, zu komplexeren Architekturen überzugehen . Zumindest dachte ich das :) An diesem Punkt haben Sie die wesentlichen Kenntnisse über Speicherzuweisung und -verwaltung, Logikfluss, Debugging, Testen usw.


3

Der Vorschlag, Debug zu verwenden, macht Spaß, damit können viele nette Tricks gemacht werden. Für ein modernes Betriebssystem kann das Erlernen der 16-Bit-Assemblierung jedoch etwas weniger nützlich sein. Verwenden Sie stattdessen ntsd.exe. Es ist in Windows XP integriert (es wurde leider in Server 2003 und höher gerissen), was es zu einem praktischen Lernwerkzeug macht, da es so weit verbreitet ist.

Die ursprüngliche Version in XP weist jedoch eine Reihe von Fehlern auf. Wenn Sie es wirklich verwenden möchten (oder cdb oder windbg, bei denen es sich im Wesentlichen um unterschiedliche Schnittstellen mit derselben Befehlssyntax und demselben Debugging-Backend handelt), sollten Sie das kostenlose Windows-Debugging- Toolpaket installieren .

Die in diesem Paket enthaltene Datei debugger.chm ist besonders nützlich, wenn Sie versuchen, die ungewöhnliche Syntax herauszufinden.

Das Tolle an ntsd ist, dass Sie es auf jedem XP-Computer in Ihrer Nähe anzeigen und zum Zusammenbauen oder Zerlegen verwenden können. Es ist ein / great / X86-Assembly-Lernwerkzeug. Zum Beispiel (mit cdb, da es in der dos-Eingabeaufforderung inline ist, ist es ansonsten identisch):

(Symbolfehler wurden übersprungen, da sie irrelevant sind - ich hoffe auch, dass diese Formatierung funktioniert, dies ist mein erster Beitrag)

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

Außerdem - während Sie mit IDA spielen, lesen Sie unbedingt das IDA Pro Book von Chris Eagle (nicht verbunden, da StackOverflow nicht zulässt, dass ich mehr als zwei Links für meinen ersten Beitrag poste). Es ist zweifellos die beste Referenz da draußen.


1
+1 für Chris Adlers Buch. Ich muss etwas Liebe für den Sk3wl von r00t hineinstecken;)
mrduclaw

3

Ich habe kürzlich einen Kurs über Computersysteme besucht. Eines der Themen war Assembly als Werkzeug zur Kommunikation mit der Hardware.

Für mich wäre das Wissen über die Montage nicht vollständig gewesen, ohne die Details der Funktionsweise von Computersystemen zu verstehen. Wenn Sie dies verstehen, erhalten Sie ein neues Verständnis dafür, warum Montageanweisungen auf einer Prozessorarchitektur großartig sind, auf einer anderen Architektur jedoch schrecklich.

Vor diesem Hintergrund neige ich dazu, mein Lehrbuch zu empfehlen:

Computersysteme: Die Perspektive eines Programmierers .

Computersysteme: Die Perspektive eines Programmierers
(Quelle: cmu.edu )

Es behandelt zwar die x86-Assembly, aber das Buch ist viel umfassender. Es behandelt Prozessor-Pipe-Lining und Speicher als Cache, das virtuelle Speichersystem und vieles mehr. All dies kann sich darauf auswirken, wie die Baugruppe für die angegebenen Funktionen optimiert werden kann.


2

Ich denke, Sie möchten die ASCII-basierten Opcode-Mnemoniken (und ihre Parameter) lernen, die von einem Disassembler ausgegeben werden und die von einem Assembler verstanden werden (als Eingabe für einen Assembler verwendet werden können).

Jeder Assembler (zB MASM) würde dies tun.

Und / oder es ist vielleicht besser für Sie, ein Buch darüber zu lesen (es wurden Bücher zu SO empfohlen, ich weiß nicht mehr, welche).


2

Machst du andere Entwicklungsarbeiten an Windows? Auf welcher IDE? Wenn es sich um VS handelt, ist keine zusätzliche IDE erforderlich, um nur zerlegten Code zu lesen: Debuggen Sie Ihre App (oder hängen Sie sie an eine externe App an), und öffnen Sie dann das Demontagefenster (in den Standardeinstellungen ist dies Alt + 8). Schritt und beobachten Sie Speicher / Register wie durch normalen Code. Möglicherweise möchten Sie auch ein Registerfenster geöffnet lassen (standardmäßig Alt + 5).

Intel bietet kostenlose Handbücher an , die sowohl einen Überblick über die grundlegende Architektur (Register, Prozessoreinheiten usw.) als auch eine vollständige Referenz geben. Mit zunehmender Reife der Architektur und zunehmender Komplexität werden die Handbücher zur Basisarchitektur immer weniger lesbar. Wenn Sie eine ältere Version in die Hände bekommen können, haben Sie wahrscheinlich einen besseren Ausgangspunkt (sogar P3-Handbücher - sie erklären dasselbe besser grundlegende Ausführungsumgebung).

Wenn Sie in ein Buch investieren möchten, finden Sie hier einen schönen Einführungstext. Suchen Sie bei Amazon nach 'x86' und Sie erhalten viele andere. Sie können mehrere andere Richtungen von einer anderen Frage hier erhalten .

Schließlich können Sie von ziemlich viel profitieren lesen einige Low - Level Blogs. Diese Byte-Info-Bits funktionieren für mich persönlich am besten.


2

Dies wird Ihnen nicht unbedingt helfen, effizienten Code zu schreiben!

i86-Op-Codes sind mehr oder weniger ein "Legacy" -Format, das aufgrund des enormen Codevolumens und der ausführbaren Binärdateien für Windows und Linux bestehen bleibt.

Es ist ein bisschen wie bei den alten Gelehrten, die auf Latein schreiben, ein italienischer Sprecher wie Galileo würde auf Latein schreiben und seine Arbeit könnte von einem polnischen Sprecher wie Copernicus verstanden werden. Dies war immer noch die effektivste Art zu kommunizieren, obwohl niether besonders gut in Latein war und Latein eine Müllsprache ist, um mathematische Ideen auszudrücken.

Daher generieren Compiler standardmäßig x86-Code, und moderne Chips lesen die Anceint-Op-Codes und wandeln das, was sie sehen, in parallele Risc-Anweisungen um, wobei die Ausführung neu angeordnet, die spekulative Ausführung, das Pipelining usw. durchgeführt werden. Außerdem nutzen sie die 32- oder 64-Register des Prozessors vollständig aus hat tatsächlich (im Gegensatz zu der erbärmlichen 8, die Sie in x86-Anweisungen sehen.)

Jetzt wissen alle optimierenden Compiler, dass dies wirklich passiert, und codieren Sequenzen von OP-Codes, von denen sie wissen, dass der Chip sie effizient optimieren kann - obwohl einige dieser Sequenzen für einen .asm-Programmierer von ca. 1990 ineffizient erscheinen würden.

Irgendwann müssen Sie akzeptieren, dass sich die Zehntausende von Mannjahren, die Compiler-Autoren unternommen haben, ausgezahlt haben, und ihnen vertrauen.

Der einfachste und einfachste Weg, um eine effizientere Laufzeit zu erzielen, ist der Kauf des Intel C / C ++ - Compilers. Sie haben einen Nischenmarkt für Efficeint-Compiler und haben den Vorteil, dass sie die Chip-Designer fragen können, was im Inneren vor sich geht.


Ihre Geschichte deutet etwas darauf hin, dass CISC-Prozessoren intern zu RISC-Prozessoren geworden sind. Ich habe vielleicht falsch verstanden, aber das ist einfach nicht wahr. Und die erbärmliche 8? Moderne Prozessoren (etwa seit 1999) umfassen viele weitere: 10 gpr: EAX-EFLAGS, 80-Bit-FP0-FP7, 64-Bit-MMX0-MMX7, 128-Bit-XMM0-XMM7, Segment: CS-GS, Specials: CR0-CR4 , DR0-DR7, TR3-TR7, GDTR, IDTR, LDTR, MSRs und auf x86-64 auch R8-R15. Nicht alle davon sind über Ring-3 zugänglich, aber die meisten werden und werden von neueren (nach 2006) GCC / VC ++ - Compilern verwendet. Insgesamt etwas mehr als die "erbärmliche 8";).
Abel

2

Um das zu tun, was Sie tun möchten, habe ich nur die Intel-Befehlssatzreferenz (möglicherweise nicht die genaue, die ich verwendet habe, aber sie sieht ausreichend aus) und einige einfache Programme, die ich in Visual Studio geschrieben habe, verwendet und sie in IDAPro / Windbg geworfen . Als ich meine eigenen Programme herauswuchs, war die Software bei crackmes hilfreich.

Ich gehe davon aus, dass Sie ein grundlegendes Verständnis dafür haben, wie Programme unter Windows ausgeführt werden. Aber wirklich, zum Lesen von Assemblys gibt es nur ein paar Anweisungen zu lernen und ein paar Varianten dieser Anweisungen (z. B. gibt es eine Sprunganweisung, Sprung hat ein paar Geschmacksrichtungen wie Sprung-wenn-gleich, Sprung-wenn-ecx-ist-Null , etc). Sobald Sie die grundlegenden Anweisungen gelernt haben, ist es ziemlich einfach, den Kern der Programmausführung zu erhalten. Die Grafikansicht von IDA hilft, und wenn Sie das Programm mit Windbg verfolgen, ist es ziemlich einfach herauszufinden, was die Anweisungen tun, wenn Sie sich nicht sicher sind.

Nachdem ich so ein bisschen gespielt hatte, kaufte ich Hacker Disassembly Uncovered . Im Allgemeinen halte ich mich von Büchern mit dem Wort "Hacker" im Titel fern, aber mir hat sehr gut gefallen, wie ausführlich darüber berichtet wurde, wie kompilierter Code zerlegt aussah. Er geht auch auf Compiler-Optimierungen und einige interessante Dinge zur Effizienz ein.

Es hängt wirklich davon ab, wie tief Sie das Programm auch verstehen wollen. Wenn Sie ein Ziel, das nach Schwachstellen sucht, rückentwickeln, Exploit-Code schreiben oder gepackte Malware auf Funktionen analysieren, benötigen Sie mehr Zeit, um die Dinge wirklich in Gang zu bringen (insbesondere bei fortgeschrittener Malware) ). Wenn Sie jedoch nur in der Lage sein möchten, das Level Ihres Charakters in Ihrem Lieblingsvideospiel zu ändern, sollten Sie in relativ kurzer Zeit gut abschneiden.


1

Eine der üblichen pädagogischen Assemblersprachen ist MIPS. Sie können MIPS-Simulatoren (Spim) und verschiedene Lehrmaterialien dafür erhalten.

Persönlich bin ich kein Fan. Ich mag IA32 lieber.


MIPS ist nett. 68000 ist auch, und wenn Sie 68000 lernen, können Sie Binärdateien schreiben, die in MAME ausgeführt werden. :-)
Nosredna

1

Mein persönlicher Favorit ist NASM, vor allem, weil es plattformübergreifend ist und MMX, SSE, 64-Bit ...

Ich fing an, eine einfache C-Quelldatei mit gcc zu kompilieren und die Assembler-Anweisung vom gcc-Format in das NASM-Format zu "transkodieren". Dann können Sie kleine Teile des Codes ändern und die damit verbundene Leistungsverbesserung überprüfen.

Die NASM-Dokumentation ist wirklich vollständig. Ich musste nie nach Informationen aus Büchern oder anderen Quellen suchen.



0

Viele gute Antworten hier. Low-Level-Programmierung, Assembly usw. sind in der Sicherheitsgemeinschaft sehr beliebt. Es lohnt sich daher, dort nach Hinweisen und Tipps zu suchen, sobald Sie loslegen. Sie haben sogar einige gute Tutorials wie dieses auf x86-Assembly .


0

Um Ihr Ziel tatsächlich zu erreichen, sollten Sie mit der IDE beginnen, in der Sie sich befinden. Das Fenster ist im Allgemeinen ein Disassembler-Fenster, sodass Sie einen einzelnen Schritt durch den Code ausführen können. Normalerweise gibt es eine Art Ansicht, mit der Sie die Register sehen und in Speicherbereiche schauen können.

Die Untersuchung von nicht optimiertem c / c ++ - Code hilft dabei, einen Link zu der Art von Code zu erstellen, die der Compiler für Ihre Quellen generiert. Einige Compiler haben eine Art von ASM-reserviertem Wort, mit dem Sie Maschinenanweisungen in Ihren Code einfügen können.

Mein Rat wäre, eine Weile mit solchen Werkzeugen herumzuspielen, die Füße nass zu machen und dann aufzusteigen? Nieder? um den Assembler-Code auf jeder Plattform, auf der Sie ausgeführt werden, zu korrigieren.

Es gibt viele großartige Tools, aber vielleicht macht es mehr Spaß, die steile Lernkurve zunächst zu vermeiden.


0

Wir haben die Montage mit einem Mikrocontroller-Entwicklungskit (Motorola HC12) und einem dicken Datenblatt gelernt.


0

Ich weiß, dass es kein Thema ist, aber da Sie ein Windows-Programmierer sind, kann ich nicht anders, als zu glauben, dass es eine angemessenere und / oder bessere Nutzung Ihrer Zeit zum Erlernen von MSIL ist. Nein, es ist keine Assembly, aber in dieser .NET-Ära ist es wahrscheinlich relevanter.


0

Das Wissen über Assembly kann beim Debuggen hilfreich sein, aber ich würde mich nicht allzu sehr darüber freuen, sie zur Optimierung Ihres Codes zu verwenden. Moderne Compiler sind heutzutage in der Regel viel besser darin, einen Menschen zu optimieren.


Hmm. Sie können selbst noch einiges an zusätzlicher Codierungsbaugruppe auswringen, aber es erfordert mehr Arbeit, um den Compiler zu schlagen als früher.
Nosredna

0

Sie können sich den Videokurs xorpd x86 Assembly ansehen . (Ich schrieb es). Der Kurs selbst ist bezahlt, aber die Übungen sind Open-Source-Übungen auf Github. Wenn Sie Programmiererfahrung haben, sollten Sie in der Lage sein, nur mit den Übungen zu arbeiten und alles zu verstehen.

Beachten Sie, dass der Code für die Windows-Plattform bestimmt ist und mit dem Fasm-Assembler geschrieben wurde . Der Kurs und die Übungen enthalten keine Konstrukte auf hoher Ebene. Sie können jedoch Fasm verwenden, um sehr komplizierte Makros zu erstellen, falls Sie dies jemals möchten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.