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ê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