0%

pwn-libc.so

关于libc的学习

在libc.so.6中,各个函数的相对地址是固定的,比如函数A相对于libc.so.6的起始地址为addr_A,函数B相对于libc.so.6的起始地址为addr_B,那么,如果我们能够泄漏进程内存空间中函数A的地址address_A,那么函数B在进程空间中的地址就可以计算出来了,为address_A + addr_B - addr_A

调用函数的真实执行路径是: plt $\rightarrow$got$\rightarrow$真实地址

也就是说plt表里面放的是got表的地址,got表里面放的是函数的真实地址。

当我们在第一次执行某个函数的时候,第一步是由函数调用跳入到PLT表中,然后第二步是从PLT表跳到GOT表中,第三步由GOT表回跳到PLT表中,这时候进行压栈,把代表函数的ID压栈,接着第四步跳转到公共的PLT表项中,第5步进入到GOT表中,然后_dl_runtime_resolve对动态函数进行地址解析和重定位,第七步把动态函数真实的地址写入到GOT表项中,然后执行函数并返回。

当我们第二次调用某个函数的时候,我们的第一步还是由函数调用跳入到PLT表,但是第二步跳入到GOT表中时,但是这个时候该表项已经是动态函数的真实地址了,所以可以直接执行然后返回。

如果开启alsr,libc每次加载的地址就不一样。

Payload1 = padding1+ p32(write_plt) + p32(func) + p32(1) + p32(write_got) + p32(4)

这样就可以写漏出write_got,也就是write在函数中的真实地址。

binsh在libc中的地址可以直接搜索得到 binsh_libc = libc.search(‘/bin/sh’).next()

64位传参:参数从左到右放入寄存器:RDI, RSI, RDX, ECX, R8, R9。当参数为7个以上时,前6个与前面一样,但后面的依次从“右向左”放入栈中。