ret2csu学习
ret2csu学习
在栈溢出的时候,64位程序的参数,都是要存在寄存器上的,有时我们直接去控制寄存器的汇编指令并不多(因为程序大多数都是动态链接),但是,动态链接的elf文件,一定存在一个这样的函数:__libc_csu_init:
我们要利用的就是下面这两段(loc_400710和loc_400726),我们先利用loc_400726,但是,我们并不从头开始,而是从pop rbx开始,我们溢出的返回地址,就填写pop rbx的地址,接下来我们设置rbx等于0,rbp等于1,r12传入一个地址,这个地址记录着我们想要执行的函数的起始地址 ,这一点非常重要,并非传入我们想要执行的函数的起始地址,因为汇编指令的书写是[r12 + rbx * 8],我们一般传入我们想要执行的函数的got表地址,因为一个函数的got表地址,记录着这个函数的真实起始地址,接下来我们设置r13为我们想执行的函数的第一个参数,r14为我们想执行的函数的第二个参数,r15为我们想执行的函数的第三个参数,接下来到了retn指令,我们写入0x400710跳转到loc_400710去执行,接下来的三个指令执行完毕,将对应的参数压入了对应的寄存器中,接下来的call qword ptr [r12+rbx*8],因为我们设置rbx等于0的缘故,这里的地址完全由r12控制,指令等效为call qword ptr [r12],就会跳转到我们想要执行的函数的起始地址,此时,参数,函数全部正确,就会正常执行了。
举一个例子,此时我们程序存在栈溢出漏洞,buf大小为0x10,但是可以向buf读0x100,假设我们想去执行write函数。此时,我们可以:
1 | python2: |
为什么我们要设置,rbp为1呢,其实是这样的:
如果r12的值我们没有找到呢,没有这个got表的地址呢,我们就要利用上面图片最下面的retn,我们去call一个空函数(_term_proc函数),返回后add rbx,1 此时rbx为1,cmp rbp,rbx ,此时rbx ,rbp都等于一,相等,不会执行jnz short_400710,而是向下执行,我们再写入垃圾数据,然后执行到retn那里,写入想跳转的地址即可。