house of force | bctf2016-bcloud

Author Avatar
Aryb1n 7月 04, 2018

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

所以现在我们能够

  1. leak出heapbase
  2. 控制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之后贴上来