Linux栈溢出例子详解

注:本例中使用的例子为看雪论坛帖子中的例子(https://bbs.pediy.com/thread-216868.htm),结合自己的理解,进行更深入的详细的讲解,更有利于理解细节!
例子中的代码如下:

//vuln.c
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
		char name[256];/* [1] */ 
        strcpy(name,argv[1]); /* [2] */
        printf("Welcome, %s\n",name); /* [3] */
        return 0;
}

首先要关闭Linux的地址随机化(ASLR)

#echo 0 > /proc/sys/kernel/randomize_va_space

注解:如果安装了gdb的插件peda,则可以简单的通过aslr命令查看是否开启aslr,也可以通过aslr on/off关闭或者开启aslr
Linux 平台上 ASLR 分为 0,1,2 三级,用户可以通过一个内核参数 randomize_va_space 进行等级控制。可以通过通过cat /proc/sys/kernel/randomize_va_space 查看。它们对应的效果如下:
0:没有随机化。即关闭 ASLR。
1:保留的随机化。共享库、栈、mmap() 以及 VDSO (VDSO就是Virtual Dynamic Shared Object,就是内核提供的虚拟的.so,这个.so文件不在磁盘上,而是在内核里头)将被随机化。
2:完全的随机化。在 1 的基础上,通过 brk() 分配的内存空间也将被随机化。
然后编译程序代码:

$gcc -g -fno-stack-protector -z execstack -no-pie -o vuln vuln.c

这里-fno-stack-protector 是关闭栈保护;-z execstack 是开启栈可执行。“-no-pie”选项用于关闭PIE功能,开启PIE功能意味着编译器将随机化ELF文件的内存装在基址。
然后更改程序的拥有者和组权限,并添加粘滞位(该步骤不是必须的,如此设置可以得到root权限的shell):

$sudo chown root vuln
$sudo chgrp root vuln
$sudo chmod +s vuln

下面我们开始使用gdb调试程序,在这里我们还将详细讲解该段代码对应的每行汇编的具体含义,所以有些啰嗦,如果已经对这部分很熟悉的就可以略过了。
反汇编的代码如下:

(gdb) disass main
Dump of assembler code for function main:
   0x0804844d <+0>:	push   %ebp
   0x0804844e <+1>:	mov    %esp,%ebp
   0x08048450 <+3>:	and    $0xfffffff0,%esp
   0x08048453 <+6>:	sub    $0x110,%esp
   0x08048459 <+12>:	mov    0xc(%ebp),%eax
   0x0804845c <+15>:	add    $0x4,%eax
   0x0804845f <+18>:	mov    (%eax),%eax
   0x08048461 <+20>:	mov    %eax,0x4(%esp)
   0x08048465 <+24>:	lea    0x10(%esp),%eax
   0x08048469 <+28>:	mov    %eax,(%esp)
   0x0804846c <+31>:	call   0x8048320 <strcpy@plt>
   0x08048471 <+36>:	lea    0x10(%esp),%eax
   0x08048475 <+40>:	mov    %eax,0x4(%esp)
   0x08048479 <+44>:	movl   $0x8048520,(%esp)
   0x08048480 <+51>:	call   0x8048310 <printf@plt>
   0x08048485 <+56>:	mov    $0x0,%eax
   0x0804848a <+61>:	leave  
   0x0804848b <+62>:	ret    
End of assembler dump.

下面我们开始运行程序,我们在每行汇编的地方就下一个断点,可以通过b *addr 的方式进行。下面一段时间我们重点关注esp,ebp,eax几个寄存器的值,来熟悉在函数调用的过程中栈如何变化以及如何传参。

(gdb) r AAAAAAAAAAAAAAAA

首先运行到函数开始处:4 int main(int argc, char* argv[]) { 此时,我们通过(gdb) i r 获得的寄存器的值如下:

(gdb) i r
eax            0x2	2
ecx            0x523d8be6	1379765222
edx            0xbf8aef14	-1081413868
ebx            0xb7735000	-1217179648
esp            0xb
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值