Aujourd'hui on s'attaque au challenge "input" de pwnable.kr. Disponible ici.
Le code est composé de 6 parties. A chaque étape validée un message nous en informe.
NB: Je me suis permis de rajouter des printf()
afin de rendre le code plus clair.






Comme le challenge est découpé en étapes, on va le résoudre une étape après l'autre.
Etape 1: ArgV

Dans cette étape il faut:
- Fournir 100 arguments
- Que l'argument 'A' soit de valeur nulle
- Que l'argument 'B' ait la valeur
\x20\x0a\x0d
Avant tout il faut comprendre ce que veut dire la formulation argv['A']
? C'est assez simple en fait. Ecrit comme ça le A est transformé en sa valeur ASCII pour être utilisé comme indice du tableau argv. On peut donc traduire cette ligne par argv[65]
. Même principe pour le argv['B']
qui devientargv[66]
.
Pour passer cette première étape, je pourrai me contenter de faire un one-liner en python. Mais vu le nombre d'étapes il va très vite devenir illisible. Je vais plutôt faire un script python2 que je vais compléter au fur et à mesure.
Voici de quoi passer le premier stage:
#!/usr/bin/env python
#-*- coding utf-8 -*-
from pprint import pprint
import os
import sys
import subprocess
myArgs = ["0"]*99
myArgs[ord('A')-1] = "" #"\x00" # In python you can't passe null value but empty value do the job
myArgs[ord('B')-1] = "\x20\x0a\x0d"
subprocess.Popen(['./input'] + myArgs)

Etape 2: StdIO

Pour cette seconde partie, il faut rediriger pipes d'entrée standard et d'erreur standard. Pour ça on va utiliser la fonction pipe()
fournir par le module os
.

Pour écrire les données qui nous intéressent ont va utiliser la fonction write()
du module os
.



Etape 3: Env

Pour cette partie, il faut créer une variable d'environnement qui porte le doux nom de \xde\xad\xbe\xef
et contient la valeur \xca\xfe\xba\be
.
Concentrons nous sur la fonction qui nous intéresse ici: getEnv

Si l'on se réfère à la documentation de python.


Voila qui nous arrange bien ! On créé donc le fameux tableau associatif.



Etape 4: File

Cette fois-ci il faut créer un fichier nommé 0x0A
et le remplir avec 4 nulls bytes.



Etape 5: Socket

Pour cette étape, il faut crée un socket qui va se connecter sur le port contenu dans argv['C']
et qui envoyer la valeur \xde\xad\xbe\xef
quand on s'y connecte. Là encore rien de très compliqué.


Etape 6: Le flag
Maintenant que notre programme tourne en local, il ne reste plus qu'a l'uploader sur la machine de pwnable.kr
.
Si je lance le programme, il ne peut pas trouver le fichier flag
car il n'est pas dans le répertoire que j'ai créé (/tmp/AgsWasHere
), et je ne peux pas l'y mettre car je n'ai pas les droits.

ln -sf
.
NB: Il ne faut pas oublier d'adapter le chemin du fichier input
pour le remplacer par un chemin absolu et valable sur la machine pwnable.kr

NB,NB: J'aurais bien aimé utilisé pwntools pour ce challenge mais le problème est qu'il ne fonctionne qu'en 64 bits...
Voici le code complet
#!/usr/bin/env python
#-*- coding utf-8 -*-
from pprint import pprint
import os
import subprocess
import socket
import time
import random
port = random.randrange(10000, 20000)
# Step 1
myArgs = ["0"]*99
myArgs[ord('A')-1] = "" #"\x00" # In python you can't passe null value but empty value do the job
myArgs[ord('B')-1] = "\x20\x0a\x0d"
myArgs[ord('C')-1] = str(port)
# Step 2
stdinr, stdinw = os.pipe()
stderrr, stderrw = os.pipe()
os.write(stdinw, "\x00\x0a\x00\xff")
os.write(stderrw, "\x00\x0a\x02\xff")
# Step 3
with open("\x0a", "a") as f: f.write("\x00\x00\x00\x00")
# Step 4
env_var = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"}
subprocess.Popen(['./input'] + myArgs, stdin=stdinr, stderr=stderrr, env=env_var)
# Step 5
time.sleep(1) # Needed else not possible to connect socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", port))
s.send("\xde\xad\xbe\xef")
s.close()
Social et Media
Comme toujours je suis disponible sur Twitter et cie, si vous avez des questions, des remarques, des suggestions etc. N’hésitez pas !
Twitter: @GhostAgs
Discord: hackraw