Diassemblieren: Unterschied zwischen den Versionen
KKeine Bearbeitungszusammenfassung |
KKeine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
== Einleitung == | |||
Das Disassemblieren ist der Prozess, bei dem aus Maschinencode wieder menschenlesbarer Assembler-Code erzeugt wird. Es ist ein wichtiges Werkzeug für: | |||
* Debugging: Nachvollziehen, was das Programm tatsächlich macht. | |||
* Reverse Engineering: Verstehen fremder Binärdateien. | |||
* Optimierung: Erkennen ineffizienter Codeabschnitte. | |||
*Lernen: Verstehen, wie Hochsprachen wie C übersetzt werden. | |||
== Werkzeuge == | |||
Für ARM64 unter Linux – z. B. auf dem Raspberry Pi – bieten sich diese Tools an: | |||
=== objdump === | |||
Teil von `binutils`. Zeigt dir den Assembler-Code aus Objektdateien oder Binärprogrammen an. Dies ist auch meine bevorzugte Art, um etwas zu Diassemblieren. | |||
<syntaxhighlight lang="shell"> | |||
objdump -d ./blink | |||
</syntaxhighlight> | |||
Optionen: | |||
* `-d` disassembliert ausführbare Abschnitte. | |||
* `-M reg-names=std` (optional): zeigt Standard-Registerbezeichnungen (x0–x30). | |||
* `-M no-aliases` (zeigt die "echten" Instruktionsnamen statt Pseudonyme). | |||
Beispiel: | |||
<syntaxhighlight lang="shell"> | |||
objdump -d -M reg-names=std ./blink | |||
</syntaxhighlight> | |||
=== gdb === | |||
Mit `gdb` (GNU Debugger) kannst du direkt im Programmfluss disassemblieren. | |||
<syntaxhighlight lang="shell"> | |||
gdb ./blink | |||
(gdb) disassemble _start | |||
</syntaxhighlight> | |||
== Praktische Tipps == | |||
* Achte auf die ''Sectionen'': `.text` ist der Code, andere wie `.data` oder `.bss` enthalten keine Instruktionen. | |||
* Prüfe, ob deine Datei ''nicht mit Strip'' bearbeitet wurde (`strip` entfernt Debugsymbole). | |||
* Wenn du aus einer reinen Binärdatei (ohne ELF-Header) disassemblieren willst, nutze `objdump` mit `--target binary` und `--architecture aarch64`. | |||
Beispiel: | |||
<syntaxhighlight lang="shell"> | |||
objdump -D -b binary -m aarch64 your.bin | |||
</syntaxhighlight> | |||
== Worauf achten? == | |||
* Alignment: ARM64 nutzt 4-Byte ausgerichtete Instruktionen. | |||
* Branch-Adressen: Bei `b`, `bl`, `cbz`, `ret` und Co. kannst du nachvollziehen, wo dein Programm hin springt. | |||
* System Calls: erkenne z. B. `mov x8, #93; svc 0` als `exit(0)`. | |||
* Speicherzugriffe: beachte, welche Register für Adressierung verwendet werden. | |||
== `objdump` im Detail: Parameter und ihre Bedeutung == | |||
`objdump` ist ein sehr vielseitiges Werkzeug. Besonders beim Disassemblieren von ARM64-Binärdateien ist es hilfreich, die wichtigsten Optionen zu kennen. | |||
=== Grundstruktur des Befehls === | |||
<syntaxhighlight lang="shell"> | |||
objdump [OPTIONEN] DATEI | |||
</syntaxhighlight> | |||
=== Wichtige Optionen beim Disassemblieren === | |||
| Option | Beschreibung | | |||
|--------|--------------| | |||
| `-d` | Disassembliert alle **ausführbaren Segmente** (z. B. `.text`). | | |||
| `-D` | Disassembliert **die gesamte Datei**, auch nicht-ausführbare Abschnitte. Nützlich bei rohen Binärdateien oder unüblichen Formaten. | | |||
| `-M <option>` | Legt das Disassemblierungsformat fest. Mehrere Optionen sind durch Kommas trennbar (z. B. `-M reg-names=std,no-aliases`). | | |||
| `--section=<name>` | Disassembliert **nur eine bestimmte Sektion**, z. B. `.text`. | | |||
| `--start-address=0xADDR` | Beginnt das Disassemblieren **ab dieser Adresse**. | | |||
| `--stop-address=0xADDR` | Hört bei dieser Adresse auf. | | |||
| `--architecture=aarch64` | Setzt die Architektur explizit, z. B. bei rohen Binärdateien. | | |||
| `-b binary` | Interpretiert die Datei als **rohe Binärdaten** (keine ELF-Struktur). | | |||
`-s` Rohdaten anzeigen | |||
--- | |||
### Beispiele für ARM64 | |||
#### Einfaches Disassemblieren | |||
```bash | |||
objdump -d ./blink | |||
``` | |||
#### Ohne Register-Aliase (z. B. `wzr` statt `w0`) | |||
```bash | |||
objdump -d -M no-aliases ./blink | |||
``` | |||
#### Mit klassischen Register-Namen (x0–x30) | |||
```bash | |||
objdump -d -M reg-names=std ./blink | |||
``` | |||
#### Nur `.text`-Sektion | |||
```bash | |||
objdump -d --section=.text ./blink | |||
``` | |||
#### Disassemblieren roher Binärdaten | |||
Wenn du z. B. ein 1:1-Memory-Dump oder reinen Maschinencode ohne ELF-Struktur hast: | |||
```bash | |||
objdump -D -b binary -m aarch64 yourfile.bin | |||
``` | |||
--- | |||
### Option `-M` im Detail | |||
`-M` steht für **Disassembler-Modifikatoren** – mehrere können kombiniert werden: | |||
- `no-aliases` | |||
Zeigt dir "echte" Instruktionen, keine Vereinfachungen. | |||
> Beispiel: Statt `mov x0, x1` sieht man `orr x0, x1, xzr`. | |||
- `reg-names=std` | |||
Standardregister (x0–x30, sp, pc). | |||
- `reg-names=raw` | |||
Zeigt numerische Register: `r0`, `r1`, ... | |||
- `reg-names=apcs` | |||
Zeigt Register gemäß dem **ARM Procedure Call Standard** (z. B. `a1`, `v1`, `fp`, `lr`). | |||
--- | |||
## Die `-s` Option: Rohdaten anzeigen | |||
Die Option `-s` (kurz für `--full-contents`) zeigt den **Hexdump des gesamten Inhalts** der Datei, geordnet nach Sektionen. | |||
### Beispiel: | |||
```bash | |||
objdump -s ./blink | |||
``` | |||
### Beispielausgabe: | |||
```text | |||
Contents of section .text: | |||
0000 52800000 d2800021 d2800442 d2800003 R...!...B.... | |||
0010 d2800004 8b030084 d2800025 d2800026 .........%...& | |||
``` | |||
### Bedeutung: | |||
- Linke Spalte: Offset innerhalb der Sektion. | |||
- Rechte Spalten: Hex-Werte der Bytes. | |||
- Ganz rechts (manchmal): ASCII-Darstellung, wenn druckbar. | |||
--- | |||
## Kombination mit `-d` und `-s` | |||
Oft ist es sinnvoll, `-d` und `-s` **gemeinsam** zu nutzen – z. B., um zu sehen, wie ein Maschinenbefehl wirklich kodiert ist: | |||
```bash | |||
objdump -ds ./blink | |||
``` | |||
Oder: gezielt auf eine bestimmte Sektion fokussieren: | |||
```bash | |||
objdump -s --section=.rodata ./blink | |||
``` | |||
So kannst du **Strings, Konstanten oder Sprungtabellen** sichtbar machen, die nicht disassembliert, aber trotzdem mitverarbeitet werden. | |||
--- | |||
## Zusammenfassung – wann `-s` nützlich ist: | |||
| Situation | Warum `-s` sinnvoll ist | | |||
|----------|--------------------------| | |||
| Debugging von Konstanten/Strings | Gibt Einblick in `.rodata`, `.data`, `.bss` etc. | | |||
| Verstehen von Maschineninstruktionen | Hex-Werte → ARM64-Opcode | | |||
| Analyse von Binärdateien ohne Symbole | Du siehst trotzdem, **was im Speicher liegt** | | |||
| Reverse Engineering | Hex-Dumps helfen, Kontrollstrukturen und Datenlayout zu erkennen | | |||
--- | |||
### Bonus: Nur Funktionssymbol disassemblieren | |||
Wenn du Symbole hast (nicht `strip` benutzt): | |||
```bash | |||
objdump -d ./blink --disassemble=_start | |||
``` | |||
--- | |||
### Abschluss: Tipps | |||
- Wenn deine Datei keine Symbole enthält, verwende zusätzlich `nm` oder `readelf`, um Adressen herauszufinden. | |||
- Kombiniere `objdump` mit `grep` zur gezielten Analyse: | |||
```bash | |||
objdump -d ./blink | grep "<_start>" | |||
``` | |||
== Diassemblieren == | == Diassemblieren == | ||
-> objdump -s -d HelloWorld.o > HelloWorld.diassem | -> objdump -s -d HelloWorld.o > HelloWorld.diassem | ||
Version vom 10. April 2025, 13:36 Uhr
Einleitung
Das Disassemblieren ist der Prozess, bei dem aus Maschinencode wieder menschenlesbarer Assembler-Code erzeugt wird. Es ist ein wichtiges Werkzeug für:
- Debugging: Nachvollziehen, was das Programm tatsächlich macht.
- Reverse Engineering: Verstehen fremder Binärdateien.
- Optimierung: Erkennen ineffizienter Codeabschnitte.
- Lernen: Verstehen, wie Hochsprachen wie C übersetzt werden.
Werkzeuge
Für ARM64 unter Linux – z. B. auf dem Raspberry Pi – bieten sich diese Tools an:
objdump
Teil von `binutils`. Zeigt dir den Assembler-Code aus Objektdateien oder Binärprogrammen an. Dies ist auch meine bevorzugte Art, um etwas zu Diassemblieren.
objdump -d ./blink
Optionen:
- `-d` disassembliert ausführbare Abschnitte.
- `-M reg-names=std` (optional): zeigt Standard-Registerbezeichnungen (x0–x30).
- `-M no-aliases` (zeigt die "echten" Instruktionsnamen statt Pseudonyme).
Beispiel:
objdump -d -M reg-names=std ./blink
gdb
Mit `gdb` (GNU Debugger) kannst du direkt im Programmfluss disassemblieren.
gdb ./blink
(gdb) disassemble _start
Praktische Tipps
- Achte auf die Sectionen: `.text` ist der Code, andere wie `.data` oder `.bss` enthalten keine Instruktionen.
- Prüfe, ob deine Datei nicht mit Strip bearbeitet wurde (`strip` entfernt Debugsymbole).
- Wenn du aus einer reinen Binärdatei (ohne ELF-Header) disassemblieren willst, nutze `objdump` mit `--target binary` und `--architecture aarch64`.
Beispiel:
objdump -D -b binary -m aarch64 your.bin
Worauf achten?
- Alignment: ARM64 nutzt 4-Byte ausgerichtete Instruktionen.
- Branch-Adressen: Bei `b`, `bl`, `cbz`, `ret` und Co. kannst du nachvollziehen, wo dein Programm hin springt.
- System Calls: erkenne z. B. `mov x8, #93; svc 0` als `exit(0)`.
- Speicherzugriffe: beachte, welche Register für Adressierung verwendet werden.
`objdump` im Detail: Parameter und ihre Bedeutung
`objdump` ist ein sehr vielseitiges Werkzeug. Besonders beim Disassemblieren von ARM64-Binärdateien ist es hilfreich, die wichtigsten Optionen zu kennen.
Grundstruktur des Befehls
objdump [OPTIONEN] DATEI
Wichtige Optionen beim Disassemblieren
| Option | Beschreibung | |--------|--------------| | `-d` | Disassembliert alle **ausführbaren Segmente** (z. B. `.text`). | | `-D` | Disassembliert **die gesamte Datei**, auch nicht-ausführbare Abschnitte. Nützlich bei rohen Binärdateien oder unüblichen Formaten. | | `-M <option>` | Legt das Disassemblierungsformat fest. Mehrere Optionen sind durch Kommas trennbar (z. B. `-M reg-names=std,no-aliases`). | | `--section=<name>` | Disassembliert **nur eine bestimmte Sektion**, z. B. `.text`. | | `--start-address=0xADDR` | Beginnt das Disassemblieren **ab dieser Adresse**. | | `--stop-address=0xADDR` | Hört bei dieser Adresse auf. | | `--architecture=aarch64` | Setzt die Architektur explizit, z. B. bei rohen Binärdateien. | | `-b binary` | Interpretiert die Datei als **rohe Binärdaten** (keine ELF-Struktur). | `-s` Rohdaten anzeigen
---
- Beispiele für ARM64
- Einfaches Disassemblieren
```bash objdump -d ./blink ```
- Ohne Register-Aliase (z. B. `wzr` statt `w0`)
```bash objdump -d -M no-aliases ./blink ```
- Mit klassischen Register-Namen (x0–x30)
```bash objdump -d -M reg-names=std ./blink ```
- Nur `.text`-Sektion
```bash objdump -d --section=.text ./blink ```
- Disassemblieren roher Binärdaten
Wenn du z. B. ein 1:1-Memory-Dump oder reinen Maschinencode ohne ELF-Struktur hast: ```bash objdump -D -b binary -m aarch64 yourfile.bin ```
---
- Option `-M` im Detail
`-M` steht für **Disassembler-Modifikatoren** – mehrere können kombiniert werden:
- `no-aliases`
Zeigt dir "echte" Instruktionen, keine Vereinfachungen. > Beispiel: Statt `mov x0, x1` sieht man `orr x0, x1, xzr`.
- `reg-names=std`
Standardregister (x0–x30, sp, pc).
- `reg-names=raw`
Zeigt numerische Register: `r0`, `r1`, ...
- `reg-names=apcs`
Zeigt Register gemäß dem **ARM Procedure Call Standard** (z. B. `a1`, `v1`, `fp`, `lr`).
---
- Die `-s` Option: Rohdaten anzeigen
Die Option `-s` (kurz für `--full-contents`) zeigt den **Hexdump des gesamten Inhalts** der Datei, geordnet nach Sektionen.
- Beispiel:
```bash objdump -s ./blink ```
- Beispielausgabe:
```text Contents of section .text:
0000 52800000 d2800021 d2800442 d2800003 R...!...B.... 0010 d2800004 8b030084 d2800025 d2800026 .........%...&
```
- Bedeutung:
- Linke Spalte: Offset innerhalb der Sektion. - Rechte Spalten: Hex-Werte der Bytes. - Ganz rechts (manchmal): ASCII-Darstellung, wenn druckbar.
---
- Kombination mit `-d` und `-s`
Oft ist es sinnvoll, `-d` und `-s` **gemeinsam** zu nutzen – z. B., um zu sehen, wie ein Maschinenbefehl wirklich kodiert ist:
```bash objdump -ds ./blink ```
Oder: gezielt auf eine bestimmte Sektion fokussieren: ```bash objdump -s --section=.rodata ./blink ```
So kannst du **Strings, Konstanten oder Sprungtabellen** sichtbar machen, die nicht disassembliert, aber trotzdem mitverarbeitet werden.
---
- Zusammenfassung – wann `-s` nützlich ist:
| Situation | Warum `-s` sinnvoll ist | |----------|--------------------------| | Debugging von Konstanten/Strings | Gibt Einblick in `.rodata`, `.data`, `.bss` etc. | | Verstehen von Maschineninstruktionen | Hex-Werte → ARM64-Opcode | | Analyse von Binärdateien ohne Symbole | Du siehst trotzdem, **was im Speicher liegt** | | Reverse Engineering | Hex-Dumps helfen, Kontrollstrukturen und Datenlayout zu erkennen |
---
- Bonus: Nur Funktionssymbol disassemblieren
Wenn du Symbole hast (nicht `strip` benutzt): ```bash objdump -d ./blink --disassemble=_start ```
---
- Abschluss: Tipps
- Wenn deine Datei keine Symbole enthält, verwende zusätzlich `nm` oder `readelf`, um Adressen herauszufinden. - Kombiniere `objdump` mit `grep` zur gezielten Analyse:
```bash objdump -d ./blink | grep "<_start>" ```
Diassemblieren
-> objdump -s -d HelloWorld.o > HelloWorld.diassem
Hello.o: file format elf64-littleaarch64
Contents of section .text:
0000 200080d2 e1000058 a20180d2 080880d2 ......X........ 0010 010000d4 000080d2 a80b80d2 010000d4 ................ 0020 00000000 00000000 ........
Contents of section .data:
0000 48656c6c 6f20576f 726c6421 0a Hello World!.
Disassembly of section .text:
0000000000000000 <_start>:
0: d2800020 mov x0, #0x1 // #1 4: 580000e1 ldr x1, 20 <_start+0x20> 8: d28001a2 mov x2, #0xd // #13 c: d2800808 mov x8, #0x40 // #64 10: d4000001 svc #0x0 14: d2800000 mov x0, #0x0 // #0 18: d2800ba8 mov x8, #0x5d // #93 1c: d4000001 svc #0x0
...
negative Zahlen
-> Beispiel: 5 + -3
3 in 1 byte is 0x03 or 0000 0011. Inverting the bits is 1111 1100 Add 1 to get 1111 1101 = 0xFD Now add 5 + 0xFD = 0x102 = 2
movadd.o: file format elf64-littleaarch64
Contents of section .text:
0000 001980d2 812580d2 0200018b a00080d2 .....%.......... 0010 41008092 0200018b 000080d2 a80b80d2 A............... 0020 010000d4 ....
Disassembly of section .text:
0000000000000000 <_start>:
0: d2801900 mov x0, #0xc8 // #200 4: d2802581 mov x1, #0x12c // #300 8: 8b010002 add x2, x0, x1 c: d28000a0 mov x0, #0x5 // #5 10: 92800041 mov x1, #0xfffffffffffffffd // #-3 14: 8b010002 add x2, x0, x1 18: d2800000 mov x0, #0x0 // #0 1c: d2800ba8 mov x8, #0x5d // #93 20: d4000001 svc #0x0