总的来说有两个层面的攻击,exit.c下基本上是结构体指针的挟持,_dl_fini层面上基本上是linkmap的字段修改或整个挟持

exit.c层面

tls_dtor_list

在exit函数调用的时候会进行tls的解构

void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
		     bool run_list_atexit, bool run_dtors)
{
  /* First, call the TLS destructors.  */
#ifndef SHARED
  if (&__call_tls_dtors != NULL)
#endif
    if (run_dtors)
      __call_tls_dtors (); // dstruct tls
      
...

这里传入参数的时候run_dtors是0x0

__call_tls_dtors的代码如下:

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);
    }
}

struct dtor_list:

type = struct dtor_list {
    dtor_func func; // dtor_func是函数指针
    void *obj;
    struct link_map *map;
    struct dtor_list *next;
}

可以看到这里会依次调用它的func

可以利用这一点构造ROP链条

但是tls_dtor_list在mmap出来的一段中(ld的前一段 相当于打ld需要爆破offset

image.png

这种打法的利用条件仅为能够修改tls_dtor_list的值为一个地址,然后能够往这个地址填东西就行

概念验证:

image.png

image.png

发现地址还发生了变化 查看宏定义 前面有个PTR_DEMANGLE

image.png