BkP CTF 2013 | randy [Write-Up]

Un binaire était donné. Celui ci demande simplement un password de 28 caractères. On le désassemble sous IDA. Voici la fonction intéressante keygen() :


.text:0000000000400A20 public keygen
.text:0000000000400A20 keygen proc near ; CODE XREF: main+155p
.text:0000000000400A20 mov r12, 0
.text:0000000000400A2A mov r13, rdi
.text:0000000000400A2D
.text:0000000000400A2D do_1:
.text:0000000000400A2D mov rax, [r13+r12*4+0]
.text:0000000000400A32 mov rdi, rax ; seed
.text:0000000000400A35 call _srandom
.text:0000000000400A3A call _random
.text:0000000000400A3F cmp rax, 7358837Ah
.text:0000000000400A45 jnz bad
.text:0000000000400A4B call _random
.text:0000000000400A50 cmp rax, 6E1B2658h
.text:0000000000400A56 jnz bad
.text:0000000000400A5C call _random
.text:0000000000400A61 cmp rax, 3C00C5FFh
.text:0000000000400A67 jnz bad
.text:0000000000400A6D call _random
.text:0000000000400A72 cmp rax, 8C0D4AAh
.text:0000000000400A78 jnz bad
.text:0000000000400A7E inc r12
.text:0000000000400A81
.text:0000000000400A81 do_2:
.text:0000000000400A81 mov rax, [r13+r12*4+0]
.text:0000000000400A86 mov rdi, rax ; seed
.text:0000000000400A89 call _srandom
.text:0000000000400A8E call _random
.text:0000000000400A93 cmp rax, 34D8C3B5h
.text:0000000000400A99 jnz bad
.text:0000000000400A9F call _random
.text:0000000000400AA4 cmp rax, 5B56DCA1h
.text:0000000000400AAA jnz bad
.text:0000000000400AB0 call _random
.text:0000000000400AB5 cmp rax, 78236D7h
.text:0000000000400ABB jnz bad
.text:0000000000400AC1 call _random
.text:0000000000400AC6 cmp rax, 1973085Eh
.text:0000000000400ACC jnz bad
.text:0000000000400AD2 inc r12
.text:0000000000400AD5
.text:0000000000400AD5 do_3:
.text:0000000000400AD5 mov rax, [r13+r12*4+0]
.text:0000000000400ADA mov rdi, rax ; seed
.text:0000000000400ADD call _srandom
.text:0000000000400AE2 call _random
.text:0000000000400AE7 cmp rax, 1F49456Ch
.text:0000000000400AED jnz bad
.text:0000000000400AF3 call _random
.text:0000000000400AF8 cmp rax, 27C0FA1Dh
.text:0000000000400AFE jnz bad
.text:0000000000400B04 call _random
.text:0000000000400B09 cmp rax, 145214AAh
.text:0000000000400B0F jnz bad
.text:0000000000400B15 call _random
.text:0000000000400B1A cmp rax, 6200299Ch
.text:0000000000400B20 jnz bad
.text:0000000000400B26 inc r12
.text:0000000000400B29
.text:0000000000400B29 do_4:
.text:0000000000400B29 mov rax, [r13+r12*4+0]
.text:0000000000400B2E mov rdi, rax ; seed
.text:0000000000400B31 call _srandom
.text:0000000000400B36 call _random
.text:0000000000400B3B cmp rax, 1FEA6614h
.text:0000000000400B41 jnz bad
.text:0000000000400B47 call _random
.text:0000000000400B4C cmp rax, 41CDB864h
.text:0000000000400B52 jnz bad
.text:0000000000400B58 call _random
.text:0000000000400B5D cmp rax, 53C0ED56h
.text:0000000000400B63 jnz bad
.text:0000000000400B69 call _random
.text:0000000000400B6E cmp rax, 63642916h
.text:0000000000400B74 jnz bad
.text:0000000000400B7A inc r12
.text:0000000000400B7D
.text:0000000000400B7D do_5:
.text:0000000000400B7D mov rax, [r13+r12*4+0]
.text:0000000000400B82 mov rdi, rax ; seed
.text:0000000000400B85 call _srandom
.text:0000000000400B8A call _random
.text:0000000000400B8F cmp rax, 4E81ABC7h
.text:0000000000400B95 jnz bad
.text:0000000000400B9B call _random
.text:0000000000400BA0 cmp rax, 792CE075h
.text:0000000000400BA6 jnz bad
.text:0000000000400BAC call _random
.text:0000000000400BB1 cmp rax, 7D2BC59Ch
.text:0000000000400BB7 jnz bad
.text:0000000000400BBD call _random
.text:0000000000400BC2 cmp rax, 42A11ADAh
.text:0000000000400BC8 jnz bad
.text:0000000000400BCE inc r12
.text:0000000000400BD1
.text:0000000000400BD1 do_6:
.text:0000000000400BD1 mov rax, [r13+r12*4+0]
.text:0000000000400BD6 mov rdi, rax ; seed
.text:0000000000400BD9 call _srandom
.text:0000000000400BDE call _random
.text:0000000000400BE3 cmp rax, 683D3F5Dh
.text:0000000000400BE9 jnz short bad
.text:0000000000400BEB call _random
.text:0000000000400BF0 cmp rax, 0CAAE38Dh
.text:0000000000400BF6 jnz short bad
.text:0000000000400BF8 call _random
.text:0000000000400BFD cmp rax, 7EC81C18h
.text:0000000000400C03 jnz short bad
.text:0000000000400C05 call _random
.text:0000000000400C0A cmp rax, 444671E6h
.text:0000000000400C10 jnz short bad
.text:0000000000400C12 inc r12
.text:0000000000400C15
.text:0000000000400C15 do_7:
.text:0000000000400C15 mov rax, [r13+r12*4+0]
.text:0000000000400C1A mov rdi, rax ; seed
.text:0000000000400C1D call _srandom
.text:0000000000400C22 call _random
.text:0000000000400C27 cmp rax, 28C9A8FEh
.text:0000000000400C2D jnz short bad
.text:0000000000400C2F call _random
.text:0000000000400C34 cmp rax, 3324B23h
.text:0000000000400C3A jnz short bad
.text:0000000000400C3C call _random
.text:0000000000400C41 cmp rax, 3075F253h
.text:0000000000400C47 jnz short bad
.text:0000000000400C49 call _random
.text:0000000000400C4E cmp rax, 60D2E9D2h
.text:0000000000400C54 jnz short bad
.text:0000000000400C56 inc r12
.text:0000000000400C59
.text:0000000000400C59 good:
.text:0000000000400C59 mov rax, 1
.text:0000000000400C63 retn
.text:0000000000400C64 ; ---------------------------------------------------------------------------
.text:0000000000400C64
.text:0000000000400C64 bad: ; CODE XREF: keygen+25j
.text:0000000000400C64 ; keygen+36j ...
.text:0000000000400C64 mov rax, 0
.text:0000000000400C6E retn
.text:0000000000400C6E keygen endp
.text:0000000000400C6E
.text:0000000000400C6E ; ---------------------------------------------------------------------------
.text:0000000000400C6F align 10h
.text:0000000000400C70

Après compréhension de la routine… ce que fait le programme est très simple.
Le password de 28 octets est coupé en 7 groupes de 4 octets. Chacun de ces groupes de 4 octets passent une condition du style


// On initalise le générateur de nombre pseudo-aléatoires avec nos 4 octets
srand(4 octets);
if( rand() == wwww
and rand() == xxxx
and rand() == yyyy
and rand() == zzzz)
# good

Et ce, avec plein de valeurs différentes à chaque fois.
Notre but va être simplement de bruteforcer 4 octets (c’est à dire des nombres de 0x00000000 à 0xffffffff), de les mettres en tant que seed de 4 futurs nombres aléatoires, et générer ces nombres puis les comparer avec les nombres qu’utilise le binaire pour les comparaisons.
En tout, il y aura 7 morceaux comme ceci à bruteforcer. Voici notre bruteforce en C (la plage a été réduite de 0x20202020 à 0x7f7f7f7f en supposant que le flag est de l’ascii lisible) :

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int seed, a, b, c, d;
	for(seed = 0x20202020; seed < 0x7f7f7f7f; seed++)
	{
		srand(seed);
		a = rand(); b = rand(); c = rand(); d = rand();
		if (a == 0x7358837a && b == 0x6e1b2658 && c == 0x3c00c5ff && d == 0x08c0d4aa) printf("[1] %08x\n", seed);
		if (a == 0x34d8c3b5 && b == 0x5b56dca1 && c == 0x078236d7 && d == 0x1973085e) printf("[2] %08x\n", seed);
		if (a == 0x1f49456c && b == 0x27c0fa1d && c == 0x145214aa && d == 0x6200299c) printf("[3] %08x\n", seed);
		if (a == 0x1fea6614 && b == 0x41cdb864 && c == 0x53c0ed56 && d == 0x63642916) printf("[4] %08x\n", seed);
		if (a == 0x4e81abc7 && b == 0x792ce075 && c == 0x7d2bc59c && d == 0x42a11ada) printf("[5] %08x\n", seed);
		if (a == 0x683d3f5d && b == 0x0caae38d && c == 0x7ec81c18 && d == 0x444671e6) printf("[6] %08x\n", seed);
		if (a == 0x28c9a8fe && b == 0x03324b23 && c == 0x3075f253 && d == 0x60d2e9d2) printf("[7] %08x\n", seed);
	}
}


Voici le résultat au bout quelques petites dizaines de minutes…


[1] 2074306e
[7] 21212121
[3] 30646e34
[6] 31316120
[4] 3420306d
[2] 72203073
[5] 72337466

Génial ! Il ne reste plus qu’à convertir tout ça en string, après avoir remis les valeurs dans l’ordre :

n0t s0 r4nd0m0 4ft3r a11!!!!

Enjoy \o/

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s