Tri Sélectif

TriSelectif

Dans ce challenge, nous avons 2 scripts Python.

Le premier tri-seectif.py qui tourne sur un serveur distant.

Le deuxieme, client.py qui est un script permettant de se connecter au serveur et fait tourner le script tri-selectif.py pour y envoyer des instructions.

Le but de ce challenge est de trier un tableau qui a été généré aléatoirement sur le serveur sans connaître ses valeurs. Tout à fait à l'aveugle.

Contenu des scripts

tri-selectif.py

import os

def usage():
	print('Actions possibles:')
	print('  - "comparer X Y": compare les valeurs du tableau aux cases X et Y, et retourne 1 si la valeur en X est inférieure ou égale à celle en Y, 0 sinon.')
	print('  - "echanger X Y": échange les valeurs du tableau aux cases X et Y, et affiche le taleau modifié.')
	print('  - "longueur:      retourne la longueur du tableau.')
	print('  - "verifier:      retourne le flag si le tableau est trié.')

def printArray(A):
	print(" ".join("*" for a in A))

def verifier(A):
	return all([ A[i] <= A[i + 1] for i in range(len(A) - 1) ])

if __name__ == "__main__":

	A = list(os.urandom(32))
	print("Votre but est de trier un tableau dont vous ne voyez pas les valeurs (chacune est remplacée par *) :")
	printArray(A)
	usage()
	B = A[:]

	try:
		while True:
			x = input(">>> ")

			if x.startswith("comparer"):
				x, y = list(map(int, x.split(" ")[1:]))
				print(int(A[x] <= A[y]))

			elif x.startswith("echanger"):
				x, y = list(map(int, x.split(" ")[1:]))
				A[x], A[y] = A[y], A[x]

			elif x.startswith("longueur"):
				print(len(A))

			elif x.startswith("verifier"):
				c = verifier(A)
				if c:
					flag = open("flag.txt").read().strip()
					print(f"Le flag est : {flag}")
				else:
					print("Erreur : le tableau n'est pas trié")
					print(f"Le tableau de départ était : {B}")
					print(f"Le tableau final est :       {A}")
				print("Bye bye!")
				break

			else:
				usage()
	except:
		print("Erreur : vérifier les commandes envoyées.")

Sans rentrer dans les détails, ce script génère un tabeau aléatoire de 32 valeurs.

Il attend les instructions à faire sur le tableau. comparer, echanger, longueur, verifier.

Quoi qu'il arrive, si la commande verifier est faite, que le résultat soit bon ou non, on se fait jeter du serveur et donc si on s'y reconnecte, un nouveau tableau est généré.

client.py

#!/usr/bin/env python3

# python3 -m pip install pwntools
from pwn import *

# Paramètres de connexion
HOST, PORT = "challenges.france-cybersecurity-challenge.fr", 2051

def comparer(x, y):
	io.sendlineafter(b">>> ", f"comparer {x} {y}".encode())
	return int(io.recvline().strip().decode())

def echanger(x, y):
	io.sendlineafter(b">>> ", f"echanger {x} {y}".encode())

def longueur():
	io.sendlineafter(b">>> ", b"longueur")
	return int(io.recvline().strip().decode())

def verifier():
	io.sendlineafter(b">>> ", b"verifier")
	r = io.recvline().strip().decode()
	if "flag" in r:
		print(r)
	else:
		print(io.recvline().strip().decode())
		print(io.recvline().strip().decode())

def trier(N):
	#############################
	#   ... Complétez ici ...   #
	# Ajoutez votre code Python #
	#############################
	if comparer(0, 1):
		echanger(0, 1)
	pass

# Ouvre la connexion au serveur
io = remote(HOST, PORT)

# Récupère la longueur du tableau
N = longueur()

# Appel de la fonction de tri que vous devez écrire
trier(N)

# Verification
verifier()

# Fermeture de la connexion
io.close()

On voit dans ce script, dans la fonction trier, la section où nous devons mettre notre code qui va dire au serveur de trier le tableau dans l'ordre croissant.

Je ne rentre pas dans les détails de ce que fait ce script, les commentaires sont assez clairs.

Algo, Algo, Algo

En algorithmie, il y a différents types de tri de tableaux.

Nous allons utiliser l'algorithme du tri à bulles

for i in range(N - 1, 0, -1):
  for j in range(0, i):
    if comparer(j + 1, j):
      echanger(j + 1, j)

Le but de ce code est de faire des permutations de valeurs dans un tableau non ordonné jusqu'à avoir toutes les valeurs ordonnées de manière croissante.

Plaçons ce bout de code dans le script client.py

#!/usr/bin/env python3

# python3 -m pip install pwntools
from pwn import *

# Paramètres de connexion
HOST, PORT = "challenges.france-cybersecurity-challenge.fr", 2051

def comparer(x, y):
	io.sendlineafter(b">>> ", f"comparer {x} {y}".encode())
	return int(io.recvline().strip().decode())

def echanger(x, y):
	io.sendlineafter(b">>> ", f"echanger {x} {y}".encode())

def longueur():
	io.sendlineafter(b">>> ", b"longueur")
	return int(io.recvline().strip().decode())

def verifier():
	io.sendlineafter(b">>> ", b"verifier")
	r = io.recvline().strip().decode()
	if "flag" in r:
		print(r)
	else:
		print(io.recvline().strip().decode())
		print(io.recvline().strip().decode())

def trier(N):
	#############################
	#   ... Complétez ici ...   #
	# Ajoutez votre code Python #
	#############################
	for i in range(N - 1, 0, -1):
		for j in range(0, i):
			if comparer(j + 1, j):
				echanger(j + 1, j)
	pass

# Ouvre la connexion au serveur
io = remote(HOST, PORT)

# Récupère la longueur du tableau
N = longueur()

# Appel de la fonction de tri que vous devez écrire
trier(N)

# Verification
verifier()

# Fermeture de la connexion
io.close()

Résultat de l'exécution :

FCSC{e687c4749f175489512777c26c06f40801f66b8cf9da3d97bfaff4261f121459}
Lolcat