# TinyCTF -> Speed WriteUp(rev300)
# Author : fr0g
# Twitter : https://twitter.com/fr0gSecurity /  https://twitter.com/HexpressoCTF
# http://hexpresso.wordpress.com/
# Greetz to : Hask, Pastek, Soup42, Sakiir, NotFound, saxx, BitK, atmoner, ex0ns, kallimero, st0rn & Santa Claus

Je tiens à préciser que je n'expliquerai pas ici le fonctionnement de chaque fonction,
mais simplement comment résoudre l'épreuve, pour la simple et bonne raison qu'à l'heure où j'écris ce paper,
je n'ai pas encore entièrement saisi l'algo.

File : rev300: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x39fe3fa9ef192e30d8a18451110b726b4179a9a7, stripped

md5 : 0785bfc33a983c0e85eb261cfdf5a46b

-------------------------------------------------------------------------------------------

Première Execution : 

$> ./rev300 
Access denied

$> ./rev300 toto
Access denied


$> objdump -h rev300
...
 12 .text         0000036c  08048360  08048360  00000360  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
...

Désassemblage :

gdb-peda$ x/20i 0x08048360
   0x8048360:	xor    ebp,ebp
   0x8048362:	pop    esi
   0x8048363:	mov    ecx,esp
   0x8048365:	and    esp,0xfffffff0
   0x8048368:	push   eax
   0x8048369:	push   esp
   0x804836a:	push   edx
   0x804836b:	push   0x8048690
   0x8048370:	push   0x8048620
   0x8048375:	push   ecx
   0x8048376:	push   esi
   0x8048377:	push   0x80485b5			;; main() offset
   0x804837c:	call   0x8048340 <__libc_start_main@plt>


Posons donc un bp sur la fonction main (0x80485b5), et lançons le programme.
Au début de la fonction, on peut voir que velui ci attend un paramètre :

=> 0x80485be:  cmp    DWORD PTR [ebp+0x8],0x1
   0x80485c2:  jle    0x80485fe			;; jump sur le message d'erreur 'Access denied' si aucun paramètre donné

  if (argc <= 1){
     printf("Access denied\n");
     return (0);
     }


On relance donc le programme avec un password en param, une fois la condition remplie,
celui ci va appeler une fonction prenant en paramètre le password entré par l'user,
ainsi qu'un entier (qui ne m'as pas servi à résoudre l'épreuve, et dont je n'ai pas encore tout à fait saisi l'utilité) :

   0x80485d4:	      mov    DWORD PTR [esp],eax   ;; ici EAX => argv[1]
=> 0x80485d7:	      call   0x8048414

A partir de là, plus qu'à suivre le chemin :) on break sur l'appel à cette fonction 0x8048414,

Une fois dans la fonction concernée, on peut voir que l'instruction cmp sur le registre al
(avec à chaque fois une valeur différente) est assez récurrente, on va donc parcourir les instructions (gdb> ni) jusqu'à atteindre le premier cmp:


    0x8048491: cmp    al,0x69
    0x8048493: je     0x80484e8
    0x8048495: mov    eax,0x0
  __0x804849a: jmp    0x8048536
 |
 |
 |> 0x8048536:	leave  
    0x8048537:	ret

--------------------------------
gdb-peda$ set $al=0x69
gdb-peda$ continue 

A ce moment là, le registre al contient la valeur du premier caractère du password entré par l'user,
et nous pouvons voir que le premier caractère du password attendu est 0x69 ('i'),
on set al à 'i', afin que le saut conditionnel suivant la comparaison soit pris, et 
on continue jusqu'à tomber sur le rappel de la fonction (manifestement récursive), qui vas
comparer le caractère suivant.
Si les deux valeurs sont différentes lors d'une comparaison de caractère, un saut absolu sera pris plus bas afin de quitter la fonction courante avec un return 0;

il ne reste plus qu'à répéter cette operation pour les autres caractères,
aucune autre verification n'est susceptible d'intérrompre la procédure que
les sauts conditionnels après chaque "cmp al,0x??", un nuage de criquets, ou un THE GAME imprévu :þ.
Une fois tous les caractères passés, et le mot de passe attendu "isengard" découvert, la fonction courante fini par un return 1,
qui nous renvoie dans le main.
S'en suit l'appel de la fonction qui génère et affiche le flag (prenant en param le mot de passe entré),
que je n'ai pas encore analysée, disponible en *bas pour les intéressés

On exécute le programme avec le bon mot de passe en paramètre, et c'est tout bon :)

(2:716)$ ./rev300 isengard
Access granted
flag{s0me7hing_S0me7hinG_t0lki3n}

-------------------------------------------------------------------------------------------

*Fonction générant le flag :

   0x8048538:	 push   ebp
   0x8048539:	 mov    ebp,esp
   0x804853b:	 push   edi
   0x804853c:	 push   esi
   0x804853d:	 push   ebx
   0x804853e:	 sub    esp,0xac
   0x8048544:	 lea    edx,[ebp-0xa0]
   0x804854a:	 mov    ebx,0x8048760
   0x804854f:	 mov    eax,0x21
   0x8048554:	 mov    edi,edx
   0x8048556:	 mov    esi,ebx
   0x8048558:	 mov    ecx,eax
   0x804855a:	 rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]
   0x804855c:	 mov    DWORD PTR [ebp-0x1c],0x0
   0x8048563:	 jmp    0x8048598
   0x8048565:	 mov    eax,DWORD PTR [ebp-0x1c]
   0x8048568:	 mov    ecx,DWORD PTR [ebp+eax*4-0xa0]
   0x804856f:	 mov    eax,DWORD PTR [ebp-0x1c]
   0x8048572:	 mov    edx,eax
   0x8048574:	 sar    edx,0x1f
   0x8048577:	 shr    edx,0x1d
   0x804857a:	 add    eax,edx
   0x804857c:	 and    eax,0x7
   0x804857f:	 sub    eax,edx
   0x8048581:	 add    eax,DWORD PTR [ebp+0x8]
   0x8048584:	 movzx  eax,BYTE PTR [eax]
   0x8048587:	 movsx  eax,al
   0x804858a:	 xor    eax,ecx
   0x804858c:	 mov    DWORD PTR [esp],eax
   0x804858f:	 call   0x8048350 <putchar@plt>
   0x8048594:	 add    DWORD PTR [ebp-0x1c],0x1
   0x8048598:	 cmp    DWORD PTR [ebp-0x1c],0x20
   0x804859c:	 jle    0x8048565
   0x804859e:	 mov    DWORD PTR [esp],0xa
   0x80485a5:	 call   0x8048350 <putchar@plt>
   0x80485aa:	 add    esp,0xac
   0x80485b0:	 pop    ebx
   0x80485b1:	 pop    esi
   0x80485b2:	 pop    edi
   0x80485b3:	 pop    ebp
   0x80485b4:	 ret    
