6.1.24 pwn HITCONCTF2016 House_of_Orange
题目复现
$ file houseoforange
houseoforange: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a58bda41b65d38949498561b0f2b976ce5c0c301, stripped
$ checksec -f houseoforange
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH Yes 1 3 houseoforange
$ strings libc-2.23.so | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu3) stable release version 2.23, by Roland McGrath et al.
Compiled by GNU CC version 5.3.1 20160413.64 位程序,保护全开,默认开启 ASLR。
在 Ubuntu16.04 上玩一下:
$ ./houseoforange
+++++++++++++++++++++++++++++++++++++
@ House of Orange @
+++++++++++++++++++++++++++++++++++++
1. Build the house
2. See the house
3. Upgrade the house
4. Give up
+++++++++++++++++++++++++++++++++++++
Your choice : 1 <-- Build a house
Length of name :20
Name :AAAAAAAAAAAAAAAAAAA
Price of Orange:1
+++++++++++++++++++++++++++++++++++++
1. Red
2. Green
3. Yellow
4. Blue
5. Purple
6. Cyan
7. White
+++++++++++++++++++++++++++++++++++++
Color of Orange:1
Finish
+++++++++++++++++++++++++++++++++++++
@ House of Orange @
+++++++++++++++++++++++++++++++++++++
1. Build the house
2. See the house
3. Upgrade the house
4. Give up
+++++++++++++++++++++++++++++++++++++
Your choice : 3 <-- Upgrade the house
Length of name :10
Name:BBBBBBBBBB
Price of Orange: +++++++++++++++++++++++++++++++++++++
1. Red
2. Green
3. Yellow
4. Blue
5. Purple
6. Cyan
7. White
+++++++++++++++++++++++++++++++++++++
Color of Orange: 1
Finish
+++++++++++++++++++++++++++++++++++++
@ House of Orange @
+++++++++++++++++++++++++++++++++++++
1. Build the house
2. See the house
3. Upgrade the house
4. Give up
+++++++++++++++++++++++++++++++++++++
Your choice : 2 <-- See the house
Name of house : BBBBBBBBBBAAAAAAAAA
Price of orange : 0
__
\/.--,
//_.'
.-""-/""----..
/ . . . . . . . \
/ . . . . . . . . \
|. 乂 . . . 乂. .|
\ . . . . . . . . |
\. . . . . . . . ./
\ . . . *. . . /
'-.__.__.__._-'
+++++++++++++++++++++++++++++++++++++
@ House of Orange @
+++++++++++++++++++++++++++++++++++++
1. Build the house
2. See the house
3. Upgrade the house
4. Give up
+++++++++++++++++++++++++++++++++++++
Your choice : 4
give up程序允许我们对 house 进行 Build、See 和 Upgrade 的操作。可以看到在 See 的时候似乎有点问题,"A"的字符串应该是 Upgrade 之前的,但这里还是被打印了出来,猜测可能存在信息泄露,需要重点关注。
题目解析
Build the house
通过对这段代码的分析可以得到两个结构体:
Build 最多可以进行 4 次,整个过程有 2 个 malloc 和 1 个 calloc:
malloc(0x10):给 house struct 分配空间malloc(length):给 name 分配空间,其中 length 来自用户输入,如果大于 0x1000,则按照 0x1000 处理。calloc(1, 8):给 orange struct 分配空间
那么我们再来看一下用于读入 name 的函数:
这个函数在读入 length 长度的字符串后,没有在末尾加上 \x00 截断,正如我们上面看到的,可能导致信息泄露。
See the house
See 会打印出 house->name,orange->price 和 orange 图案。
Upgrade the house
Upgrade 最多可以进行 3 次,当确认 house 存在后,就直接在 orange->name 的地方读入长度为 length 的 name,然后读入新的 price 和 color。新的 length 同样来自用户输入,如果大于 0x1000,则按照 0x1000 处理。
这里的问题在于程序没有将新 length 与旧 length 做任何比较,如果新 length 大于 旧 length,那么将导致堆溢出。
漏洞利用
和常见的堆利用题目不同的是,这题只有 malloc 而没有 free,于是很多利用方法都用不了。当然这题是独创了一种 house-of-orange 的利用方法,这种方法利用堆溢出修改 _IO_list_all 结构体,从而改变程序流,前提是能够泄漏堆和 libc,泄露的方法是触发位于 sysmalloc() 中的 _int_free() 将 top chunk 释放到 unsorted bin 中(详细内容参考章节 3.1.8 和 4.13)。
overwrite top chunk
第一步,覆盖 top chunk 的 size 域,以触发 sysmalloc()。创建第一个 house:
根据一定的规则修改 size,简单说就是这里 top chunk size 是 0x20fa1,那就修改为 0xfa1:
leak libc
接下来分配一个大于 top chunk,小于 mp_.mmap_threshold 的 large chunk,此时将触发 sysmalloc() 中的 _int_free(),top chunk 将被释放到 unsorted bin 中,同时新的 top chunk 将由扩展方式分配出来:
可以看到 old top chunk 已经被放到 unsorted bin 中了,其 fd, bk 指针指向 libc。接下来再分配一个 large chunk,这个 chunk 将从 old top chunk 中切下来,剩下的再放回 unsorted bin:
可以看到 name 3 上有遗留的 old top chunk 的 bk 指针。只要将其打印出来,通过计算即可得到 libc 的基址。
leak heap
在上一步中我们还可以看到 name 3 上还有遗留的 fd_nextsize 和 bk_nextsize,这是因为在分配一个 large chunk 时,会先将 unsorted bin 中的 large chunk 取出放到 large bin 中。因为当前 large bin 是空的,所以 chunk 的 fd_nextsize 和 bk_nextsize 都指向自身:
所以这里我们通过修改 name 即可泄露出 heap 地址:
house of orange
现在我们有了 libc 和 heap 地址,接下来就是真正的 house-of-orange,相信你已经看了参考章节,这里就不再重复了。结果如下:
可以看到 old top chunk 的 size 被改写为 0x60,在下次分配时,会先从 unsorted bin 中取下 old top chunk,将其放到 smallbins[5],同时,unsorted bin 的 bk 也将被改写成了 &IO_list_all-0x10。
pwn
由于不能够通过检查,将触发异常处理过程,malloc_printerr -> __libc_message -> __GI_abort -> _IO_flush_all_lockp。
开启 ASLR,Bingo!!!
exploit
完整的 exp 如下:
参考资料
Last updated
Was this helpful?