Ret2libc函数个人见解
在学习libc之前,我们要先懂得32位和64位的传参模式。
1.32位-----是栈里传参,属于后传参
2.64位-----是先传参,其参数从左到右依次放入寄存器:rdi,rsi,rdx,rcx,r8,r9中
接着,我们就要开始学习plt和got的关系。
深入理解GOT表和PLT表 - 知乎 (zhihu.com)
由此文章我们大概可以发现我们是由got表转到plt表来获得函数真实地址,所以如何发现这些函数的地址呢,这时候我们就想到了两个函数:put和write函数。
第一步
所以下面我们来讲解第一个函数:put函数
Put函数:
Put函数的传参是libc中较为简单的,其只要一个参数即可,所以很明显,那个参数就是某个函数的got地址。可以是read或者put。
32位:其传参方式大概是p32(puts_plt)+p32(main_addr)+p32(puts_got)【也可以是其他函数的got】
32位传参按顺序看即可,先是调用了puts函数,注意需要返回主函数地址才能保证ROP链正常运行。最后加上got函数将其地址表达出来
64位:其传参方式大概是p64(rdi_addr)+p64(puts_got)【也可以是其他函数的got】+p64(puts_plt)+p64(main_addr)
64位传参是需要寄存器的,所以按上文所述,先将他放进rdi寄存器中。大概原理与32位一致
ROPgadget --binary xxx --only 'pop|ret' | grep 'rdi'#查找控制寄存器的指令
这是查找寄存器的方法
接下来就是第二个函数:write函数
Write函数:
Write函数就需要注意,他需要传送三个参数C语言中write函数-CSDN博客,大概模式就是如此。Write函数第一个参数(0代表标准输入,1代表标准输出,2代表标准错误。)write函数第三个参数是输出的字节数#32位就是4,64位就是8
32位:其传参方式大概是
p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
64位:其传参方式大概是
p64(rdi_addr)+p64(1)+p64(rsi_addr)+p64(write_got)+p64(rdx)+p(8)+p64(write_plt)+p64(main_addr)
所需要注意的是,传参有时可以直接利用其本来就有的参数,而且第三个参数可以不用使用寄存器,有时还会由rsi与其他寄存器一起出现,这时第三个参数便可以随便输入了
参考文献:PWN题型之Ret2Libc_[error] './ret2text' is not marked as executable (-CSDN博客
最后就是接受函数地址
32位目前只看见过:
xxx_addr=u32(r.recv(4))
64位则有:
第一个是无数据干扰,第二个是有数据干扰
第二步
第一步已经接收到了,接下来print即可,然后我们看他函数后三位,即可调查到他的真实地址,我们可以使用libcsearcher或者libc database search (blukat.me)在线网站。binsh_addr = next(elf.search(b"/bin/sh"))需要注意libcsearcher查找方法
然后就可以开始计算地址偏移量了:
libc_base=xxx_addr-找出的对应函数的offset
最后就是最普通的栈溢出了,至此libc就结束了。
上述就是我对于的libc的部分理解,本人纯小白,若有部分理解不到位请多多指教。
部分例题以后有时间,我会整理......