GDB est un programme de débogage universel, il peut être exécuté sur Unix, ou sur Windows. Voyons quelques commandes et exempls.





0x00. PRESENTATION



Le cracking est l'art de contourner la protection d'un programme, de trouver le code ou de réussir à générer un code. Dans les cas de générations de code ou numéros de série, on parle aussi de keygening.
<br /><br />
Le reversing est l'art d'analyser les instructions du programme dans le but de reconstituer son fonctionnement et de l'analyser (utile dans le forensic ou bien dans l'analyse antivirale).





0x01. QUELQUES COMMANDES


# Disassemble function :

disas|disassemble <*address|function>

(gdb) disas main

Dump of assembler code for function main:
                                      ;
  0x080484ac <+0>:  push   %ebp       ; Prologue d'une fonction
  0x080484ad <+1>:  mov    %esp,%ebp  ;
  [...]
# Extract instruction :

x/<type> <$register|address>

(gdb) x/i $eip

0x80484f7 <main+75>:  test   eax,eax
# Extract decimal :

x/<type> <$register|address>

(gdb) x/d $edx
0xbffff7da:   116

(gdb) x/4d $edx
0xbffff7da:  116  101 115 116
# Extract hexadecimal :

x/<type> <$register|address>

(gdb) x/x $edx
0xbffff7da:   0x74

(gdb) x/4x $edx
0xbffff7da:  0x74  0x65  0x73  0x74
# Extract string :

x/<type> <$register|address>

(gdb) x/s $edx
0xbffff7da:  "test"

(gdb) x/2s $edx
0xbffff7da:  "test"
0xbffff7da:  "USER=root"
# Extract 1 word in hexadecimal format:
x/<type> <$register|address>

(gdb) x/1wx $edx
0xbffff7da:   0x74736574

# Extract 2 words in decimal format:
(gdb) x/2wd $edx
0xbffff7da:   1953719668 1163089152
# Continue execution:
c|continue

(gdb) c
Continuing.

Breakpoint 1, 0x080484b1 in main ()

# Execute from breakpoint step by stepi:
stepi

(gdb) stepi
0x080484b6 in main ()



0x02. GDBINIT


#
# INSTALL INSTRUCTIONS: save as ~/.gdbinit
#
# DESCRIPTION: A user-friendly gdb configuration file, for x86/x86_64 and ARM platforms.
#
# 
#
# CONTRIBUTORS: mammon_, elaine, pusillus, mong, zhang le, l0kit,
#               truthix the cyberpunk, fG!, gln
#
# FEEDBACK: http://reverse.put.as - reverser@put.as
#
# NOTES: 'help user' in gdb will list the commands/descriptions in this file
#        'context on' now enables auto-display of context screen
#
 
wget "https://raw.githubusercontent.com/gdbinit/Gdbinit/master/gdbinit" -O "$HOME/.gdbinit"
 




0x03. STRINGS


 
// Very basic program to crack
 
#include <stdio.h>
 
main(int ac, char **av, char **ev)
{
  char *ref="p4$$WoRD";
 
  if( ac != 2 )
  {
    printf("Usage: %s <code>\\n",av[0]);
    exit(0);
  }
 
  if( strcmp(av[1],ref) )
  {
    printf("Failed.\\n");
    return(1);
  }
  else
  {
    system("/bin/sh");
  }
}
 

   0x080484ac <+0>:    push   %ebp
   0x080484ad <+1>:    mov    %esp,%ebp
   0x080484af <+3>:    and    $0xfffffff0,%esp
   0x080484b2 <+6>:    sub    $0x20,%esp
=> 0x080484b5 <+9>:    movl   $0x80485b0,0x1c(%esp)   ; Store something in stack (1)
   0x080484bd <+17>:   cmpl   $0x2,0x8(%ebp)          ; number of arguments
   0x080484c1 <+21>:   je     0x80484df <main+51>     ; check number of arguments
   0x080484c3 <+23>:   mov    0xc(%ebp),%eax
   0x080484c6 <+26>:   mov    (%eax),%eax
   0x080484c8 <+28>:   mov    %eax,0x4(%esp)
   0x080484cc <+32>:   movl   $0x80485b9,(%esp)      
   0x080484d3 <+39>:   call   0x8048370 <printf@plt>  ; printf(usage)
   0x080484d8 <+44>:   mov    $0x0,%eax
   0x080484dd <+49>:   jmp    0x804851c <main+112>    ; return()
   0x080484df <+51>:   mov    0xc(%ebp),%eax
   0x080484e2 <+54>:   add    $0x4,%eax               ; 
   0x080484e5 <+57>:   mov    (%eax),%eax             ; av[1]
   0x080484e7 <+59>:   mov    0x1c(%esp),%edx         ; (1) stack stored data
   0x080484eb <+63>:   mov    %edx,0x4(%esp)          ; use register data (dx)
   0x080484ef <+67>:   mov    %eax,(%esp)             ; set eax to content of esp (user arg)
=> 0x080484f2 <+70>:   call   0x8048360 <strcmp@plt>  ; eax = strcmp( (eax),(edx) )
   0x080484f7 <+75>:   test   %eax,%eax               ; test if eax equal zero
   0x080484f9 <+77>:   je     0x804850e <main+98>     ; je = jump if equal (zero)
   0x080484fb <+79>:   movl   $0x80485cb,(%esp)
   0x08048502 <+86>:   call   0x8048380 <puts@plt>    ; puts(message)
   0x08048507 <+91>:   mov    $0x1,%eax
   0x0804850c <+96>:   jmp    0x804851c <main+112>    ; return()
   0x0804850e <+98>:   movl   $0x80485d3,(%esp)       ; from main+77
   0x08048515 <+105>:  call   0x8048390 <system@plt>
   0x0804851a <+110>:  jmp    0x804851c <main+112>
   0x0804851c <+112>:  leave
   0x0804851d <+113>:  ret
# Pour cracker ce programme, il faut alors chercher dans le tas (heap), c'est à dire la mémoire interne du programme
(gdb) x/s 0x080484b5

# Ou alors faire un point d'arrêt (breakpoint) sur la procédure de comparaison
(gdb) b *0x080484f2

# Note on peut aussi faire notre breakpoint comme ceci :
(gdb) b main+70

# Notre argument :
(gdb) x/s $eax
0xbffff7d9:  "1234"

# La valeur a laquelle il est comparé
(gdb) x/s $edx
0x8048600:   "p4$$WoRD"



0x04. INTEGER


 
#include <stdio.h>
 
main(int ac, char **av, char **ev)
{
  int ref=1279172;
 
  if( ac != 2 )
  {
    printf("Usage: %s <code>\\n",av[0]);
    return(0);
  }
 
  if( atoi(av[1]) != ref )
  {
    printf("Failed.\\n");
    return(1);
  }
  else
  {
    system("/bin/sh");
  }
}
 

Dump of assembler code for function main:
   0x080484ac <+0>:    push   %ebp
   0x080484ad <+1>:    mov    %esp,%ebp
   0x080484af <+3>:    and    $0xfffffff0,%esp
   0x080484b2 <+6>:    sub    $0x20,%esp
=> 0x080484b5 <+9>:    movl   $0x1384c4,0x1c(%esp)    ; Store something in stack (1)
   0x080484bd <+17>:   cmpl   $0x2,0x8(%ebp)          ; number of arguments
   0x080484c1 <+21>:   je     0x80484df <main+51>     ; check number of arguments
   0x080484c3 <+23>:   mov    0xc(%ebp),%eax 
   0x080484c6 <+26>:   mov    (%eax),%eax
   0x080484c8 <+28>:   mov    %eax,0x4(%esp)
   0x080484cc <+32>:   movl   $0x80485b0,(%esp)
   0x080484d3 <+39>:   call   0x8048360 <printf@plt>  ; printf(usage)
   0x080484d8 <+44>:   mov    $0x0,%eax
   0x080484dd <+49>:   jmp    0x8048516 <main+106>    ; return()
   0x080484df <+51>:   mov    0xc(%ebp),%eax
   0x080484e2 <+54>:   add    $0x4,%eax
   0x080484e5 <+57>:   mov    (%eax),%eax             ; av[1]
   0x080484e7 <+59>:   mov    %eax,(%esp)             ; get content of av[1] from its address in stack
   0x080484ea <+62>:   call   0x80483b0 <atoi@plt>    ; atoi() applied on $eax
=> 0x080484ef <+67>:   cmp    0x1c(%esp),%eax         ; compare $esp+0x1c (stored value) to $eax (av[1])
   0x080484f3 <+71>:   je     0x8048508 <main+92>     ; if result equal zero, jump to main+92
   0x080484f5 <+73>:   movl   $0x80485c2,(%esp)
   0x080484fc <+80>:   call   0x8048370 <puts@plt>    ; puts(message)
   0x08048501 <+85>:   mov    $0x1,%eax
   0x08048506 <+90>:   jmp    0x8048516 <main+106>    ; return()
   0x08048508 <+92>:   movl   $0x80485ca,(%esp)       ; from main+71
   0x0804850f <+99>:   call   0x8048380 <system@plt>
   0x08048514 <+104>:  jmp    0x8048516 <main+106>
   0x08048516 <+106>:  leave
   0x08048517 <+107>:  ret
End of assembler dump.
# Méthode n°1 : retranscrire les données 
; => 0x080484b5 <+9>:    movl   $0x1384c4,0x1c(%esp)    ; Store something in stack (1)
python -c "print int('0x1384c4',0)"

# Méthode n°2 : regarder à quoi est comparée notre argument 
(gdb) b *0x080484ef
Breakpoint 1 at 0x80484ef

(gdb) run 1234
=> 0x80484ef <main+67>: cmp    eax,DWORD PTR [esp+0x1c]

(gdb) x/wd $esp+0x1c
0xbffff59c: 1279172



0x05. DATA


 
#include <stdio.h>
 
main(int ac, char **av, char **ev)
{
  int ref1=97;
  char ref2='c';
  int ref3=0x63;
  int ref4=51;
  char ref5='\\x24';
  int ref6=115;
  int ref7=0x5f;
  char ref8='0';
  char ref9='\\x6b';
 
  // 'acc3$s_0k'
 
  if( ac != 2 )
  {
    printf("Usage: %s <code>\\n",av[0]);
    return(0);
  }
 
  // En assembleur, quand la première condition
  // n'est pas remplie, les autres ne sont pas effectuées
  if( av[1][0] == ref1
   && av[1][1] == ref2
   && av[1][2] == ref3
   && av[1][3] == ref4
   && av[1][4] == ref5
   && av[1][5] == ref6
   && av[1][6] == ref7
   && av[1][7] == ref8
   && av[1][8] == ref9 )
  {
    system("/bin/sh");
  }
  else
  {
    printf("Failed.\\n");
    return(1);
  }
}
 

Dump of assembler code for function main:
   0x0804847c <+0>: push   %ebp
   0x0804847d <+1>: mov    %esp,%ebp
   0x0804847f <+3>: and    $0xfffffff0,%esp
   0x08048482 <+6>: sub    $0x30,%esp
   0x08048485 <+9>: movl   $0x61,0x2c(%esp)
=> 0x0804848d <+17>:  movb   $0x63,0x2b(%esp)      ; movb => mov byte => char
=> 0x08048492 <+22>:  movl   $0x63,0x24(%esp)      ; movl => mov long => (long) int
=> 0x0804849a <+30>:  movl   $0x33,0x20(%esp)      ; movl => mov long => (long) int
=> 0x080484a2 <+38>:  movb   $0x24,0x1f(%esp)      ; movb => mov byte => char
=> 0x080484a7 <+43>:  movl   $0x73,0x18(%esp)      ; movl => mov long => (long) int
=> 0x080484af <+51>:  movl   $0x5f,0x14(%esp)      ; movl => mov long => (long) int
=> 0x080484b7 <+59>:  movb   $0x30,0x13(%esp)      ; movb => mov byte => char
=> 0x080484bc <+64>:  movb   $0x6b,0x12(%esp)      ; movb => mov byte => char
   0x080484c1 <+69>:  cmpl   $0x2,0x8(%ebp)
   0x080484c5 <+73>:  je     0x80484e6 <main+106>
   0x080484c7 <+75>:  mov    0xc(%ebp),%eax
   0x080484ca <+78>:  mov    (%eax),%eax
   0x080484cc <+80>:  mov    %eax,0x4(%esp)
   0x080484d0 <+84>:  movl   $0x8048670,(%esp)
   0x080484d7 <+91>:  call   0x8048340 <printf@plt>
   0x080484dc <+96>:  mov    $0x0,%eax
   0x080484e1 <+101>: jmp    0x80485d2 <main+342>
   0x080484e6 <+106>: mov    0xc(%ebp),%eax
   0x080484e9 <+109>: add    $0x4,%eax
   0x080484ec <+112>: mov    (%eax),%eax
   0x080484ee <+114>: movzbl (%eax),%eax           ; récupère le 1er octet de av[1]
   0x080484f1 <+117>: movsbl %al,%eax              ;
   0x080484f4 <+120>: cmp    0x2c(%esp),%eax       ; compare notre argument à $esp+0x2c
   0x080484f8 <+124>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x080484fe <+130>: mov    0xc(%ebp),%eax
   0x08048501 <+133>: add    $0x4,%eax
   0x08048504 <+136>: mov    (%eax),%eax
   0x08048506 <+138>: add    $0x1,%eax             ; récupère le 2ème octet de av[1]
   0x08048509 <+141>: movzbl (%eax),%eax           ;
   0x0804850c <+144>: cmp    0x2b(%esp),%al        ; compare notre argument à $esp+0x2b
   0x08048510 <+148>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x08048516 <+154>: mov    0xc(%ebp),%eax
   0x08048519 <+157>: add    $0x4,%eax
   0x0804851c <+160>: mov    (%eax),%eax
   0x0804851e <+162>: add    $0x2,%eax             ; récupère le 3ème octet de av[1]
   0x08048521 <+165>: movzbl (%eax),%eax           ;
   0x08048524 <+168>: movsbl %al,%eax              ;
   0x08048527 <+171>: cmp    0x24(%esp),%eax       ; compare notre argument à $esp+0x24
   0x0804852b <+175>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x08048531 <+181>: mov    0xc(%ebp),%eax
   0x08048534 <+184>: add    $0x4,%eax
   0x08048537 <+187>: mov    (%eax),%eax
   0x08048539 <+189>: add    $0x3,%eax             ; récupère le 4ème octet de av[1]
   0x0804853c <+192>: movzbl (%eax),%eax           ;
   0x0804853f <+195>: movsbl %al,%eax              ;
   0x08048542 <+198>: cmp    0x20(%esp),%eax       ; compare notre argument à $esp+0x20
   0x08048546 <+202>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x08048548 <+204>: mov    0xc(%ebp),%eax
   0x0804854b <+207>: add    $0x4,%eax
   0x0804854e <+210>: mov    (%eax),%eax
   0x08048550 <+212>: add    $0x4,%eax             ; récupère le 5ème octet de av[1]
   0x08048553 <+215>: movzbl (%eax),%eax           ;
   0x08048556 <+218>: cmp    0x1f(%esp),%al        ; compare notre argument à $esp+0x1f
   0x0804855a <+222>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x0804855c <+224>: mov    0xc(%ebp),%eax
   0x0804855f <+227>: add    $0x4,%eax
   0x08048562 <+230>: mov    (%eax),%eax
   0x08048564 <+232>: add    $0x5,%eax             ; récupère le 6ème octet de av[1]
   0x08048567 <+235>: movzbl (%eax),%eax           ;
   0x0804856a <+238>: movsbl %al,%eax              ;
   0x0804856d <+241>: cmp    0x18(%esp),%eax       ; compare notre argument à $esp+0x18
   0x08048571 <+245>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x08048573 <+247>: mov    0xc(%ebp),%eax
   0x08048576 <+250>: add    $0x4,%eax
   0x08048579 <+253>: mov    (%eax),%eax
   0x0804857b <+255>: add    $0x6,%eax             ; récupère le 7ème octet de av[1]
   0x0804857e <+258>: movzbl (%eax),%eax           ;
   0x08048581 <+261>: movsbl %al,%eax              ;
   0x08048584 <+264>: cmp    0x14(%esp),%eax       ; compare notre argument à $esp+0x14
   0x08048588 <+268>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x0804858a <+270>: mov    0xc(%ebp),%eax
   0x0804858d <+273>: add    $0x4,%eax
   0x08048590 <+276>: mov    (%eax),%eax
   0x08048592 <+278>: add    $0x7,%eax             ; récupère le 8ème octet de av[1]
   0x08048595 <+281>: movzbl (%eax),%eax           ;
   0x08048598 <+284>: cmp    0x13(%esp),%al        ; compare notre argument à $esp+0x13
   0x0804859c <+288>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x0804859e <+290>: mov    0xc(%ebp),%eax
   0x080485a1 <+293>: add    $0x4,%eax
   0x080485a4 <+296>: mov    (%eax),%eax           ;
   0x080485a6 <+298>: add    $0x8,%eax             ; récupère le 9ème octet de av[1]
   0x080485a9 <+301>: movzbl (%eax),%eax           ;
   0x080485ac <+304>: cmp    0x12(%esp),%al        ; compare notre argument à $esp+0x2c
   0x080485b0 <+308>: jne    0x80485c1 <main+325>  ; if compare failed, then return()
   0x080485b2 <+310>: movl   $0x8048682,(%esp)
   0x080485b9 <+317>: call   0x8048360 <system@plt>
   0x080485be <+322>: nop
   0x080485bf <+323>: jmp    0x80485d2 <main+342>
   0x080485c1 <+325>: movl   $0x804868a,(%esp)
   0x080485c8 <+332>: call   0x8048350 <puts@plt>
   0x080485cd <+337>: mov    $0x1,%eax
   0x080485d2 <+342>: leave
   0x080485d3 <+343>: ret
End of assembler dump.
À propos de movzbl et movsbl :

http://www.cse.unl.edu/~goddard/Courses/JDEP284/Lectures/Lecture5.pdf

MOVSBL and MOVZBL
* MOVSBL sign-extends a single byte, and copies it into a
  double-word destination
* MOVZBL expands a single byte to 32 bits with 24 leading
  zeros, and copies it into a double-word destination

Example:
%eax = 0x12345678
%edx = 0xAAAABBBB
MOVB   %dh, %al       %eax = 0x123456BB
MOVSBL %dh, %eax      %eax = 0xFFFFFFBB
MOVZBL %dh, %eax      %eax = 0x000000BB



=> 0x80484ee <main+114>:  movzx  eax,BYTE PTR [eax]
(gdb) x/xw $eax
0xbffff7d9: 0x34333231


=> 0x80484f1 <main+117>:  movsx  eax,al
(gdb) x/xw $eax
0x31: Cannot access memory at address 0x31

(gdb) info register $eax
eax            0x31 0x31

(gdb) i r $eax
eax            0x31 0x31
# Méthode n°1 : retranscrire les données 
movl   $0x61,0x2c(%esp)  |  int ref1=0x61;
movb   $0x63,0x2b(%esp)  |  char ref2='\\x63';
movl   $0x63,0x24(%esp)  |  int ref3=0x63;
movl   $0x33,0x20(%esp)  |  int ref4=0x33;
movb   $0x24,0x1f(%esp)  |  char ref5='\\x24';
movl   $0x73,0x18(%esp)  |  int ref6=0x73;
movl   $0x5f,0x14(%esp)  |  int ref7=0x5f;
movb   $0x30,0x13(%esp)  |  char ref8='\\x30';
movb   $0x6b,0x12(%esp)  |  char ref9='\\x6b';

$ printf "\\x61\\x63\\x63\\x33\\x24\\x73\\x5f\\x30"
acc3$s_0k



# Méthode n°2 : regarder à quoi est comparée chacun des octets de notre argument
(gdb)  b *0x080484f4
Breakpoint 1 at 0x80484ef

(gdb)  b *0x0804850c
Breakpoint 2 at 0x0804850c

(gdb)  b *0x08048527
Breakpoint 3 at 0x08048527


// ...


(gdb) run 1234
=> 0x80484ef <main+67>: cmp    eax,DWORD PTR [esp+0x1c]

(gdb) x $esp+0x2c
0xbffff59c: 0x00000061
; Nous avons donc le 1er caractère 0x61 ('a')
(gdb) continue

// Par contre, à chaque erreur, on se retrouve en fin de programme (jmp+325)
// il faut donc relancer le programme avec le caractère trouvé pour connaitre le suivant 

(gdb) x $esp+0x2b
0xbffff59c: 0x00000063
; Nous avons donc le 1er caractère 0x61 ('c')
(gdb) continue

(gdb) continue
Failed.

(gdb) r a234

(gdb) x $esp+0x2b
0xbffff59b: 0x00006163
; Nous avons donc le 2nd caractère 0x63 plus le précédent ("ac")




0x06. BOUCLES


 
#include <stdio.h>
 
main(int ac, char **av, char **ev)
{
  char pass[10];
  int i,bad;
 
  // i=0 ; i<10
  // est la m&ecirc;me chose que
  // i=0 ; i<=9
  for( i=0 ; i<10 ; i++ )
  {
    pass[i] = 6*i + 0x37;
    // printf("%c",pass[i]);
  }
  // 7=CIOU[agm
 
  if( ac != 2 )
  {
    printf("Usage: %s <code>\\n",av[0]);
    return(0);
  }
 
  bad=0;
  for( i=0 ; i<10 ; i++ )
  {
    if( av[1][i] != pass[i] )
    {
      bad=1;
    }
  }
 
  if( bad == 0 )
  {
    system("/bin/sh");
  }
  else
  {
    printf("Failed.\\n");
    return(1);
  }
}
 

Dump of assembler code for function main:
   0x0804847c <+0>:   push   %ebp
   0x0804847d <+1>:   mov    %esp,%ebp
   0x0804847f <+3>:   and    $0xfffffff0,%esp
   0x08048482 <+6>:   sub    $0x30,%esp
   0x08048485 <+9>:   movl   $0x0,0x2c(%esp)
   0x0804848d <+17>:  jmp    0x80484b1 <main+53>
   0x0804848f <+19>:  mov    0x2c(%esp),%eax        ; 
   0x08048493 <+23>:  mov    %eax,%edx              ; $eax 
   0x08048495 <+25>:  mov    %edx,%eax              ; $edx 1
   0x08048497 <+27>:  add    %eax,%eax              ; | eax=eax + eax
   0x08048499 <+29>:  add    %edx,%eax              ; | eax=eax + edx
   0x0804849b <+31>:  add    %eax,%eax              ; | eax=eax + eax
   0x0804849d <+33>:  add    $0x37,%eax             ; + 37
   0x080484a0 <+36>:  lea    0x1e(%esp),%ecx        ; 
   0x080484a4 <+40>:  mov    0x2c(%esp),%edx        ; 
   0x080484a8 <+44>:  add    %ecx,%edx              ; 
   0x080484aa <+46>:  mov    %al,(%edx)             ; 
   0x080484ac <+48>:  addl   $0x1,0x2c(%esp)        ; ajouter 1 à $esp
   0x080484b1 <+53>:  cmpl   $0x9,0x2c(%esp)        ; compare $esp à 9
   0x080484b6 <+58>:  jle    0x804848f <main+19>    ; retour en main+19

   0x080484b8 <+60>:  cmpl   $0x2,0x8(%ebp)         ; compare le nombre d'argument à 2
   0x080484bc <+64>:  je     0x80484da <main+94>    ; si c'est OK, alors aller en main+94
   0x080484be <+66>:  mov    0xc(%ebp),%eax         ; 
   0x080484c1 <+69>:  mov    (%eax),%eax            ; 
   0x080484c3 <+71>:  mov    %eax,0x4(%esp)         ; 
   0x080484c7 <+75>:  movl   $0x80485e0,(%esp)      ; x/s 0x80485e0 => "Usage: %s <code>\\n
   0x080484ce <+82>:  call   0x8048340 <printf@plt> ; call printf
   0x080484d3 <+87>:  mov    $0x0,%eax              ; 
   0x080484d8 <+92>:  jmp    0x8048548 <main+204>   ; return()

   0x080484da <+94>:  movl   $0x0,0x28(%esp)        ; 
   0x080484e2 <+102>: movl   $0x0,0x2c(%esp)        ; 
   0x080484ea <+110>: jmp    0x804851b <main+159>   ; 
   0x080484ec <+112>: mov    0xc(%ebp),%eax         ; 
   0x080484ef <+115>: add    $0x4,%eax              ; 
   0x080484f2 <+118>: mov    (%eax),%edx            ; 
   0x080484f4 <+120>: mov    0x2c(%esp),%eax        ; 
   0x080484f8 <+124>: add    %edx,%eax              ; 
   0x080484fa <+126>: movzbl (%eax),%edx            ; argv[i]
   0x080484fd <+129>: lea    0x1e(%esp),%ecx        ; 
   0x08048501 <+133>: mov    0x2c(%esp),%eax        ; 
   0x08048505 <+137>: add    %ecx,%eax              ; 
   0x08048507 <+139>: movzbl (%eax),%eax            ; ref[i]
   0x0804850a <+142>: cmp    %al,%dl                ; compare( ref[i] , tab[i] )
   0x0804850c <+144>: je     0x8048516 <main+154>   ; 
   0x0804850e <+146>: movl   $0x1,0x28(%esp)        ; 
   0x08048516 <+154>: addl   $0x1,0x2c(%esp)        ; 
   0x0804851b <+159>: cmpl   $0x9,0x2c(%esp)        ; compare $esp+0x2c à 9 (la longueur du tableau)
   0x08048520 <+164>: jle    0x80484ec <main+112>   ; goto main+112 

   0x08048522 <+166>: cmpl   $0x0,0x28(%esp)        ; if( flag )
   0x08048527 <+171>: jne    0x8048537 <main+187>   ; 
   0x08048529 <+173>: movl   $0x80485f2,(%esp)      ; 
   0x08048530 <+180>: call   0x8048360 <system@plt> ; system()
   0x08048535 <+185>: jmp    0x8048548 <main+204>   ; 
   0x08048537 <+187>: movl   $0x80485fa,(%esp)      ; 
   0x0804853e <+194>: call   0x8048350 <puts@plt>   ; puts()
   0x08048543 <+199>: mov    $0x1,%eax
   0x08048548 <+204>: leave
   0x08048549 <+205>: ret
End of assembler dump.
# Le déroulement de la boucle s'effectue ainsi :

eax=0
=> 0x8048493 <main+23>:mov    edx,eax

edx=0
=> 0x8048495 <main+25>:mov    eax,edx

=> 0x8048497 <main+27>:add    eax,eax
=> 0x8048499 <main+29>:add    eax,edx
=> 0x804849b <main+31>:add    eax,eax
=> 0x804849d <main+33>:add    eax,0x37
eax=0x37




eax=1
=> 0x8048493 <main+23>:mov    edx,eax

edx=1
=> 0x8048495 <main+25>:mov    eax,edx
=> 0x8048497 <main+27>:add    eax,eax

eax=2
=> 0x8048499 <main+29>:add    eax,edx

eax=3
=> 0x804849b <main+31>:add    eax,eax

eax=6
=> 0x804849d <main+33>:add    eax,0x37
eax=0x3D (*)




eax=2
=> 0x8048493 <main+23>:mov    edx,eax

edx=2
=> 0x8048495 <main+25>:mov    eax,edx
=> 0x8048497 <main+27>:add    eax,eax

eax=4
=> 0x8048499 <main+29>:add    eax,edx

eax=6
=> 0x804849b <main+31>:add    eax,eax

eax=C (=12)
=> 0x804849d <main+33>:add    eax,0x37
eax=0x43 (*)




eax=3
=> 0x8048493 <main+23>:mov    edx,eax

edx=3
=> 0x8048495 <main+25>:mov    eax,edx
=> 0x8048497 <main+27>:add    eax,eax

eax=6
=> 0x8048499 <main+29>:add    eax,edx

eax=9
=> 0x804849b <main+31>:add    eax,eax

eax=12 (=18)
=> 0x804849d <main+33>:add    eax,0x37
eax=0x49 (*)



eax=1
edx=1
eax=eax + eax + edx  [1]
eax=eax + eax        [2]

( (  1 + 1 ) +  1 ) + ( (  1 + 1 ) +  1 ) = 6
    --- ---    ---        --- ---    ---
[1] eax+eax  + edx    [1] eax+eax  + edx

------------------   ------------------
[2]     eax        +         eax



eax=2
edx=2
eax=eax + eax + edx
eax=eax + eax

( (  2 + 2 ) +  2 ) + ( (  2 + 2 ) +  2 ) = 12
    --- ---    ---        --- ---    ---
[1] eax+eax  + edx    [1] eax+eax  + edx

------------------   ------------------
[2]     eax        +         eax


#>>>> En assembleur la multiplication se fait par un ensemble d'additions

(*) : Nous avons les valeurs hexadécimale stockée dans le tableau 

# Méthode n°1 : retranscrire les données, si on fait un breakpoint sur 0x80484a0,
# on peut lire ce qui est stocké dans le tableau dans eax :

(gdb) b *0x080484a0
(gdb) continue
(gdb) i r $eax

# Une fois sorti de la boucle, on a récolté toutes les valeurs du tableau :
# Le mot de passe est :
$ printf "\\x37\\x3D\\x43\\x49\\x4F\\x55\\x5B\\x61\\x67\\x6D"
7=CIOU[agm





   =>   Écrit par : Nicolas, le 06 juillet 2015


 
Mots clés :  
  reverse 
  
  gdb 
    >   Articles connexes :

Format String


Le "format string" est une vulnérabilité lié au paramètre qu'il est possible de donner à l'instruction printf et ses dérivés. Nous allons l'exploiter dans un cas d'école

6401141