forked from ree-lecture/assignments
First commit
commit
c5315e1640
Binary file not shown.
|
@ -0,0 +1,54 @@
|
||||||
|
# Assignment: Java-Klasse analysieren und patchen
|
||||||
|
<!-- Points: 5 -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
In diesem Assignment werden Sie Java-Klassen analysieren und so verändern, dass ein Flag ausgegeben wird. Hierzu verwenden wir den [Java Decompiler (JD)](http://java-decompiler.github.io/).
|
||||||
|
|
||||||
|
|
||||||
|
## Flags
|
||||||
|
|
||||||
|
Die Executables enthalten ein Geheimnis (Flag), das in der Form `FLAG{...}` ausgegeben wird, wenn Sie das richtige Passwort angeben. Leider kennen Sie das Passwort nicht.
|
||||||
|
|
||||||
|
_Beispiel:_
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./password_check_1
|
||||||
|
Enter password: my_password
|
||||||
|
FLAG{supper_secret}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ihre Aufgabe ist es, diese Geheimnisse aus den Dateien zu extrahieren. Sie können versuchen, das Passwort oder direkt das Flag zu finden. Ein Brute-Force-Angriff auf das Passwort ist aber nicht Teil dieser Übung -- wir betreiben hier Reverse-Engineering und kein Cracking ;-)
|
||||||
|
|
||||||
|
|
||||||
|
## Flags sammeln
|
||||||
|
|
||||||
|
Wenn Sie das Flag erhalten haben, so tragen Sie das Flag bitte auf der [CTF-Webseite](http://tank.informatik.hs-mannheim.de) ein. Bei der ersten Benutzung legt sich jedes Team einen Benutzer an, der wie das Team heißt.
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
|
||||||
|
Die folgende Datei gibt das Flag nicht aus, auch wenn Sie das richtige Passwort eingeben. Es ergibt also keinen Sinn, das Passwort aus der Datei extrahieren zu wollen.
|
||||||
|
|
||||||
|
* [flag_printer.jar](flag_printer.jar)
|
||||||
|
|
||||||
|
Deswegen werden wir die Java-Klassen dekompilieren und untersuchen.
|
||||||
|
|
||||||
|
Da es sich hier um ein Java-Archive (jar) handelt, können Sie es einfach mit `java -jar flag_printer.jar` starten.
|
||||||
|
|
||||||
|
Gehen Sie wie folgt vor:
|
||||||
|
|
||||||
|
* Installieren Sie den [Java Decompiler (JD)](http://java-decompiler.github.io/)
|
||||||
|
* Untersuchen Sie das vorliegende Java-Programm und finden Sie die Stelle an der eine Prüfung der Eingabe erfolgt.
|
||||||
|
* Schreiben Sie eine neue Klasse, die genauso heißt und dieselben Methoden hat, aber bei der Prüfung des Passwortes immer ein korrektes Passwort meldet.
|
||||||
|
* Ersetzen Sie im JAR die Original-Klasse durch ihre eigene.
|
||||||
|
* Starten Sie das Programm.
|
||||||
|
|
||||||
|
## Abgabe
|
||||||
|
|
||||||
|
Überlegen Sie sich eine sinnvolle Verzeichnis-Struktur, um dieses und die folgenden Assignments abzulegen.
|
||||||
|
|
||||||
|
* Schreibern Sie auf, was Sie über die vorhandenen Klassen herausgefunden haben.
|
||||||
|
* Schreiben Sie auf, wie Sie bei der Lösung der Aufgabe vorgegangen sind. Dies umfasst die eingegebenen Befehle und weitere Informationen, sodass ein fachkundiger Dritter Ihr Vorgehen nachvollziehen kann.
|
||||||
|
* Checken Sie die geänderte Klasse und das veränderte JAR ein.
|
||||||
|
|
||||||
|
Die Abgabe erfolgt über das Repository, das Ihrem Team zugeordnet ist.
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Binwalk
|
||||||
|
|
||||||
|
[Binwalk](https://github.com/ReFirmLabs/binwalk) ist ein Reverse-Engineering-Werkzeug für die Kommandozeile.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Sie müssen Binwalk installieren, bevor Sie es benutzen können. Unter Ubuntu können Sie es einfach mit `sudo apt install binwalk` installieren.
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Der GNU Debugger (gdb)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Der GNU Debugger (gdb) ist auf den meisten Systemen bereits installiert. Sollte er bei Ihnen fehlen, können Sie ihn mit dem Kommando `sudo apt install gdb` installieren.
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
`gdb` verwendet standardmäßig die AT&T-Syntax für die Ausgabe von Assembler-Befehlen. Da dies aber die unüblichere Form ist, werden wir ausschließlich die Intel-Syntax verwenden. Sie können `gdb` nach jedem Aufruf mit dem Kommando `set disassembly-flavor intel` auf die Intel-Syntax umstellen. Einfacher ist es jedoch, diese Einstellung dauerhaft abzulegen. Erzeugen Sie hierzu einfach eine Datei `.gdbinit` in Ihrem Home-Verzeichnis und schreiben Sie dort das Kommando für die Syntax hinein.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ echo "set disassembly-flavor intel" > ~/.gdbinit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wichtige Kommandos
|
||||||
|
|
||||||
|
Sie laden ein Programm, indem Sie den Pfad zum Programm nach dem Aufruf von `gdb` angeben, also z.B. `$ gdb ./crackme`.
|
||||||
|
|
||||||
|
Wenn Sie `gdb` gestartet haben, können Sie hinter dem Prompt `(gdb)` Ihre Kommandos eingeben. Einige wichtige Kommandos sind:
|
||||||
|
|
||||||
|
* `run` oder `r`: Startet das Programm
|
||||||
|
* CTRL-C: Unterbricht das Programm
|
||||||
|
* `backtrace` oder `bt`: Zeigt den Stack an
|
||||||
|
* `frame NO`: Springt zum Frame mit der angegebenen Nummer
|
||||||
|
* `disassemble` oder `disas`: Disassembliert die Funktion für den aktuellen Stack-Frame
|
||||||
|
* `break` oder `b`: Setzt einen Breakpoint. Hierbei können Sie angeben
|
||||||
|
- Funktionsnamen: `break strcmp`
|
||||||
|
- Adresse: `break *0x7ffff7f39660`
|
||||||
|
* `continue` oder `c`: Setzt das Programm fort
|
||||||
|
* `x`: Untersucht eine Speicherstelle, d.h. der übergebene Wert wird als Adresse interpretiert
|
||||||
|
- als Hexadezimalwert: `x /x $rdi` oder `x /x 0x555555559ac0`
|
||||||
|
- als Dezimalwert: `x /d $rdi` oder `x /d 0x555555559ac0`
|
||||||
|
- als Fließkommazahl: `x /f $rdi` oder `x /f 0x555555559ac0`
|
||||||
|
- als String: `x /s $rdi` oder `x /s 0x555555559ac0`
|
||||||
|
- als Instruktionen: ` x /i $rip` oder `x /i 0x555555559ac0`
|
||||||
|
- es können mehrere Werte auf einmal ausgegeben werden, z.B. `x /10x $rdi`
|
||||||
|
* `print` oder `p`: Gibt einen Wert aus
|
||||||
|
- eines Registers: `p $rdi`
|
||||||
|
- eines Ausdrucks: `p 2*2`
|
||||||
|
- Sie können auch die Flags `/x`
|
||||||
|
* CTRL-D: Beendet den Debugger
|
||||||
|
|
||||||
|
Sowohl `print` als auch `x` unterstützen sogenannte Formatzeichen, die angeben, wie der Wert zu interpretieren und formatieren ist:
|
||||||
|
|
||||||
|
* `x`: Hexadezimal
|
||||||
|
* `d`: Vorzeichenbehaftete Dezimalzahl
|
||||||
|
* `u`: Vorzeichenlose Dezimalzahl
|
||||||
|
* `o`: Octal
|
||||||
|
* `t`: Binär
|
||||||
|
* `a`: Adresse (hexadezimal + Offset zu nächsten bekannten Symbol)
|
||||||
|
* `c`: ASCII-Zeichen
|
||||||
|
* `f`: Fließkommazahl
|
||||||
|
* `s`: String (nur `x`)
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Radare 2
|
||||||
|
|
||||||
|
[Radare 2 ](https://rada.re) ist ein Reverse-Engineering-Werkzeug für die Kommandozeile. Es gibt mit [iato](https://github.com/radareorg/iaito/) auch eine grafische Oberfläche. Diese setzen wir hier aber nicht ein, sondern verwenden ein anderes Werkzeug namens Ghidra.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Sie müssen Radare 2 installieren, bevor Sie es benutzen können. Unter Ubuntu können Sie eine ältere Version einfach mit `sudo apt install radare2` installieren. Diese Version reicht für diese und folgende Übungen vollständig aus. Möchten Sie eine aktuellere Version, so finden Sie diese auf [GitHub](https://github.com/radareorg/radare2/releases).
|
||||||
|
|
||||||
|
Die Version 4.1.x von radare2 hat Probleme mit der Instruktion `endbr64` (`f3 0f 1e fa`) am Anfang von Funktionen und zeigt diese als "invalid" an. Deswegen können Sie Funktionen nicht einfach mit `pd@ FNAME` disassemblieren, sondern müssen die Funktion über `s` suchen und dann mit `pd` disassemblieren. Um dieses Problem zu umgehen, installieren Sie die aktuelle Version.
|
||||||
|
|
||||||
|
## Wichtige Kommandos
|
||||||
|
|
||||||
|
### rabin2
|
||||||
|
|
||||||
|
`rabin2` ist ein Werkzeug, um Informationen über ein vorliegendes Binary zu erhalten. Sie übergeben `rabin2` den Pfad des Executables und legen über ein Flag fest, welche Informationen Sie sehen wollen. Beispielsweise zeit das Kommando `rabin2 -i /usr/bin/ls` die Imports des `ls`-Kommandos an.
|
||||||
|
|
||||||
|
Die wichtigsten Flags für `rabin2` sind:
|
||||||
|
|
||||||
|
* `-z`: Strings in der `.data`-Section ausgeben
|
||||||
|
* `-zzz`: Strings aus allen Sektionen ausgeben
|
||||||
|
* `-i`: Imports ausgeben
|
||||||
|
* `-E`: Exports ausgeben
|
||||||
|
* `-l`: Verwendete Libraries ausgeben
|
||||||
|
|
||||||
|
### r2
|
||||||
|
|
||||||
|
`r2` ist das eigentliche Reverse-Engieering-Werkzeug mit einem integrierten Disassembler. Das zu analysierende Programm wird `r2` als Parameter übergeben, z.B. `r2 /usr/bin/ls`. Üblicherweise startet man `r2` mit dem zusätzlichen Parameter `-AA`, um das Programm auch direkt zu analysieren, also `r2 -AA /usr/bin/ls`. Will man Änderungen am Binary vornehmen, muss man es im Write-Mode mit `-w` öffnen.
|
||||||
|
|
||||||
|
Nach dem Start zeigt `r2` einen Prompt mit der aktuellen Adresse. Im folgenden sollen die wichtigsten Kommandos aufgelistet werden:
|
||||||
|
|
||||||
|
* `s`: Sucht nach einem Symbol und springt an die Startadresse des Symbols, z.B. `s main`
|
||||||
|
* `pd`: Gib ab der aktuellen Position ein Assembler-Listing aus (*p*rint *d*issassembly). Die Anzahl der Zeilen (Opcodes) kann als Parameter angegeben werden, also `pd 10` für 10 Zeilen.
|
||||||
|
* `pdr`: Gibt ab der aktuellen Position ein Assembler-Listing aus, verwendet aber einen rekursiven Disassembler.
|
||||||
|
* `v`: Startet den visuellen Modus, den man mit `q` wieder verlassen kann. Im visuellen Modus kann man durch `ENTER` die Anzeige verbreitern
|
||||||
|
* `CTRL-D` verlässt `r2`
|
|
@ -0,0 +1,180 @@
|
||||||
|
# Typische Sicherheitslücken
|
||||||
|
|
||||||
|
Im Folgenden finden Sie eine kleine Auflistung von Sicherheitslücken, die sich gut in Crackmes verwenden können. Die Liste ist natürlich nicht vollständig - lassen Sie Ihrer Kreativität freien Lauf.
|
||||||
|
Gerne können Sie auch noch weitere Lücken vorschlagen.
|
||||||
|
|
||||||
|
## Buffer-Overflow
|
||||||
|
|
||||||
|
### Lokale Variablen überschreiben
|
||||||
|
|
||||||
|
Buffer auf dem Stack liegen dort zusammen mit allen anderen lokalen Variablen und können diese bei fehlender oder falscher Prüfung der Grenzen überschreiben (Buffer-Overflow).
|
||||||
|
|
||||||
|
```c
|
||||||
|
int i = 0;
|
||||||
|
char x[3];
|
||||||
|
|
||||||
|
printf("%d\n", i); // -> 0
|
||||||
|
strcpy(x, "Hell");
|
||||||
|
printf("%d\n", i); // -> 108
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rücksprungadresse überschreiben
|
||||||
|
|
||||||
|
Buffer-Overflows können auch dazu benutzt werden, die Rücksprungadresse zur Aufrufenden Funktion zu überschreiben. Stack-Guards sollen dies verhindern, können aber manchmal übergangen oder explizit durch `-fno-stack-protector` beim Compilieren ausgeschaltet werden.
|
||||||
|
|
||||||
|
|
||||||
|
## Stackbasierte Schwachstellen
|
||||||
|
|
||||||
|
### Base-Pointer
|
||||||
|
|
||||||
|
Auf dem Stack liegt nicht nur die Rücksprungadresse, sondern auch der gespeicherte Base-Pointer (`EBP`) der vorhergehenden Funktion. Wenn man diesen durch einen Buffer-Overflow modifizieren kann, besteht die Möglichkeit lokale Variablen der aufrufenden Funktion zu verändern.
|
||||||
|
|
||||||
|
### Reste auf dem Stack
|
||||||
|
|
||||||
|
Der Stack wird bei einem Funktionsaufruf nicht gesäubert. Wenn die Funktion ihre Variablen nicht initialisiert, kann man möglicherweise alte Daten auf dem Stack entdecken.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int a(void) {
|
||||||
|
short a = 0xbeef;
|
||||||
|
short b = 0xdead;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int b(void) {
|
||||||
|
int z;
|
||||||
|
printf("0x%x\n", z);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
a();
|
||||||
|
b(); // -> 0xbeefdead
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## String-Funktionen
|
||||||
|
|
||||||
|
### Größe von String-Puffern
|
||||||
|
|
||||||
|
Wegen des Nullbytes muss der Buffer für einen String immer mindestens ein Zeichen länger sein, als der String selbst. Wenn man dies nicht berücksichtigt, kommt es Buffer-Overflows.
|
||||||
|
|
||||||
|
```c
|
||||||
|
char *text = "Hallo";
|
||||||
|
char *copy = alloc(strlen(text)); /* zu klein */
|
||||||
|
strcpy(copy, text); /* Buffer overflow */
|
||||||
|
```
|
||||||
|
|
||||||
|
### Länge von Strings
|
||||||
|
|
||||||
|
Die normalen String-Funktionen (`strcpy`. `strlen` ...) lesen bis zum ersten 0-Byte (`'\0'`) im `char*`-Array. Dies kann man eventuell ausnutzen, um mehr Daten zu verändern als vom Entwickler gewollt, weil man z.B. einen Puffer bis zum letzten Byte füllt.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int k = 0x47554755;
|
||||||
|
char src[] = { 'H', 'a', 'l', 'l', 'o' };
|
||||||
|
char dest[30];
|
||||||
|
|
||||||
|
strcpy(dest, src);
|
||||||
|
|
||||||
|
printf("%s", dest); // -> HalloUGUGJ
|
||||||
|
```
|
||||||
|
|
||||||
|
### Puffer überschreiben
|
||||||
|
|
||||||
|
Funktionen wie `gets`, `strcpy` und `sprintf` überprüfen die Größe des Zielpuffers nicht und lassen sich deswegen hervorragend für Buffer-Overflows nutzen.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int i = 0;
|
||||||
|
char b[5];
|
||||||
|
gets(b);
|
||||||
|
printf("%d\n", i);
|
||||||
|
```
|
||||||
|
|
||||||
|
Deswegen sollten die Funktionen nicht mehr genutzt werden. Findet man sie in den Imports eines Programms lohnt sich die Suche nach der Stelle, an der sie verwendet werden.
|
||||||
|
|
||||||
|
## Integer-Overflow
|
||||||
|
|
||||||
|
Alle Integer-Datentypen ohne `unsigned` (`char`, `short`, `int`, `long`, `long long`) sind vorzeichenbehaftet und laufen von Plus nach Minus über.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int i = 2147483647;
|
||||||
|
i++;
|
||||||
|
printf("%d\n", i); // -> -2147483648
|
||||||
|
```
|
||||||
|
|
||||||
|
Alle Integer-Datentypen mit `unsigned` laufen zur `0` über und zum Max-Value unter.
|
||||||
|
|
||||||
|
```c
|
||||||
|
unsigned int i = 0;
|
||||||
|
i--;
|
||||||
|
printf("%u\n", i); // -> 4294967295
|
||||||
|
i++;
|
||||||
|
printf("%u\n", i); // -> 0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formatstring-Schwachstelle
|
||||||
|
|
||||||
|
Formatstringschwachstellen (`printf`) erlauben es, Variablen auf dem Stack zu lesen und zu schreiben.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int main() {
|
||||||
|
long k = 0xcafebabe;
|
||||||
|
long *p = &k;
|
||||||
|
|
||||||
|
printf("0x%9$x"); // -> 0xcafebabe
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Funktionspointer
|
||||||
|
|
||||||
|
Funktionspointer auf dem Stack können, wenn sie durch eine der anderen Schwachstellen modifiziert werden können, dazu genutzt werden beliebige Funktionen aufzurufen.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void f() {
|
||||||
|
puts("f called");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
void (*fp)(void);
|
||||||
|
|
||||||
|
fp = f;
|
||||||
|
fp(); // -> f called
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## "malloc can never fail"
|
||||||
|
|
||||||
|
`malloc()` gibt `0` im Fehlerfall zurück, dies sollte eigentlich vom Programm geprüft werden. Wird dies nicht geprüft, arbeitet das Programm mit einem Pointer weiter, der die Adresse `0x00` hat.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void *p = malloc(1717272222772);
|
||||||
|
printf("%p\n", p); // (nil)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use-After-Free
|
||||||
|
|
||||||
|
Mit `malloc` allozierter Speicher wird mit `free` wieder freigegeben. Wenn man den Speicher aber nach dem `free` noch weiter benutzt, können beliebige Daten von anderen Teilen des Programms dort landen, weil `malloc` den Speicher natürlich "recycled". Hierdurch kann man Daten exfiltrieren oder Funktionen sogar eigene Daten unterschieben.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void printer() {
|
||||||
|
static char *text = 0;
|
||||||
|
if (!text) {
|
||||||
|
text = (char*) malloc(sizeof(char) * 9);
|
||||||
|
strcpy(text, "mutti123");
|
||||||
|
}
|
||||||
|
printf("%s\n", text); /* use after free */
|
||||||
|
free(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
printer(); /* -> mutti123 */
|
||||||
|
char *pwnd = (char*) malloc(sizeof(char) * 9);
|
||||||
|
strcpy(pwnd, "pwned!");
|
||||||
|
printer(); /* -> pwned! */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## GOT.PLT
|
||||||
|
|
||||||
|
Wenn das Programm `-z,norelro` compiliert ist, kann man die Funktionen im global offset-table (GOT.PLT) ersetzen, so man durch eine andere Schwachstelle Zugriff darauf bekommt. Hierdurch kann man dann Standard-Funktionen der Library durch eigene ersetzen.
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Softwareausstattung
|
||||||
|
|
||||||
|
Wenn Sie einen eigenen Rechner für die Veranstaltung mitbringen wollen -- was durchaus zu empfehlen ist, installieren Sie bitte (direkt auf dem Gerät oder in einer VM) ein 64-Bit Ubuntu Linux (oder ein anderes Linux, das auf der glibc basiert) in einer aktuellen Version. Eine Anleitung und Unterstützung finden Sie [hier](https://github.com/informatik-mannheim/linux-hsma/blob/master/doc/readme.md). Bitte versuchen Sie nicht, die Übungen ohne Linux zu lösen, es wartet eine Welt der Frustration und des Schmerzes 😭 auf Sie, durch die schon viele andere gegangen sind, die diesen einen wichtigen Tipp ignoriert haben.
|
||||||
|
|
||||||
|
Für die Durchführung der Assignments benötigen Sie die entsprechenden Tools, die Sie am besten vorher installieren. Auf der VM im Poolraum sind diese Tools bereits vorhanden. Bei Ihrem eigenen Rechner müssen Sie sie selbst installieren:
|
||||||
|
|
||||||
|
* Java JDK 17 (wird von Ghidra benötigt)<br>`sudo apt install openjdk-17-jdk`
|
||||||
|
* [Ghidra](https://ghidra-sre.org/) in der aktuellsten Version<br>Herunterladen und das ZIP-File auspacken. Ghidra wird über das Skript `ghidraRun` gestartet
|
||||||
|
* [Radare 2](https://github.com/radareorg/radare2/releases/download/5.8.8/radare2_5.8.8_amd64.deb) in der aktuellen Version herunterladen und das Paket installieren<br>`sudo apt install ./radare2_5.8.8_amd64.deb`
|
||||||
|
* Git<br>`sudo apt install git meld git-cola`
|
||||||
|
* strace und ltrace<br>`sudo apt install strace ltrace`
|
||||||
|
* GNU C-Compiler, Assembler und Debugger<br>`sudo apt install g++ make remake cmake gdb nasm`
|
||||||
|
* Ruby-Interpreter für Crackmes<br>`sudo apt install ruby3.0`
|
||||||
|
* Python-PIP<br>`sudo apt install python3-pip`
|
||||||
|
* Hex-Editor<br>`sudo apt install hexedit hexyl`
|
||||||
|
* Net-Tools<br>`sudo apt install net-tools`
|
||||||
|
* [Java-Decompiler (jd)](https://github.com/java-decompiler/jd-gui/releases/download/v1.6.6/jd-gui-1.6.6.deb) in der aktuellen Version herunterladen und das Paket installieren<br>`sudo apt install ./jd-gui-1.6.6.deb`
|
||||||
|
* Visual Studio Code als Editor<br>`sudo snap install code --classic`
|
||||||
|
* Ruby `sudo snap install ruby`
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Reverse Engineering (Wintersemester 2024/2025)
|
||||||
|
|
||||||
|
## Willkommen zum Kurs Reverse Engineering (REE)
|
||||||
|
|
||||||
|
In diesem Kurs erfahren Sie, wie man einem unbekannten Binärartefakt (Programm, Virus, Payload) seine Geheimnisse entlocken kann. Hierzu werden Sie grundlegende Techniken der Analyse solcher Programme erlernen und diese Techniken verwenden, um deren Funktionsweise zu verstehen und Schwachstellen zu finden. Am Ende des Kurses werden Sie in der Lage sein, einfache CTFs (Capture The Flag) aus dem Bereich des Reverse Engineerings zu lösen und eigene kleinere Aufgaben für Ihre Mitstudierenden zu entwickeln, die diese dann lösen müssen.
|
||||||
|
|
||||||
|
|
||||||
|
## Assignments
|
||||||
|
|
||||||
|
Hier finden Sie die wöchentlichen Assignments für die Vorlesung Reverse Engineering (RE). Die Assignments sind unten, zusammen mit dem Fälligkeitsdatum, aufgelistet.
|
||||||
|
|
||||||
|
Einige dieser Assignments sind _benotet_, d.h. die Qualität Ihrer Ausarbeitung geht in die Gesamtnote für diesen Kurs ein. Sie erkennen die _benoteten Assignments an dem Abgabedatum_, bis zu dem Ihre Lösung hochgeladen sein muss.
|
||||||
|
|
||||||
|
Hinweise zur nötigen Softwareausstattung finden Sie [hier](help/software.md).
|
||||||
|
|
||||||
|
| # | Ausgabe | Thema | Fällig am 📆 |
|
||||||
|
|----|------------|------------------------------------------------------------------|----------------|
|
||||||
|
| 1. | 02.10.2024 | [Java-Klasse analysieren und patchen](Assignment_001/readme.md) | |
|
||||||
|
|
||||||
|
## 🎓 Benotung
|
||||||
|
|
||||||
|
Die Benotung des Kurses erfolgt im Format Continuous Assessment (CA). Hierzu werden Ihre Leistungen während des gesamten Semesters bewertet und die Endnote ergibt sich aus den Einzelleistungen.
|
||||||
|
|
||||||
|
Bewertet werden:
|
||||||
|
|
||||||
|
* die erstellten Writeups und Lösungen zu den Assignments
|
||||||
|
* die Erstellung neuer Aufgaben/CTFs durch die Teams (Peer-Aufgaben)
|
||||||
|
* die Lösung der Peer-Aufgaben/CTFs durch die Teams
|
||||||
|
|
||||||
|
Alle mit einem Abgabedatum gekennzeichneten Assignments sind Teil der Bewertung und müssen von Ihnen bearbeitet und fristgerecht abgegeben werden.
|
||||||
|
|
||||||
|
|
||||||
|
## 💻 Hilfreiche Links und Tipps
|
||||||
|
|
||||||
|
* [Typische Sicherheitslücken](help/sicherheitsluecken.md)
|
||||||
|
* [Compiler Explorer](https://godbolt.org/)
|
||||||
|
* [x86 and amd64 instruction reference](https://www.felixcloutier.com/x86/index.html)
|
||||||
|
* [System V AMD64 ABI Calling Convention](https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI)
|
||||||
|
1. `RDI` ⬅ 1st param (left to right)
|
||||||
|
2. `RSI` ⬅ 2nd param (left to right)
|
||||||
|
3. `RDX` ⬅ 3rd param (left to right)
|
||||||
|
4. `RCX` ⬅ 4th param (left to right)
|
||||||
|
5. `R8` ⬅ 5th param (left to right)
|
||||||
|
6. `R9` ⬅ 6th param (left to right)
|
||||||
|
* Stack ⬅ excess params (right to left)
|
||||||
|
* `RAX` ⮕ result
|
||||||
|
* [Linux kernel syscall tables](https://syscalls.mebeim.net/?table=x86/64/x64/latest)
|
||||||
|
* [Linux System Call Convention](https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux)
|
||||||
|
* `RAX` ⬅ System call number
|
||||||
|
1. `RDI` ⬅ 1st param (left to right)
|
||||||
|
2. `RSI` ⬅ 2nd param (left to right)
|
||||||
|
3. `RDX` ⬅ 3rd param (left to right)
|
||||||
|
4. `R10` ⬅ 4th param (left to right)
|
||||||
|
5. `R8` ⬅ 5th param (left to right)
|
||||||
|
6. `R9` ⬅ 6th param (left to right)
|
||||||
|
* `RAX` ⮕ result
|
||||||
|
* [printf Formatierungszeichen](http://www2.hs-esslingen.de/~zomotor/home.fhtw-berlin.de/junghans/cref/FUNCTIONS/format.html)
|
||||||
|
* [gdb Cheat Sheet](https://users.ece.utexas.edu/~adnan/gdb-refcard.pdf)
|
||||||
|
|
||||||
|
|
||||||
|
## 📚 Literatur zur Vorlesung
|
||||||
|
|
||||||
|
* Sikorski, M. and Honig, A. (2012). Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software. No Starch Press.
|
||||||
|
* Andriesse, D. (2018). Practical Binary Analysis: Build Your Own Linux Tools for Binary Instrumentation, Analysis, and Disassembly. No Starch Press.
|
||||||
|
* Eagle C. and Nance K. (2020). The Ghidra Book: The Definitive Guide. No Starch Press.
|
||||||
|
* Yurichev, D. (2019). Reverse Engineering for Beginners. [Online](https://beginners.re/main.html)
|
||||||
|
* [x86-64 Assembly Language Programming with Ubuntu](http://www.egr.unlv.edu/~ed/assembly64.pdf)
|
||||||
|
* [Intel Dokumentation zu x86-64](https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html)
|
||||||
|
* [System V ABI](https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf)
|
Loading…
Reference in New Issue