我先燃尽了,四次 bkcrack,出题人是真喜欢这东西啊

还有一堆散点杂色像素图,看的眼睛都要瞎啦

您每题的图片都要藏那么点东西是吗

本次的 PCB 我负责的是 Misc 部分(毕竟我们队里三个搞 Web 的,不如放给那两个经验丰富的 Web 手来搞,我还是回归我擅长的 Misc 领域吧,Web 转 Misc 这块),所以下面我会讲一讲 Misc 部分我的思路,解出来了的题目会标记 Solved

下面放一下战况

time | Solved

题目上来就给了个 ELF 文件

nc 给出的服务器,会给出 base64 编码后的 zip 文件数据流,并询问现在几点

解压出来发现图片,就是个时钟

因为 OpenCV 的识别率不高,且考虑到只有 12 种情况,所以用建哈希表的玩法

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
import base64
import sys
from pwn import remote, context
from zipfile import ZipFile
from hashlib import md5

# 计算 0 - 11 点的图片的 md5
hashmap = {}
for _ in range(12):
with open(f"preset/{_}.png", "rb") as f:
data = f.read()
h = md5(data).hexdigest()
hashmap[h] = _

context.log_level = "debug"
io = remote("192.168.18.31", 24001)

TIPSIG = b'):\n'

intro = io.recvline()
data = io.recvline()
carriage = io.recvline()
tip = io.recvline()
print(tip)
result = TIPSIG

while TIPSIG in result:
zipstream = base64.b64decode(data)
with open("tmp.zip", "wb") as f:
f.write(zipstream)

with ZipFile("tmp.zip", "r") as zip_ref:
zip_ref.extractall(".")

with open("0.png", "rb") as f:
imgdata = f.read()
h = md5(imgdata).hexdigest()
if h in hashmap:
hour = hashmap[h]
minute = hour * 5
else:
hour, minute = 0, 0

print(f"Send line: {hour}:{minute:02d}")

# 发送结果
io.sendline(f"{hour}:{minute:02d}".encode())
result = io.recvuntil(TIPSIG)

print(result.decode())
io.interactive()

然后发现第一次正确了,第二次直接炸,手动也是这样

应该没那么简单 =-=

看了一下,输入应该是 hmm,就不要中间的那个冒号,所以我这里应该是卡输入格式问题了,重新修正了一下

全对会让执行一个命令,我直接反弹 shell(错误的,反弹不了,好像不出网)

没办法,看了一下 bin 里面有 socat,把文件下载下来好了

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
106
107
108
109
110
111
import base64
import io
import sys
from pwn import remote, context
from zipfile import ZipFile
from hashlib import md5

context.log_level = "debug"

hashmap = {}
print("[*] Loading presets...")
try:
for _ in range(12):
with open(f"preset/{_}.png", "rb") as f:
data = f.read()
h = md5(data).hexdigest()
hashmap[h] = _
print(f"[+] Loaded {len(hashmap)} presets.")
except Exception as e:
print(f"[-] Error loading presets: {e}")
sys.exit(1)

try:
p = remote("192.168.18.31", 24001)
except:
print("[-] Connection failed")
sys.exit(1)

PROMPT = b'): '

for i in range(12):
print(f"\n========== Round {i+1} / 12 ==========")

try:
raw_data = p.recvuntil(PROMPT)
except EOFError:
print("[-] Server disconnected prematurely.")
break

lines = raw_data.strip().split(b'\n')
b64_data = b""
for line in lines:
if len(line) > 100:
b64_data = line.strip()
break

if not b64_data:
print("[-] Base64 data not found.")
break

target_idx = 0
try:
zip_bytes = base64.b64decode(b64_data)

with ZipFile(io.BytesIO(zip_bytes), "r") as z:
img_data = z.read("0.png")

img_hash = md5(img_data).hexdigest()

if img_hash in hashmap:
target_idx = hashmap[img_hash]
print(f"[+] Match! Index: {target_idx} (Hash: {img_hash[:6]}...)")
else:
print(f"[-] No match for hash: {img_hash[:6]}...")

except Exception as e:
print(f"[-] Error processing image: {e}")
break

payload = str(target_idx)

print(f"[>] Sending: {payload}")
p.sendline(payload.encode())

try:
output = p.clean(timeout=0.1)
print(output.decode(errors='ignore'))
except:
pass

print("\n[+] Rounds finished. Getting shell...")
payload = b"/bin/sh"
print(f"[>] Sending payload: {payload}")
p.sendline(payload)

print("\n[+] Exfiltrating using socat...")
try:
p.clean()
except:
pass

cmd = b'socat -u FILE:"Bandizip(flag).zip" STDOUT'
print(f"[>] Sending: {cmd}")
p.sendline(cmd)

print("[*] Downloading raw data...")
try:
p.recvline()

data = p.recvall(timeout=5)

with open("flag.zip", "wb") as f:
f.write(data)

print(f"[+] Download complete! Size: {len(data)} bytes")
print("[*] Try to unzip flag.zip now.")

except Exception as e:
print(f"[-] Error: {e}")
p.interactive()
p.close()

不是哥们?又加密了

bkcrack 看一眼

1
2
3
4
5
$ bkcrack -L flag.zip
bkcrack 1.8.1 - 2025-10-25
Archive: flag.zip
Index Encryption Compression CRC32 Uncompressed Packed size Name
----- ---------- ----------- -------- ------------ ------------ ----------------

嗯?空的?修复一下试试?

1
2
3
4
5
6
7
8
$ zip -FF flag.zip --out flag-fixed.zip                                                                             ─╯
Fix archive (-FF) - salvage what can
Found end record (EOCDR) - says expect single disk archive
Scanning for entries...
copying: data.txt
zip warning: no end of stream entry found: data.txt
zip warning: rewinding and scanning for later entries
zip warning: zip file empty

真是空的哥们?问了 AI 说是 socat 的问题,让它给我改了一版

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import base64
import io
import sys
from pwn import remote, context
from zipfile import ZipFile
from hashlib import md5

context.log_level = "debug"

hashmap = {}
print("[*] Loading presets...")
try:
for _ in range(12):
with open(f"preset/{_}.png", "rb") as f:
data = f.read()
h = md5(data).hexdigest()
hashmap[h] = _
print(f"[+] Loaded {len(hashmap)} presets.")
except Exception as e:
print(f"[-] Error loading presets: {e}")
sys.exit(1)

try:
p = remote("192.168.18.31", 24001)
except:
print("[-] Connection failed")
sys.exit(1)

PROMPT = b'): '

for i in range(12):
print(f"\n========== Round {i+1} / 12 ==========")

try:
raw_data = p.recvuntil(PROMPT)
except EOFError:
print("[-] Server disconnected prematurely.")
break

lines = raw_data.strip().split(b'\n')
b64_data = b""
for line in lines:
if len(line) > 100:
b64_data = line.strip()
break

if not b64_data:
print("[-] Base64 data not found.")
break

target_idx = 0
try:
zip_bytes = base64.b64decode(b64_data)

with ZipFile(io.BytesIO(zip_bytes), "r") as z:
img_data = z.read("0.png")

img_hash = md5(img_data).hexdigest()

if img_hash in hashmap:
target_idx = hashmap[img_hash]
print(f"[+] Match! Index: {target_idx} (Hash: {img_hash[:6]}...)")
# 保存 7.zip 用来后面明文攻击
with open(f"debug/round_{i+1}_matched_{target_idx}.zip", "wb") as f:
f.write(zip_bytes)
else:
print(f"[-] No match for hash: {img_hash[:6]}...")

except Exception as e:
print(f"[-] Error processing image: {e}")
break

payload = str(target_idx)

print(f"[>] Sending: {payload}")
p.sendline(payload.encode())

try:
output = p.clean(timeout=0.1)
print(output.decode(errors='ignore'))
except:
pass

cmd = b'socat -u FILE:"Bandizip(flag).zip" STDOUT'
print(f"[>] Sending: {cmd}")
p.sendline(cmd)

print("[*] Receiving raw stream...")

total_data = b""
try:
while True:
# 设置短超时,快速轮询
chunk = p.recv(timeout=1)
if not chunk:
break
total_data += chunk

if len(total_data) > 223000:
break
except Exception as e:
print(f"recv error: {e}")

print(f"[+] Total received: {len(total_data)} bytes")

zip_header = b'\x50\x4B\x03\x04'
start_idx = total_data.find(zip_header)

if start_idx != -1:
print(f"[+] Found ZIP header at offset: {start_idx}")
real_size = 222544
clean_data = total_data[start_idx : start_idx + real_size]

with open("flag_new.zip", "wb") as f:
f.write(clean_data)
print(f"[+] Saved 'flag_new.zip' ({len(clean_data)} bytes).")
print("[*] Now verify with: bkcrack -L flag_new.zip")
else:
print("[-] Still no ZIP header found. Dumping all...")
with open("flag_dump.bin", "wb") as f:
f.write(total_data)

p.close()

这下文件就对了

1
2
3
4
5
6
7
$ bkcrack -L flag_new.zip
bkcrack 1.8.1 - 2025-10-25
Archive: flag_new.zip
Index Encryption Compression CRC32 Uncompressed Packed size Name
----- ---------- ----------- -------- ------------ ------------ ----------------
0 ZipCrypto Store bacedd4d 218800 218812 7.zip
1 ZipCrypto Store 83221ac1 3448 3460 data.txt

里面有 7.zip,大概率是要 7 点的那个压缩包

拿着 7:35 的图片的压缩包来 crack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ bkcrack -C .\flag_new.zip -c 7.zip -p round_10_matched_7.zip
bkcrack 1.8.1 - 2025-10-25
[14:52:49] Z reduction using 218793 bytes of known plaintext
3.9 % (8631 / 218793)
[14:52:50] Attack on 241 Z values at index 211131
Keys: bf431018 6033e5d1 33389c81
100.0 % (241 / 241)
Found a solution. Stopping.
[14:52:50] Keys
bf431018 6033e5d1 33389c81
$ bkcrack -C flag_new.zip -k bf431018 6033e5d1 33389c81 -U flag_cracked.zip "Volcania"
bkcrack 1.8.1 - 2025-10-25
[14:54:02] Writing unlocked archive flag_cracked.zip with password "Volcania"
100.0 % (2 / 2)
Wrote unlocked archive.

得到 data.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMN@MMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MMMMMMHCCMMM@MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MM@@@MMMMMMMMMMMMMMMMMMMMMMMMM@MM@@@MM@MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@CONMMMMMMMMM
MMMMMMMCCO@OCCC@@CCMMMMMM@CCHMMMMMM@CCCOMMMMNCMMMMCCOM@OQMHCOMMMMMMMMQCQ@CCC@MM@C@MMMMMMMMMCCOONMMMNHCCOMNHNMMNCCCOQMMMMQCCOMMMMMMMMM@CCOMNQCNMMCC@M@@@MMMMMMMMMHCOMMMMMMMMQCQMCC@M@@@MCCOMHOCNMMMMMMMMMMM@CCHMMMMMNHNMMMNCMMMMMMMMM
MMMMMMMCCOMMMMMMNCCMMMMM@CCC@C@MMMHCCNMMMMMMNCMMMNCCOMMNCMMCCHM@CQMMHCCNMCCCNC@NC@MMMMMMMMMCCONC@M@CHCCOMCC@MMOC@MMMMM@CCQMMMMMMMMMMMMCCOMMMNC@MCC@MMMMMMMMMMMMMMCCHM@CQMMHCCNMCC@MMMMMCCOMMMNCMMMMMMMMMM@CCC@C@MMMCC@MMMNCMMMMMMMMM
MMMMMMMCCOQOCQMMQCCMMMMMOCCNMHCNMMCC@QCCOMM@QHMMMNCCOHCQ@MMNCC@ONQNNCCHMMCCCMQQNCMMMMMMMMMMCCOMQOMQC@CCOMCC@MMM@QCO@MMOCHMMMMMMMMMMMMMCCO@OCQ@MMCCHCCC@MMMMMMMMMMNCC@ONQNNCCHMMCCHCCC@MCCOMQCC@MMMMMMMMMMOCCNMHCNMMCC@MMM@CH@MMMMMMM
MMMMMMMCCOMMMMMMCCCMMMMHCCHQCHOC@MOC@M@CMMM@QCMMMNCCOMMMMMMMQCOMMMNCCQMMMCCCM@CHOMMMMMMMMMMCCOM@CQCNMCCQMCC@M@O@MMNC@MCCMMMMMMMMMMMMMMCCOMQC@MMMCC@MMMMMMMMMMMMMMMQCOMMMNCCQMMMCC@MMMMMCCOMMNOQMMMMMMMMMHCCHQCHOC@MCC@MMM@CH@MMMMMMM
MMMMMMMCCOMMMMMMNHHM@@@OCOMMMM@CQMMHCCCCMMMMNCMMMNCCQMMMMMMM@OCNMMCCOMMMMCCCMMHC@MMMMMMMMMMCCOMMQCHMMCCQ@NH@MMQCQHCQMM@OCOCQMMMMMMMMM@CCQMMNCHMMCCNNNN@MMMMMMMMMMM@OCNMMCCOMMMMCCNNNN@MCCOMM@OQMMMMMMMMMOCOMMMM@CQ@NH@MMMNCMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@CNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MMMOOOOOOOOMMMMMMMMMMMMMMMM@HCMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

有点抽象,先把 M 换成空格

flag{pwn_misc_re_web_ai}

SMB | Solved

拿到 SMB2 的数据包,先提取 NTLM

https://github.com/mlgualtieri/NTLMRawUnHide

得到 NTLM 信息,拿去 hashcat

username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response

1
2
3
4
rockyou::PC:5649f6b5969a9fbf:f8cb9296a5206484b1baf6bce47abe3b:0101000000000000f68d75c3fb59dc01ba30ab51dc5395c3000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800f68d75c3fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000
rockyou::PC:a230ee46968b6116:c3b172a7df39f6d1765de24170d5f387:0101000000000000ed3fabc7fb59dc01d9b1245c055f29b2000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000
rockyou::PC:12e83c96f85b09d7:14266416151fcfce3b420575ef030028:0101000000000000ed3fabc7fb59dc01ab5b9b0cfe9b35d0000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000
rockyou::PC:3822c6dbeba60ca2:4b35d5e49a18a4bf1ce0e68f591799d0:0101000000000000ed3fabc7fb59dc01c0f5befb4ddd6648000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000

给的数据里面直接就写了 rockyou,所以拿 rockyou 爆破一下,得到密码是 12megankirwin12

  • 用户名:rockyou
  • 域:PC
  • 密码:12megankirwin12
  • server_challenge
    • 5649f6b5969a9fbf
    • a230ee46968b6116
    • 12e83c96f85b09d7
    • 3822c6dbeba60ca2

导出一下 sessionkey

1
2
3
4
5
6
$ tshark -n -r SMB.pcapng -Y 'ntlmssp.messagetype == 0x00000003' -T fields -e ntlmssp.auth.username -e ntlmssp.auth.domain -e ntlmssp.ntlmv2_response.ntproofstr -e ntlmssp.auth.sesskey -e smb2.sesid
Protocol being registered is "Minecraft Java Edition"
rockyou PC f8cb9296a5206484b1baf6bce47abe3b 83ef8765dc2621899e86744f9dd9c5c8 0x0000100000000031
rockyou PC c3b172a7df39f6d1765de24170d5f387 7d8542d2690e115789f9d07c01334ec4 0x0000100000000031
rockyou PC 14266416151fcfce3b420575ef030028 8a71c61fcb8ed0c8d011a5bf7591b0c3 0x0000100000000031
rockyou PC 4b35d5e49a18a4bf1ce0e68f591799d0 daaab95bb9461bbcf65a89a55ea09adb 0x0000100000000031
  • NTproofstring:sessionkey
    • f8cb9296a5206484b1baf6bce47abe3b:83ef8765dc2621899e86744f9dd9c5c8
    • c3b172a7df39f6d1765de24170d5f387:7d8542d2690e115789f9d07c01334ec4
    • 14266416151fcfce3b420575ef030028:8a71c61fcb8ed0c8d011a5bf7591b0c3
    • 4b35d5e49a18a4bf1ce0e68f591799d0:daaab95bb9461bbcf65a89a55ea09adb

算一下 session key

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
from Crypto.Cipher import ARC4
from Crypto.Hash import MD4, MD5, HMAC

def get_decrypted_session_key(password: str, username: str, domain: str, ntProofStr: str, serverChallenge: str, sessionKey: str) -> str:
password = password
username = username
domain = domain
ntProofStr = ntProofStr
serverChallenge = serverChallenge
sessionKey = sessionKey

passwordHash = MD4.new(password.encode('utf-16-le')).digest()
responseKey = HMAC.new(passwordHash, (username.upper()+domain.upper()).encode('utf-16-le'), MD5).digest()
keyExchangeKey = HMAC.new(responseKey, bytes.fromhex(ntProofStr), MD5).digest()
decryptedSessionKey = ARC4.new(keyExchangeKey).decrypt(bytes.fromhex(sessionKey))

return decryptedSessionKey.hex()

if __name__ == "__main__":
data = [
{
"password": "12megankirwin12",
"username": "rockyou",
"domain": "PC",
"ntProofStr": "f8cb9296a5206484b1baf6bce47abe3b",
"serverChallenge": "5649f6b5969a9fbf",
"sessionKey": "83ef8765dc2621899e86744f9dd9c5c8"
},
{
"password": "12megankirwin12",
"username": "rockyou",
"domain": "PC",
"ntProofStr": "c3b172a7df39f6d1765de24170d5f387",
"serverChallenge": "a230ee46968b6116",
"sessionKey": "7d8542d2690e115789f9d07c01334ec4"
},
{
"password": "12megankirwin12",
"username": "rockyou",
"domain": "PC",
"ntProofStr": "14266416151fcfce3b420575ef030028",
"serverChallenge": "12e83c96f85b09d7",
"sessionKey": "8a71c61fcb8ed0c8d011a5bf7591b0c3"
},
{
"password": "12megankirwin12",
"username": "rockyou",
"domain": "PC",
"ntProofStr": "4b35d5e49a18a4bf1ce0e68f591799d0",
"serverChallenge": "3822c6dbeba60ca2",
"sessionKey": "daaab95bb9461bbcf65a89a55ea09adb"
},
]
for item in data:
decrypted_key = get_decrypted_session_key(
item["password"],
item["username"],
item["domain"],
item["ntProofStr"],
item["serverChallenge"],
item["sessionKey"]
)
print(f"Decrypted Session Key: {decrypted_key}")
1
2
3
4
5
$ uv run .\smb_get_session_key.py
Decrypted Session Key: a5bfafdad7cb6b35947e06faa4f2504d
Decrypted Session Key: c3b59105fcb305240a4b00ebdd0aa3a3
Decrypted Session Key: 9b48d9ff2ed50318770c284169f389f0
Decrypted Session Key: fa54bf67cc683198e0a035605521dae1

将导出的 session key 添加到 wireshark 里面去

注意先获取到 sessionid (直接从数据包中就能看到,在 smb.sesid

  • 0x0000100000000031

要转成小端序

  • 3100000000100000

看到请求了一个 zip,直接弄出来,发现加密了,但是算法为 ZipCrypto Store

里面是 exe,exe 文件有个部分比较固定,考虑 bkcrack,用 exe 的签名部分即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ echo -n "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000" | xxd -r -ps > exe_header
$ bkcrack -C %5cletter.zip -c letter.exe -p .\exe_header -o 64
bkcrack 1.8.1 - 2025-10-25
[11:28:27] Z reduction using 56 bytes of known plaintext
100.0 % (56 / 56)
[11:28:27] Attack on 141108 Z values at index 71
Keys: 68cc45ab 864060ce ac958caa
75.6 % (106623 / 141108)
Found a solution. Stopping.
You may resume the attack with the option: --continue-attack 106623
[11:29:47] Keys
68cc45ab 864060ce ac958caa
$ bkcrack -C %5cletter.zip -k 68cc45ab 864060ce ac958caa -U output.zip Volcania
bkcrack 1.8.1 - 2025-10-25
[11:31:48] Writing unlocked archive output.zip with password "Volcania"
100.0 % (1 / 1)
Wrote unlocked archive.

然后解压得到 exe

以下程序分析部分是队友做的

发现运行程序每次都只打印一个字符,但是直接搜 flag 搜不到,猜测是加密了运行时解密

下面有一段数据

这段数据会被转换成 String

然后在 gen_pool 通过指针传入了这个参数

看到 gen_pool 函数的定义

*(arg1 + 8) 就对应的 String 的数据地址,在 shuffle 之前存在对传入的 String 的处理,可猜测数据是在这进行了解密

可在处理完后的地方打断点,看 *(arg1 + 8) 即可看到 Flag

1
flag{N0w_U-V1ctory}

ZipCracker | Solved

不懂,先给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
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

这是一个 **GNU Radio Companion (GRC)** 的流程图文件(通常后缀为 `.grc`)。

GNU Radio 是一个开源的软件无线电(SDR)开发工具包,这个文件描述了一个信号处理的流程。

### 文件内容分析 (CTF 角度)

从代码结构来看,这个流程图正在模拟一个 **NBFM (窄带调频) 发射机**。以下是关键部分的解读:

1. **输入源 (Input):**
* `blocks_wavfile_source_0`: 它尝试读取一个名为 `E:\Download\ZipCracker\password.wav` 的音频文件。
* **CTF 提示:** 这个文件名 `password.wav` 非常关键,暗示这个音频里包含了解压缩某个 ZIP 文件的密码。

2. **信号处理 (Processing):**
* `analog_nbfm_tx_0`: 这是一个 NBFM 发射模块。它将输入的音频数据调制成射频信号(IQ 信号)。
* `pl_freq`: 这里还加入了一个亚音(PL Tone),虽然默认值是 0.0,但在无线电通信中常用于静噪控制。

3. **输出 (Output):**
* **文件输出**: 流程图通过 `blocks_complex_to_float_0` 将生成的复数 IQ 信号拆分成实部和虚部,分别写入:
* `flag1.txt` (实部/I路)
* `flag2.txt` (虚部/Q路)
* **网络流**: `zeromq_pub_sink_0` 将数据发送到 `tcp://127.0.0.1:49201`

### 这道题可能在考什么?

这道题通常有两种考法:

#### 情况 A:你需要恢复密码
题目可能给了你 `flag1.txt``flag2.txt`(或者生成后的单一信号文件),你需要:
1. **合成 IQ 信号**: 将两个 txt 文件的数据合并回一个复数 IQ 信号文件(通常是 `.cfile``.raw` 格式)。
2. **解调**: 使用软件(如 GNU Radio, GQRX, 或者 Python 脚本)对这个信号进行 **NBFM 解调**
3. **听音频**: 解调后你会得到原始的音频,播放它,听里面说出的“密码”。
4. **解压**: 用听到的密码去解压题目给的加密 ZIP 文件。

#### 情况 B:你需要运行这个脚本
如果题目给了你 `password.wav` 但它是加密的或者损坏的,或者需要你生成特定的波形来获取 Flag。
你需要安装 **GNU Radio** (Linux下常用,Windows也有),用 `gnuradio-companion` 打开这个文件。
* **注意**: 你需要修改文件路径(比如 `E:\Download\ZipCracker\...`)为你本地的实际路径,否则运行会报错。

### 简单的解题思路 (针对情况 A)

如果你手头有生成出来的 `flag1.txt``flag2.txt`,可以使用 Python 快速还原并解调(如果你不想装庞大的 GNU Radio):

1. 读取两个文件,组合成 `I + jQ` 的复数数组。
2. 使用 `numpy``scipy` 进行 FM 解调。
3. 保存为 `.wav` 文件并收听。

或者,如果题目只是给了这个文本内容让你分析:
**核心线索是:这是一个将 `password.wav` 进行 NBFM 调制并保存为 IQ 数据的脚本。你需要做的就是逆向这个过程(NBFM 解调)来听到密码。**



这是一个非常典型的无线电取证(SDR Forensics)题目。

根据 GRC 文件分析,`flag1``flag2` 分别是 **IQ 信号****I路(实部)****Q路(虚部)** 数据。
题目原始逻辑是:`音频` -> `NBFM调制` -> `IQ信号` -> `拆分保存`
你需要做的逆向过程是:`合并IQ信号` -> `NBFM解调` -> `保存为音频` -> `听取密码`

即使你没有安装 GNU Radio,也可以直接用 **Python** 脚本来处理这两个文件。

### 核心参数提取(从 GRC 文件中)
* **采样率 (Sample Rate):** GRC 中 `if_rate` = `usrp_rate / 3` = `576000 / 3` = **192000 Hz**
* **数据类型:** `float` (32位浮点数)。GNU Radio 的 File Sink 默认保存的是**二进制**数据,而不是人类可读的文本。

---

### 解题方法:使用 Python 脚本还原音频

你需要安装 python 的 `numpy``scipy` 库:
```bash
pip install numpy scipy
```

然后运行以下脚本(将脚本放在 `flag1``flag2` 同目录下):

```python
import numpy as np
from scipy.io import wavfile

# 1. 配置参数
# 从 GRC 文件中分析得出:if_rate = 576000 / 3
SAMPLE_RATE = 192000
FILENAME_I = 'flag1.txt' # 如果题目给的文件名没有后缀,请自行修改为 'flag1'
FILENAME_Q = 'flag2.txt' # 同上,修改为 'flag2'

print("正在读取文件...")

# 2. 读取数据
# GNU Radio 的 File Sink 默认存储为 raw binary float32
# 如果你用记事本打开全是乱码,那就是二进制;如果是数字文本,需要改用 loadtxt
try:
# 尝试作为二进制读取
data_i = np.fromfile(FILENAME_I, dtype=np.float32)
data_q = np.fromfile(FILENAME_Q, dtype=np.float32)
except FileNotFoundError:
print(f"错误:找不到文件,请确认文件名是否为 {FILENAME_I} 和 {FILENAME_Q}")
exit()

# 确保两个文件长度一致
min_len = min(len(data_i), len(data_q))
data_i = data_i[:min_len]
data_q = data_q[:min_len]

# 3. 合成 IQ 复数信号
# I 是实部,Q 是虚部
iq_signal = data_i + 1j * data_q

print("正在进行 NBFM 解调...")

# 4. NBFM 解调 (非相干解调)
# 核心原理:计算相邻采样点之间的相位差 (即频率)
# result = angle( s[n] * conj(s[n-1]) )
demodulated = np.angle(iq_signal[1:] * np.conj(iq_signal[:-1]))

# 5. 音频后处理
# 归一化到 -1.0 到 1.0 之间,防止爆音
demodulated = demodulated / np.max(np.abs(demodulated))

# 6. 保存为 WAV 文件
OUTPUT_FILE = 'recovered_password.wav'
wavfile.write(OUTPUT_FILE, SAMPLE_RATE, demodulated.astype(np.float32))

print(f"完成!请播放 {OUTPUT_FILE} 听取密码。")
```

### 拿到音频后怎么办?

1. **播放音频**:生成的 `recovered_password.wav` 可能会有明显的底噪(嘶嘶声),这是 NBFM 解调的特性。
2. **听取内容**
* 如果是**人声**,仔细听他在读什么(通常是英语字母或数字)。
* 如果是**“滴滴滴”**的声音,可能是摩斯电码。
* 如果是**怪异的拨号声**,可能是 DTMF 信号(可以用手机上的 DTMF 识别软件或 Audacity 分析频谱)。
3. **解压**:题目名字叫 `zipcracker`,说明这个 flag 或者是解压密码,或者是需要你根据听到的内容去构造 flag。

### 常见问题排错

* **读取报错?**
* 如果脚本运行出来的音频全是噪音,没有任何有效信息,检查一下 `flag1``flag2` 文件内容。用记事本打开,如果是**人类可读的数字**(例如 `0.1234`),则脚本中 `np.fromfile` 需要改为 `np.loadtxt`。但根据 GR 默认行为,大概率是二进制乱码。
* **语速太快/太慢?**
* 修改脚本中的 `SAMPLE_RATE`。如果声音像花栗鼠,把采样率改低(比如 48000);如果声音像巨人,把采样率改高。但 192000 是根据题目计算出的理论正确值。
* **声音太小?**
* 使用 Audacity 打开生成的 wav 文件,进行“放大(Amplify)”处理。

OK,用脚本处理一下,丢进 AU,很明显的摩斯电码

得到密码,解压给到的 flag.zip

好好好今天是 bkcrack 专场是吧

把 flag.txt 的明文头和尾巴拆成了两部分,放到 head.txt 和 tail.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ bkcrack -C flag.zip -c flag.txt -p head.txt -o 0 -x 25 2121217d
bkcrack 1.8.1 - 2025-10-25
[15:13:59] Z reduction using 1 bytes of known plaintext
100.0 % (1 / 1)
[15:13:59] Attack on 2555904 Z values at index 6
Keys: 33b19021 93c4a78d 9ceed931
13.3 % (339167 / 2555904)
Found a solution. Stopping.
You may resume the attack with the option: --continue-attack 339167
[15:17:16] Keys
33b19021 93c4a78d 9ceed931

$ bkcrack -C flag.zip -k 33b19021 93c4a78d 9ceed931 -U flag-nopasswd.zip "Volcania"
bkcrack 1.8.1 - 2025-10-25
[15:17:52] Writing unlocked archive flag-nopasswd.zip with password "Volcania"
100.0 % (1 / 1)
Wrote unlocked archive.

得到真正的 flag

1
flag{Y0u_r_th3_Z1p_k1ng!!!!!}

The_Rogue_Beacon | Solved

给了总线信号数据包

有 0x244,这个是车速信号,直接提取 0x244 最大的那个就好了,然后避开那种看起来很可疑的东西

让 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
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
import hashlib
import matplotlib.pyplot as plt
from scapy.all import *

# ================= 配置 =================
TARGET_ID = 0x244 # 目标 ID
# 根据你的样本 0000001b16,有效数据在最后两个字节
BYTE_START = 3
BYTE_END = 5
# ========================================

try:
from scapy.layers.can import CAN
except ImportError:
load_contrib('can')

pcap_file = 'The Rogue Beacon.pcapng'
print(f"[+] 正在读取 {pcap_file} ...")
packets = rdpcap(pcap_file)

indices = []
values = []

print(f"[+] 正在提取 ID {hex(TARGET_ID)} 的 Byte {BYTE_START}-{BYTE_END} 数据...")

for idx, pkt in enumerate(packets, 1):
if pkt.haslayer(CAN):
can = pkt.getlayer(CAN)
if can.identifier == TARGET_ID:
data = can.data

# 确保数据长度足够
if len(data) >= BYTE_END:
hex_val = data[BYTE_START:BYTE_END]
val = int.from_bytes(hex_val, byteorder='big')

indices.append(idx)
values.append(val)

if not values:
print("[-] 错误:没有提取到数据,请检查 ID 或 长度。")
exit()

# 将数据打包排序:(index, value),按 value 从大到小排
sorted_data = sorted(zip(indices, values), key=lambda x: x[1], reverse=True)

print("\nTop 5 最大值候选:")
print("Rank\tPacket_Index\tValue (Dec)\tValue (Hex)")
print("-" * 50)

for i in range(min(5, len(sorted_data))):
idx, val = sorted_data[i]
print(f"#{i+1}\t{idx}\t\t{val}\t\t{hex(val)}")

print("-" * 50)

# ================= 修改部分:自动计算 Top 1 的 Flag =================
if sorted_data:
# 直接取排序后的第一个(最大值)
best_idx = sorted_data[0][0]
best_val = sorted_data[0][1]

print(f"\n[+] 自动锁定最大值数据包: Packet #{best_idx} (Value: {best_val})")

# 计算 SHA256
flag_hash = hashlib.sha256(str(best_idx).encode()).hexdigest()
print(f"\n[SUCCESS] 你的 Flag 是: flag{{{flag_hash}}}")
else:
print("[-] 未找到数据,无法计算 Flag")

# 最后再弹窗画图(关闭窗口后脚本结束)
print("\n[+] 正在显示图表以供确认...")
plt.figure(figsize=(12, 6))
plt.plot(indices, values, label=f"ID {hex(TARGET_ID)} (Bytes {BYTE_START}-{BYTE_END})")
plt.title(f"Speed Curve Analysis - ID {hex(TARGET_ID)}")
plt.xlabel("Packet Index (Frame Number)")
plt.ylabel("Raw Value")
plt.legend()
plt.grid(True)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
uv run .\sol.py
[+] 正在读取 The Rogue Beacon.pcapng ...
[+] 正在提取 ID 0x244 的 Byte 3-5 数据...

Top 5 最大值候选:
Rank Packet_Index Value (Dec) Value (Hex)
--------------------------------------------------
#1 12149 13796 0x35e4
#2 12125 13777 0x35d1
#3 12179 13777 0x35d1
#4 12100 13759 0x35bf
#5 12201 13759 0x35bf
--------------------------------------------------

[+] 自动锁定最大值数据包: Packet #12149 (Value: 13796)

[SUCCESS] 你的 Flag 是: flag{9db878fd06dd7587a91c0fb600e0e9f7c3ea310e75f36253ef57ac2d92dd8c29}

[+] 正在显示图表以供确认...

得到 flag{9db878fd06dd7587a91c0fb600e0e9f7c3ea310e75f36253ef57ac2d92dd8c29}

Whiteout | Solved

直接导入 docker

1
$ docker load -i image.tar

然后可以看到有一个 decode.py 和一个 syslog.bin

  • 6ad10b1fede380e2db5571dfe343455d33dd1f07588368ff59ee2a9a826739a9/opt/app 里面有 decode.py
  • d53154d4f2499c5c31fdd61d359d2a9a0b9076ac639b102bb913c752f5769cfb/opt/.data/logs 里面有 syslog.bin

直接拿出来,一个简单异或

1
2
3
4
5
6
7
KEY = 0x37

with open("syslog.bin", "rb") as f:
data = f.read()

decoded = bytes(b ^ KEY for b in data)
print(decoded)
1
2
$ uv run .\sol.py
b'flag{docker_whiteout_forensics_is_fun}'

Blue

题目名字为 blue,看看蓝色通道,发现可能藏有 zip(50 4b 03 04)

有点怪怪的,说实话,不是那么集中,看样子是隔位提取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import os

RAW_PATH = "blue/blue/raw.bin"
OUT_PATH = "blue/blue/extracted_nibbles_skip1_off0.bin"

def extract_high_nibbles_and_combine(raw: bytes) -> bytes:
nibbles = [(b >> 4) & 0xF for b in raw]
out = bytearray()
for i in range(0, len(nibbles) - 1, 2):
out.append((nibbles[i] << 4) | nibbles[i+1])
return bytes(out)

def main():
with open(RAW_PATH, "rb") as f:
raw_data = f.read()

extracted = extract_high_nibbles_and_combine(raw_data)
with open(OUT_PATH, "wb") as out_f:
out_f.write(extracted)
print(f"Wrote {OUT_PATH} ({len(extracted)} bytes)")

if __name__ == '__main__':
main()

隔位提取出来一个压缩包,带加密

ZipCrypto Store,怎么又是 bkcrack,用 png 文件头爆一下

1
2
3
4
5
6
7
8
9
10
11
12
13
$ echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header
$ bkcrack -C extracted_nibbles_skip1_off0.zip -c xor.png -p png_header -o 0
bkcrack 1.8.1 - 2025-10-25
[13:01:17] Z reduction using 9 bytes of known plaintext
100.0 % (9 / 9)
[13:01:17] Attack on 707085 Z values at index 6
Keys: 68cc45ab 864060ce ac958caa
29.2 % (206267 / 707085)
Found a solution. Stopping.
You may resume the attack with the option: --continue-attack 206267
[13:03:45] Keys
68cc45ab 864060ce ac958caa
$ bkcrack -C .\extracted_nibbles_skip1_off0.zip -k 68cc45ab 864060ce ac958caa -U output.zip "Volcania"

图片丢进 010 发现最后的 IEND 块后还有东西

80504e47 开头,应该是个图,弄出来

不明所以的图,但是题目上一张图片的名字是 xor,应该是要跟什么异或一下,但这张图不是灰度图(即RGB相等),所以丢进 PS 看看,发现只有蓝色通道有东西

尝试提取蓝色通道的数据,但没啥用;试着用这张图跟 xor.png 进行 xor 也没啥用,不懂

尝试一下只跟蓝色通道 XOR 看看,让 AI 写个 script,结果还是不对,没招了

超越感官极致

来都来了,先致敬沙鹰三枪背身

发现注释,可能有用

binwalk一下,毕竟文件那么大

那我还说啥了,提取一下呗

嗯?不行,那就 foremost 一下

发现出来一个压缩包,里面还有一张图 ?.png

不是?又是杂色图?但是这个大小跟分辨率不符,IDAT 的数据非常多,甚至去到了 482 chunks

让 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
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
import zlib
import struct

filename = "?.png" # 你的文件名

with open(filename, 'rb') as f:
data = f.read()

# 1. 提取所有 IDAT 数据块
# PNG 结构: Length(4) + ChunkType(4) + Data(Length) + CRC(4)
# 我们需要跳过 header,遍历 chunks
pos = 8 # Skip PNG signature
idat_data = b''

while pos < len(data):
length = struct.unpack('>I', data[pos:pos+4])[0]
chunk_type = data[pos+4:pos+8]

if chunk_type == b'IDAT':
idat_data += data[pos+8 : pos+8+length]

if chunk_type == b'IEND':
break

pos += 12 + length

print(f"IDAT 压缩数据大小: {len(idat_data)} bytes")

# 2. 解压数据
try:
decompressed_data = zlib.decompress(idat_data)
total_len = len(decompressed_data)
print(f"解压后真实数据大小: {total_len} bytes")
except Exception as e:
print(f"解压失败: {e}")
exit()

# 3. 爆破宽高
# 你的截图显示 offset 0x19 处是 08 02 -> BitDepth=8, ColorType=2 (RGB)
# 所以 BytesPerPixel = 3
bytes_per_pixel = 3

print("正在根据数据大小反推宽高...")
found = False

# 假设宽度在 1 到 10000 之间
for w in range(1, 10000):
# 公式: Total = H * (W * 3 + 1)
# 所以: H = Total / (W * 3 + 1)

line_bytes = w * bytes_per_pixel + 1

if total_len % line_bytes == 0:
h = total_len // line_bytes
# 过滤掉显然不合理的比例(比如 1x10000000)
if h < 100000 and w * h > 1000000: # 假设像素总数应该比较大
print(f"[!] 可能的宽高: 宽度={w}, 高度={h}")
found = True

# 自动修复文件头
print(f"正在尝试修复为 {w}x{h} ...")
with open(filename, 'rb') as f_src:
content = bytearray(f_src.read())

# 修改 IHDR 中的宽高 (Offset 16-24)
# 010 Editor 截图显示 IHDR 从 offset 0x0C 开始 (Length)
# 实际宽高数据在 offset 0x10 (16) 开始
struct.pack_into('>I', content, 16, w)
struct.pack_into('>I', content, 20, h)

# 不需要修正 CRC,因为我们要用看图软件打开,
# 大部分看图软件会忽略 CRC 错误,或者我们稍后手动修。
# 如果 PS 打不开,就用 Chrome/Edge 浏览器打开修复后的图片。

out_name = f"fixed_{w}_{h}.png"
with open(out_name, 'wb') as f_out:
f_out.write(content)
print(f"已保存: {out_name}")

if not found:
print("未找到合适的宽高组合,请检查是否是 RGBA (4通道) 或其他格式。")

发现三种组合,但是没啥用,看不出东西

1
2
3
4
5
6
7
$ uv run .\preview.py
[+] 正在读取 ?.png ...
[+] 解压成功!数据总大小: 31457280 字节
[+] 找到 3 个可能的组合,准备绘制预览...
方案 1: 1365x7680 (RGB)
方案 2: 3413x3072 (RGB)
方案 3: 5461x1920 (RGB)

PunkFace

这题的 word 直接把我电脑卡死了,我还导入了飞书来着,结果飞书在线也卡死了

解压 docx 文档,发现 document.xml 非常大,有很多颜色相关的内容

队友弄了个脚本来提取颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import itertools
import re

from PIL import Image


path = "document.xml"

pixels = []

with open(path, "r") as fp:
for line in fp:
pixels.extend(re.findall(r'<w:r><w:rPr><w:color w:val="([0-9A-F]+)"\/><\/w:rPr><w:t xml:space="preserve"> <\/w:t><\/w:r>', line))

width, height = 1024, 1024
assert height * width == len(pixels)

with Image.new("RGB", (width, height)) as im:
for pixel, (y, x) in zip(pixels, itertools.product(range(height), range(width))):
rgb = int(pixel, 16)
color = ((rgb >> 16), ((rgb >> 8) & 0xFF), (rgb & 0xFF))
im.putpixel((x, y), color)
im.show()

怎么还是这种图??!我对这种图真没招 =-=

队友发现了4通道有东西(这谁想得到woc)

得到一个图

改下颜色,得到

1
4e 65 74 77 6f 72 6b 20 73 65 63 75 72 69 74 79 20 69 73 20 61 6e 20 75 6d 62 72 65 6c 6c 61 20 74 65 72 6d 20 74 6f 20 64 65 73 63 72 69 62 65 20 73 65 63 75 72 69 74 79 20 63 6f 6e 74 72 6f 6c 73 2c 20 70 6f 6c 69 63 69 65 73 2c 20 70 72 6f 63 65 73 73 65 73 20 61 6e 64 20 70 72 61 63 74 69 63 65 73 20 61 64 6f 70 74 65 64 20 74 6f 20 70 72 65 76 65 6e 74 2c 20 64 65 74 65 63 74 20 61 6e 64 20 6d 6f 6e 69 74 6f 72 20 75 6e 61 75 74 68 6f 72 69 7a 65 64 20 61 63 63 65 73 73 2c 20 6d 69 73 75 73 65 2c 20 6d 6f 64 69 66 69 63 61 74 69 6f 6e 2c 20 6f 72 20 64 65 6e 69 61 6c 20 6f 66 20 61 20 63 6f 6d 70 75 74 65 72 20 6e 65 74 77 6f 72 6b 20 61 6e 64 20 6e 65 74 77 6f 72 6b 2d 61 63 63 65 73 73 69 62 6c 65 20 72 65 73 6f 75 72 63 65 73 2e 4e 65 74 77 6f 72 6b 20 73 65 63 75 72 69 74 79 20 69 6e 76 6f 6c 76 65 73 20 74 68 65 20 61 75 74 68 6f 72 69 7a 61 74 69 6f 6e 20 6f 66 20 61 63 63 65 73 73 20 74 6f 20 64 61 74 61 20 69 6e 20 61 20 6e 65 74 77 6f 72 6b 20 76 65 72 61 63 72 79 70 74 2c 20 77 68 69 63 68 20 69 73 20 63 6f 6e 74 72 6f 6c 6c 65 64 20 62 79 20 74 68 65 20 6e 65 74 77 6f 72 6b 20 61 20 69 73 20 36 3f 2c 20 62 20 69 73 20 3f 37 2c 20 73 20 69 73 20 3f 2c 20 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 2e 20 55 73 65 72 73 20 63 68 6f 6f 73 65 20 6f 72 20 61 72 65 20 61 73 73 69 67 6e 65 64 

Network security is an umbrella term to describe security controls, policies, processes and practices adopted to prevent, detect and monitor unauthorized access, misuse, modification, or denial of a computer network and network-accessible resources.Network security involves the authorization of access to data in a network veracrypt, which is controlled by the network a is 6?, b is ?7, s is ?, administrator. Users choose or are assigned

不懂 =-=

Hidden

给了一个 Bmp 文件,Slienteye 出不来东西,应该不是隐写,binwalk 和 foremost 出不来有用的东西,跑路