Dans cet article, nous analyserons la solution d'une tâche à plusieurs niveaux à l'aide de la bibliothèque
pwntools .
Information organisationnelleSurtout pour ceux qui veulent apprendre quelque chose de nouveau et se développer dans l'un des domaines de l'information et de la sécurité informatique, j'écrirai et parlerai des catégories suivantes:
- PWN;
- cryptographie (Crypto);
- technologies de réseau (réseau);
- reverse (Reverse Engineering);
- stéganographie (Stegano);
- recherche et exploitation des vulnérabilités WEB.
En plus de cela, je partagerai mon expérience en criminalistique informatique, analyse de logiciels malveillants et micrologiciels, attaques sur les réseaux sans fil et réseaux locaux, réalisation de pentests et écriture d'exploits.
Afin que vous puissiez vous renseigner sur les nouveaux articles, logiciels et autres informations, j'ai créé une
chaîne dans Telegram et un
groupe pour discuter de tout problème dans le domaine de l'ICD. Aussi, je considérerai personnellement vos demandes, questions, suggestions et recommandations
personnelles et répondrai à tout le monde .
Toutes les informations sont fournies à des fins éducatives uniquement. L'auteur de ce document n'assume aucune responsabilité pour tout dommage causé à quelqu'un du fait de l'utilisation des connaissances et des méthodes obtenues à la suite de l'étude de ce document.
Solution de travail d'entrée
Nous cliquons sur l'icône avec l'entrée de signature, et on nous dit que nous devons nous connecter via SSH avec le mot de passe guest.

Une fois connecté, nous voyons la bannière correspondante.

Voyons quels fichiers se trouvent sur le serveur, ainsi que les droits dont nous disposons.
ls -l

Ainsi, nous pouvons lire le code source du programme, car il y a un droit de lecture pour tout le monde, et exécuter le programme d'entrée (ensemble de bits collants) avec les droits du propriétaire. Voyons le résultat du code.
Code source 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; }
Du code, il s'ensuit que nous devons passer par cinq niveaux. Nous les prendrons à tour de rôle.

Au premier niveau, il est vérifié que le nombre d'arguments du programme est de 100. Dans ce cas, le 65ème élément doit être la chaîne "\ x00" et le 66ème élément doit être "\ x20 \ x0a \ x0d". Créez votre propre répertoire dans le répertoire / tmp / et créez-y un script Python.

Pour résoudre le premier niveau, nous allons créer un tableau de cent lignes de «A». Et affectez les arguments nécessaires aux valeurs souhaitées. Nous pouvons démarrer le processus avec ces arguments comme suit:
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()

Nous avons passé le premier niveau. Jetez un oeil à la seconde.

A ce niveau, deux lignes sont lues, l'une de l'entrée standard stdin et l'autre de stderr. Nous devons créer deux fichiers qui contiendront ces lignes.

Ouvrez des flux vers ces fichiers et spécifiez le descripteur pour le flux d'un fichier comme descripteur stdin et d'un autre fichier comme descripteur stderr.
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()

Nous procédons à la décision du troisième niveau.

La fonction getenv () renvoie la valeur d'une variable d'environnement, qui doit être égale à la valeur de référence. Ainsi, vous devez créer une variable d'environnement avec une valeur spécifique.
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()

Nous avons géré la variable d'environnement, maintenant commençons par le quatrième niveau.

Selon le code, nous pouvons dire que le programme ouvre un fichier avec le nom "\ x0a" et en lit 4 caractères, après quoi il les compare avec les octets "\ x00". Étant donné que les caractères eux-mêmes et le nom de fichier sont constitués de caractères non imprimables, nous utilisons python.


Le dernier niveau reste. Commençons.

Le programme ouvre le socket sur le port spécifié dans le 66ème argument. Il reçoit ensuite 4 octets sur le réseau et le compare à la chaîne de référence. Nous devons ajouter un autre argument au programme - le numéro de port, établir une connexion et envoyer les 4 octets nécessaires.
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()


C'est tout, obtenez vos points.

Rendez-vous dans les articles suivants!
Nous sommes dans un canal de télégramme: un
canal dans Telegram .