/ ndh2k17

Nuit du Hack XV Qualifications - Slumdog Millionaire - (WEB 100)

Description:
The PiggyBank corporation has dediced to open source its new gambling application, SlumdogMillionaire ! Since then, it has become a world phenomenon. They are particularly proud of their new algorithm and hope to prove their game is fair by giving "Carte Blanche" for anyone to audit their code !

Points: 100

Category: Web/Crypto

Url:
http://slumdogmillionaire.quals.nuitduhack.com/

Résolution:
En accédant au site web on arrive sur un jeu ou il faut deviner les 10 prochains nombres en une seule fois. Le code fourni permettant de générer ces nombres est le suivant :

#!/usr/bin/python2.7

import random

import config
import utils


random.seed(utils.get_pid())
ngames = 0


def generate_combination():
    numbers = ""
    for _ in range(10):
        rand_num = random.randint(0, 99)
        if rand_num < 10:
            numbers += "0"
        numbers += str(rand_num)
        if _ != 9:
            numbers += "-"
    return numbers


def reset_jackpot():
    random.seed(utils.get_pid())
    utils.set_jackpot(0)
    ngames = 0


def draw(user_guess):
    ngames += 1
    if ngames > config.MAX_TRIES:
        reset_jackpot()
    winning_combination = generate_combination()
    if winning_combination == user_guess:
        utils.win()
        reset_jackpot()

Dans ce code la ligne suivante est particulièrement intéressante :

 random.seed(utils.get_pid())

En effet ajouter un seed à la fonction random a pour résultat de toujours produire la même séquence. Exemple avec un seed de 1 la séquence sera toujours 13,84,76,...
De plus ici le seed est facilement bruteforcable puisqu'il correspond à un pid (soit un nombre entre 0 et 4194305 sur un système 64bits).

C'est parti, on commence par envoyer une mauvaise réponse au serveur pour obtenir les premiers nombres attendus puis on lance le script suivant :

#!/usr/bin/python
#coding: utf-8

import random

target = "99-40-52-76-91-05-21-42-60-56"

for i in range(4194305):
	random.seed(i)
	numbers = ""
	for _ in range(10):
		rand_num = random.randint(0, 99)
		if rand_num < 10:
		    numbers += "0"
		numbers += str(rand_num)
		if _ != 9:
		    numbers += "-"
	#print numbers
	if target == numbers:
		print 'seed',str(i)
		break

numbers=''
for _ in range(10):
		rand_num = random.randint(0, 99)
		if rand_num < 10:
		    numbers += "0"
		numbers += str(rand_num)
		if _ != 9:
		    numbers += "-"
print 'next numbers',numbers	

Il suffit d'envoyer au serveur "next numbers" et voilà :

flag{God_does_not_pl4y_dic3}