tls_dtor_list劫持exit执行-高版本glibc利用思路之一
利用原理
主要链条:
1 | exit->__run_exit_handlers->__call_tls_dtors |
源码:
1 |
|
很清楚能看到如果tls_dtor_list
不为空,就会把cur指针指向tls_dtor_list
,然后将其中func的函数指针字段经过PTR_DEMANGLE
处理后,直接作为函数调用,参数是cur->obj
。
tls_dtor_list
记录了dtor_list
这个单向链表的表头,我们可以通过覆盖tls_dtor_list
的值为一个我们可控的内存区域,然后就能伪造各个字段了。但最麻烦的是在调用func前有一个异或的逻辑,实际上会与fs:0x30(tcbhead_t->pointer_guard)
处的内容进行异或,那我们首先要想办法泄露出这个内容,或者是直接改写这个位置的内容,才可以调用我们想要的函数。所以一般会利用largebin
attack或者unsortedbin
attack两次,完成tls_dtor_list
的修改以及对tcbhead_t->pointer_guard
的修改。
汇编实现
主要逻辑如下:
1 | <__call_tls_dtors+17> mov rbp, qword ptr fs:[rbx] |
先是会把rbp指向tls_dtor_list
,也就是dtor_list
链表的头节点,正是我们修改的地方。然后取出func字段后,会先右移0x11位,再与fs:[0x30]
处的内容异或。最后call进行调用。那么我们传func字段时就先异或再左移,就能够解出正确的函数指针。需要注意的是,如果我们不是直接利用头节点处的dtor_list
,map域也要进行伪造,使map+0x468
为一个可写地址,而且之后的free
也需要想办法绕过,所以最好还是直接一次直接利用完成。因为这里mov rdx, qword ptr [rbp + 0x18]
直接把rdx拉到我们可控的堆区域了,而且我们控制next域就可以控制rdx的值,其实我们也可以走setcontext
的打法。
利用验证
自己写一个堆的菜单题,不做什么限制方便原理验证。
1 |
|
首先泄露libc基址和heap基址,这里libc基址我直接在主程序中打印出来了,其实也可以通过show largebin
来获得。
1 | add(1,0x428) #1 |

然后free掉一个和0x430那个larginbin属于一个大小范围的,但又比0x430小的chunk3,修改以及在largebin中的那个chunk的bk_nextsize域为target_addr-0x20
,然后申请一个大chunk,从topchunk分配,并把chunk3置入largebin,触发largebin
attack,往target_addr
写chunk3的地址。
1 | delete(3) |



然后故技重施,再来次largebin
attack改tcbhead_t->pointer_guard
为一个我们知道的堆地址,这里我们可以先把fake_dtor_list->next
改成一个可控的堆区域先,方便后面栈迁移。这里fs_base
的地址相对于libc基址是固定的,计算一下就可以得出。
1 | edit(3,0x10,p64(0)+p64(heap_base+0x1af0)) #next=chunk2->data |


这里的key就是我们写到fs:0x30
的地址,最后利用chunk2把chunk3(fake_dtor_list)的func域改为加密后的setcontext+61
,由于我们之前把next域设置为了chunk2的data域的地址,所以这里rdx就会指向chunk2的data域,这样我们在改chunk2时,设置rsp为一个可写地址,rbp为栈迁移目标地址-8,rcx为leave;ret
地址,最终就能栈迁移到我们可控的堆段上,这里我们迁移到了chunk8的data域,chunk8写rop链即可。
1 | pop_rdi_ret = libc_base + 0x000000000002a3e5 |




exp
1 | from pwn import * |
- 标题: tls_dtor_list劫持exit执行-高版本glibc利用思路之一
- 作者: collectcrop
- 创建于 : 2024-11-28 12:52:47
- 更新于 : 2024-11-28 12:55:29
- 链接: https://collectcrop.github.io/2024/11/28/tls-dtor-list劫持exit执行-高版本glibc利用思路之一/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。