In diesem Artikel analysieren wir die Lösung einer mehrstufigen Aufgabe mithilfe der
pwntools- Bibliothek.
OrganisationsinformationenSpeziell für diejenigen, die etwas Neues lernen und sich in einem der Bereiche Informations- und Computersicherheit entwickeln möchten, werde ich über die folgenden Kategorien schreiben und sprechen:
- PWN;
- Kryptographie (Krypto);
- Netzwerktechnologien (Netzwerk);
- Reverse (Reverse Engineering);
- Steganographie (Stegano);
- Suche und Ausnutzung von WEB-Schwachstellen.
Darüber hinaus werde ich meine Erfahrungen in den Bereichen Computerforensik, Analyse von Malware und Firmware, Angriffe auf drahtlose Netzwerke und lokale Netzwerke, Durchführung von Pentests und Schreiben von Exploits teilen.
Damit Sie sich über neue Artikel, Software und andere Informationen informieren können, habe ich
in Telegram einen
Kanal und eine
Gruppe eingerichtet, um alle Probleme im Bereich ICD
zu diskutieren . Außerdem werde ich Ihre persönlichen Anfragen, Fragen, Vorschläge und Empfehlungen
persönlich prüfen
und alle beantworten .
Alle Informationen werden nur zu Bildungszwecken bereitgestellt. Der Autor dieses Dokuments übernimmt keine Verantwortung für Schäden, die jemandem durch die Verwendung von Kenntnissen und Methoden entstehen, die durch das Studium dieses Dokuments erworben wurden.
Joblösung eingeben
Wir klicken auf das Symbol mit der Signatureingabe und es wird uns mitgeteilt, dass wir uns über SSH mit dem Passwort Gast verbinden müssen.

Wenn verbunden, sehen wir das entsprechende Banner.

Lassen Sie uns herausfinden, welche Dateien sich auf dem Server befinden und welche Rechte wir haben.
ls -l

Auf diese Weise können wir den Quellcode des Programms lesen, da für jeden ein Leserecht besteht, und das Eingabeprogramm mit den Rechten des Eigentümers ausführen (das Sticky-Bit ist gesetzt). Lassen Sie uns das Ergebnis des Codes sehen.
Quellcode input.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> int main(int argc, char* argv[], char* envp[]){ printf("Welcome to pwnable.kr\n"); printf("Let's see if you know how to give input to program\n"); printf("Just give me correct inputs then you will get the flag :)\n"); // argv if(argc != 100) return 0; if(strcmp(argv['A'],"\x00")) return 0; if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0; printf("Stage 1 clear!\n"); // stdio char buf[4]; read(0, buf, 4); if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0; read(2, buf, 4); if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0; printf("Stage 2 clear!\n"); // env if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0; printf("Stage 3 clear!\n"); // file FILE* fp = fopen("\x0a", "r"); if(!fp) return 0; if( fread(buf, 4, 1, fp)!=1 ) return 0; if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0; fclose(fp); printf("Stage 4 clear!\n"); // network int sd, cd; struct sockaddr_in saddr, caddr; sd = socket(AF_INET, SOCK_STREAM, 0); if(sd == -1){ printf("socket error, tell admin\n"); return 0; } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons( atoi(argv['C']) ); if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){ printf("bind error, use another port\n"); return 1; } listen(sd, 1); int c = sizeof(struct sockaddr_in); cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c); if(cd < 0){ printf("accept error, tell admin\n"); return 0; } if( recv(cd, buf, 4, 0) != 4 ) return 0; if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0; printf("Stage 5 clear!\n"); // here's your flag system("/bin/cat flag"); return 0; }
Aus dem Code folgt, dass wir fünf Ebenen durchlaufen müssen. Wir werden sie der Reihe nach nehmen.

Auf der ersten Ebene wird überprüft, ob die Anzahl der Programmargumente 100 beträgt. In diesem Fall sollte das 65. Element die Zeichenfolge "\ x00" und das 66. Element "\ x20 \ x0a \ x0d" sein. Erstellen Sie Ihr eigenes Verzeichnis im Verzeichnis / tmp / und erstellen Sie dort ein Python-Skript.

Um die erste Ebene zu lösen, erstellen wir ein Array mit hundert Zeilen 'A'. Und weisen Sie den gewünschten Werten die erforderlichen Argumente zu. Wir können den Prozess mit diesen Argumenten wie folgt starten:
from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' ex = process(argv=a) ex.interactive()

Wir haben das erste Level bestanden. Schauen Sie sich die zweite an.

Auf dieser Ebene werden zwei Zeilen gelesen, eine der Standardeingaben stdin und die andere von stderr. Wir müssen zwei Dateien erstellen, die diese Zeilen enthalten.

Öffnen Sie Streams für diese Dateien und geben Sie den Deskriptor für den Stream einer Datei als Deskriptor stdin und eine andere Datei als Deskriptor stderr an.
from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') ex = process(argv=a, stdin=fin, stderr=ferr) fin.close() ferr.close() ex.interactive()

Wir fahren mit der Entscheidung der dritten Ebene fort.

Die Funktion getenv () gibt den Wert einer Umgebungsvariablen zurück, der dem Referenzwert entsprechen sollte. Daher müssen Sie eine Umgebungsvariable mit einem bestimmten Wert erstellen.
from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'} ex = process(argv=a, stdin=fin, stderr=ferr, env=e) fin.close() ferr.close() ex.interactive()

Wir haben die Umgebungsvariable verwaltet. Beginnen wir jetzt mit der vierten Ebene.

Entsprechend dem Code können wir sagen, dass das Programm eine Datei mit dem Namen "\ x0a" öffnet und 4 Zeichen daraus liest, wonach es sie mit den Bytes "\ x00" vergleicht. Da sowohl die Zeichen selbst als auch der Dateiname aus nicht druckbaren Zeichen bestehen, verwenden wir Python.


Das letzte Level bleibt. Fangen wir an.

Das Programm öffnet den Socket an dem im 66. Argument angegebenen Port. Dann empfängt es 4 Bytes über das Netzwerk und vergleicht es mit der Referenzzeichenfolge. Wir müssen dem Programm ein weiteres Argument hinzufügen - die Portnummer, eine Verbindung herstellen und die erforderlichen 4 Bytes senden.
from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' a[ord('C')] = '1234' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'} ex = process(argv=a, stdin=fin, stderr=ferr, env=e) fin.close() ferr.close() ex.interactive()


Das ist alles, hol deine Punkte.

Wir sehen uns in den folgenden Artikeln!
Wir befinden uns in einem Telegrammkanal: einem
Kanal im Telegramm .