栈ASLR保护Address Space Layout Randomization 地址空间布局随机化是一种对程序的保护机制。它通过如其名的保护方式通过在程序运行时对程序的栈堆共享库libc等的地址随机化来避免不怀好意的人通过栈溢出时在溢出区直接给程序输入固定的程序地址以此来让程序跳转到其想让程序跳转到的地址最终劫持执行流。开启了ASLR保护后程序每一次运行时函数system和字符串/bin/sh的地址都是随机的这样攻击者就不能通过给程序输入固定的地址来控制程序跳转。为了克服ASLR这一困难我们会使用下面的攻击方法一步步解释我们想要劫持程序的执行流通常是想方设法地让程序执行system/bin/sh。而现在的程序里就算有system函数和/binsh字符串由于开启了ASLR保护我们就不能在溢出区直接输入固定的函数和字符串的地址像前面那样pop_rdi binsh然后直接执行system函数。既然现在程序内部函数的地址是随机的我们就想办法让它从随机变为固定或者说半固定。ASLR保护存在时libc整个共享库会完整地偏移某个值。这就给了我们操作的机会我们可以通过某些libc库中的函数例如puts函数通过查看它们原的地址和偏移后的地址来计算偏移量。这样通过固定的偏移量我们就可以通过libc基址加上system函数在libc库中的绝对地址然后加上偏移量把这样的payload插入程序溢出区就可以让程序执行system函数。我们用ciscn_2019_n_1这道题目为例。main函数调用了func这个函数。我们可以看到func函数中存在gets函数存在栈溢出程序中也存在puts函数我们可以从中操作来得到libc的偏移量。第一步查找puts函数在程序中的真实地址第二步通过puts真实地址和puts在libc中绝对地址的差值找到libc库的基值第三步通过libc中绝对地址固定的system函数和/binsh加上偏移得到它们在程序中的真实地址构造payload。下面我们来写exp上面的这一半包括了我们上面说的前两步。io连接process因为这里作者选择打本地elf连接本地文件方便后续确定puts函数的plt和got表位置。直接构造第一个payload输入之后程序会返回一个值我们pop rdi为puts的got表地址然后通过plt表来跳转执行puts函数让他为我们输出程序的地址存在got表中。plt表相当于跳板程序执行callplt时会跳到这里将地址存入got或跳到已存地址的got表got是一个二重指针里面存储着一个个指针程序所调用过函数的地址。//像是本例中程序调用过了puts函数之后就会把puts函数在程序中的真实地址存在这里。通过接收函数us我们就接收到了puts函数的真实地址。payload里的main函数地址是因为接下来我们还要对程序再进行一次攻击就是我们搞到了偏移量之后直接执行system函数和binsh字符串地址之后的攻击。接下来我们通过通过xxx_offsetlibc.dump(xxx)这个指令来计算libc库的基址。通过libc.dump我们可以确定上述函数在libc库中的偏移量。结合偏移量我们即可写出最终的劫持payload。