缓冲区溢出程序


地址改写
将main函数的返回地址写入main函数的第一个参数在堆栈中的位置保证溢出返回后能返回到__lib_start_main函数使程序顺利结束
将foo 函数的返回地址写入main函数的返回地址,当main 函数执行结束返回时会跳转到foo函数中执行(溢出)

执行过程
1、__lib_start_main 为main函数创建好堆栈空间写好返回地址
2、main函数执行该地址输出now in main执行结束返回(跳转)到foo函数
3、foo函数输出jump here 执行shell结束返回到__lib_start_main函数调用main的下一条指令
4、__lib_start_main 函数继续执行,结束程序

说明
len可设置为1或2,编译时直接在栈顶开辟4个或8个字节的空间,
设置成其他值时在栈顶到数据结尾处会有一些字节的空间不容易得到函数的返回地址

汇编代码:

main函数
Dump of assembler code for function main:
0x8048568 <main>:         push   %ebp                  ;将旧ebp(__lib_start_main中)压栈
0x8048569 <main+1>:     mov    %esp,%ebp             ;将esp值赋给ebp AT&T汇编模式
0x804856b <main+3>:     sub    $0x8,%esp             ;为局部变量开辟空间,这里刚好是两个字节
0x804856e <main+6>:     mov    0x4(%ebp),%eax        ;ebp+4为main的返回地址,
0x8048571 <main+9>:     mov    %eax,0x8(%ebp)        ;将main的返回地址写入其下面的单元,使溢出返回后能回到__lib_start_main中
0x8048574 <main+12>:    movl   $0x8048540,0x4(%ebp)  ;将foo函数的入口地址写入main函数的返回地址中
0x804857b <main+19>:    sub    $0xc,%esp
0x804857e <main+22>:    push   $0x804861a
0x8048583 <main+27>:    call   0x80483f4 <puts>
0x8048588 <main+32>:    add    $0x10,%esp
0x804858b <main+35>:    mov    $0x0,%eax
0x8048590 <main+40>:    leave 
0x8048591 <main+41>:    ret   
End of assembler dump.

foo函数
Dump of assembler code for function foo__Fv:
0x8048540 <foo__Fv>:    push   %ebp
0x8048541 <foo__Fv+1>:  mov    %esp,%ebp
0x8048543 <foo__Fv+3>:  sub    $0x8,%esp
0x8048546 <foo__Fv+6>:  sub    $0xc,%esp
0x8048549 <foo__Fv+9>:  push   $0x8048608
0x804854e <foo__Fv+14>: call   0x80483f4 <puts>
0x8048553 <foo__Fv+19>: add    $0x10,%esp
0x8048556 <foo__Fv+22>: sub    $0xc,%esp
0x8048559 <foo__Fv+25>: push   $0x8048612
0x804855e <foo__Fv+30>: call   0x80483e4 <system>
0x8048563 <foo__Fv+35>: add    $0x10,%esp
0x8048566 <foo__Fv+38>: leave 
0x8048567 <foo__Fv+39>: ret   
End of assembler dump.

执行到<main+6>时的堆栈结构为

esp  -->            offset+0 [ buf[0]                                            ]
                         offset+1 [ buf[1]                                            ]
ebp  -->            offset+2 [ 旧ebp(__lib_start_main中的) ]
                         offset+3 [  main 返回地址                            ]
                         offset+4 [  argc = 1 main函数运行的参数   ]   

执行到<foo_Fv+6>时的堆栈结构为

                         offset+0 [ 局部变量空间                            ]
esp  -->            offset+1 [ 局部变量空间                             ]
                         offset+2 [ 局部变量空间                             ]
ebp  -->            offset+3 [  旧ebp (main中的)                  ]
                         offset+4 [  main的返回地址                         ] 
                   
源代码
                   
#include <stdio.h>
#include <stdlib.h>

void foo(void)
{
        puts("jump here");
        system("/bin/sh");
}
#define len 2

int main()
{
        int buf[len];
        *(int *)(buf+len+2) = *(buf+len+1);
        *(int *)(buf+len+1) =(int)((void(*)(void))foo);
        puts("now in main");
        return 0;
}

shell下执行过程
# g++ -g test.c
# ls
a.out  test.c
# ./a.out
now in main
jump here
sh-2.05a# ls
a.out  test.c
sh-2.05a# exit
exit
#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值