2026年山东省某市网络安全职业技能大赛(含题目、WP)

admin 2026-08-27 05:21:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文记录了2026年山东省某市网络安全职业技能大赛CTF解题思路,涵盖逆向、密码与杂项。逆向题通过去除花指令并逆向MSVC伪随机算法求解;密码题利用已知前缀对重复密钥异或进行推导恢复明文;杂项题深入剖析WPA2-PSK四次握手中PMK、PTK与MIC的生成原理,并附带一套基于Scapy的通用WIFI握手爆破Python脚本,支持多版本加密,对流量分析实战具有较高参考价值。 综合评分: 82 文章分类: CTF,逆向分析,安全工具,实战经验


2026年山东省某市网络安全职业技能大赛(含题目、WP)

原创

蓬莱人形 蓬莱人形

AI丽丝的人偶工坊

2026年8月6日 12:34 山东

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

好久没打过CTF了,感觉已经完全废废了,记录一下学习学习~有不足或者错误的地方,还请劳烦指出(鞠躬)


(省流看文章末尾蓝奏链接,含附件和WP)


RE

题目叫8E,这里有一个8E的指令,上面有个jz和jnz的花指令跳过,E8是垃圾指令,忽略即可

把中间的花指令nop掉,下面的代码直接P恢复即可

使用F5查看

一个伪随机,种子是0xDEADBEEF,编译环境是MSVC,所以找对应的伪随机就行

import ctypes # MSVC rand() implementationclass MSVCRand:    def __init__(self, seed):        self.state = seed     def rand(self):        self.state = (self.state * 214013 + 2531011) & 0xFFFFFFFF        return (self.state >> 16) & 0x7FFF target = [0x51, 0x7D, 0xE1, 0x4C, 0x43, 0x8A, 0xDE, 0xDC, 0x48, 0x8F,          0x07, 0xE2, 0x1F, 0xC0, 0x42, 0x0D, 0xAE, 0xEE, 0x79, 0x99,          0xDA, 0x53, 0x74, 0x5A, 0xF7, 0x5F, 0x14, 0xF9, 0xBC, 0x01,          0xDA, 0x77, 0x9F, 0xD5, 0xE3, 0x4E, 0x65, 0x02, 0xE9, 0x2A] rng = MSVCRand(0xDEADBEEF)result = list(target) for i in range(0, 40, 2):    v3 = rng.rand()    r = v3 % 255    a = result[i]    b = result[i + 1]  # Reverse: a ^= b    a = a ^ b  # Reverse: b -= a ^ r  =>  b += a ^ r    b = (b + (a ^ r)) & 0xFF  # Reverse: a += r  =>  a -= r    a = (a - r) & 0xFF    result[i] = a    result[i + 1] = b flag = ''.join(chr(c) for c in result)print(flag)

DASCTF{ae457007d86e4509587fc27fa32e3ce3}

Crypt

重复密钥异或

from&nbsp;math&nbsp;import&nbsp;gcd&nbsp;hex_output =&nbsp;'2899d080c62a8379947adb554e92c83f1df96b54e1e6f4a20d9b7994768c544b96c03d1cfb695aa5c782c12fac5ad82ada594a98ca3c15fb355ebebbfaf75bc87dc02ada551d99cf381df9345cbcb5bed62dab5ff70996094b94ce3617f83d5ce0b1a5aa559d2b932e8e094b98993712fc355ee1b3a7a411bc5df00cb92a07c4cf3a13f23f5fe8b3fba00ac025c678dd0d1fc4cf3644f33a5be0b1faa208ce61e70ebe2f28e7836a12fe3b55eab0f3a254ca7a9b76885b4cc09b6a12f26c54efb4fba055c8789532a92d2fe2ac495eae3a59eebaf1a15cc8249129d5551996c86e46ae3a55b9bbf4a554ca25932bdb1138e0ab4c718d7609efb6f5ab5ecb2c9377df0a44989d3815aa6e09efbaa2aa5bcf249176dd084adcbc4e7688592aa3e6f4a75ac12e907fdd544ec7c03640fc3d0dbbe6f4ab0dc02b9477df554cc5ce72618a5e2f8cc5b8f75bcd2a9a7dde5c4c99ca691df2685be8e2a0f75bc17d9b78da544e98c86b13b6492d8bc097d4179d2b9679d45e4f91c83717ad3555bdb4f3f30f9d2b9a2ed55b4b99ca3615af3b119cc290d138be67c678d85a4593cb3f15f33f0ae0baa6a55c997fc678d40d4496cf3717f23d08eefe87d33fbb48e534885b4997c13d16fb3d54eae5fbab09cf2cc22c885b45c0c03812f33f55e8e7f5ef28b94fe01bab171996cd391cf93e5ce8bbf1f454c179947f8c0f1996c16e1dfc3a54eabaf3f65a8558e21cae383ada9d3810fd345eebb3f3aa5e9e249a2ada5c1dc29d381caa355befbbf1ab5c9c2ade0bac3f3ff5be7440fc385ae1b1f0a25cc02ec577d4094b91996c40fc340de0b4f4aa5ec12cc77990283df2bb5b63b0685bedb5faa05fc82c9b7d8b5445c4cf3f44a8685be1e2fba55bc02e9a7f895a01e5b95c669f4b17bdb4f6a455ca2f937fd55e1a99c16a12fb6c0fbdb4faf354cf2b9b7dd45c1897854b64984e389ef8a6a559ce25917cdd5c44939e371cae3a5cb9e0a6a55599249478d55e45919c39588f4c3f9bd785e909cf299576df5f4c91c03d43f33409efb3a2f109cf25c277da5b4493c13f41fd70'O =&nbsp;bytes.fromhex(hex_output)&nbsp;for&nbsp;L, K&nbsp;in&nbsp;[(40,&nbsp;19), (19,&nbsp;40)]:&nbsp; &nbsp;&nbsp;print(f'\\nTrying L={L}&nbsp;(flag_len), K={K}&nbsp;(key_len)...')&nbsp; &nbsp; R = [None] * K&nbsp; &nbsp; F = [None] * L&nbsp;&nbsp;# Known prefix&nbsp; &nbsp; prefix =&nbsp;'DASCTF{'&nbsp; &nbsp;&nbsp;for&nbsp;i, ch&nbsp;in&nbsp;enumerate(prefix):&nbsp; &nbsp; &nbsp; &nbsp; F[i] =&nbsp;ord(ch)&nbsp;&nbsp;# Recover R from known F&nbsp; &nbsp;&nbsp;for&nbsp;t&nbsp;in&nbsp;range(len(O)):&nbsp; &nbsp; &nbsp; &nbsp; i = t % L&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;F[i]&nbsp;is&nbsp;not&nbsp;None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = t % K&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val = O[t] ^ F[i]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;R[j]&nbsp;is&nbsp;None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; R[j] = val&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;R[j] != val:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f' &nbsp;Inconsistency at R[{j}]:&nbsp;{R[j]}&nbsp;vs&nbsp;{val}')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;None&nbsp;in&nbsp;R:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f' &nbsp;Missing R bytes:&nbsp;{[j&nbsp;for&nbsp;j,v&nbsp;in&nbsp;enumerate(R)&nbsp;if&nbsp;v&nbsp;is&nbsp;None]}')&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp;&nbsp;# Recover F from R&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;t&nbsp;in&nbsp;range(len(O)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i = t % L&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;F[i]&nbsp;is&nbsp;None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = t % K&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; F[i] = O[t] ^ R[j]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag =&nbsp;''.join(chr(c)&nbsp;if&nbsp;32&nbsp;<= c <&nbsp;127&nbsp;else&nbsp;'?'&nbsp;for&nbsp;c&nbsp;in&nbsp;F)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f' &nbsp;Flag:&nbsp;{flag}')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f' &nbsp;Hex:&nbsp;{bytes(F).hex()}')

Misc

题目:小明忘记了自己的WIFI密码,但是他知道密码很简单。

俩流量包,一个哥斯拉?一个WIFI流量,直接看WIFI流量就行

直接搜索eapol

对应M1和M2,提取关键数据

另外,又找了一个更直观的讲key_info的表补充讲解:

802.11这块我自己原来也没学明白,所以补习了一下

一般来说,WIFI连接( WPA2-PSK 算法)分四次握手,简称M1/M2/M3/M4,过程中涉及到的设备有AP(路由器)和STA(连接设备)

这里就以 WPA2-PSK 举个例子,讲一下WIFI的正常算法:

用户密码password->(PBKDF2+SSID+4096次迭代)->PMK(32字节主密钥,长期不变,存在AP和STA里,注意,PMK不是直接加密数据用的,可以理解为一个ID一样的东西)->每次连接协商一个临时的PTK->利用PTK的不同部分进行不同操作(包括完整性校验、密钥下发、加密单播数据等)

这里就需要记住,密码(对应唯一PMK)、加密“ID”(对应唯一PTK)、KCK校验值(PTK前16位)这三个东西就行,大致流程如下:

细节就不在这里写了,太多了,大概意思就是,我要知道密码,我就得要PMK,PMK可以用PTK反推,KCK是PTK的前16位,MIC又是KCK算出来的。经历这么一长串,也就是说,在ANonce和SNonce已知的情况下,MIC可以认作密码通过一种诡异的“签名算法”算出来的唯一值,当我们使用正确密码算这个的时候,是能够算出来唯一值与之对应的。这也就是为什么这道题能够直接爆破

有了上面的依据,直接开爆破就行,爆出来之后可以用wireshark解密试一下(我流量分析不咋地,Misc的这种脚本让我自己写是真写不出来。,还得是AI)

”””WPA/WPA2-PSK 四次握手爆破脚本(通用版)用法:&nbsp; &nbsp; python wp4crack.py -c Wifi.cap -w wordlist.txt [-s SSID]依赖:&nbsp; &nbsp; pip install scapy&nbsp; &nbsp; pip install pycryptodome&nbsp;# 仅当遇到 Version=3 的 AES-CMIC 时才需要”””import&nbsp;hashlib, hmac, sys, os, time, argparsefrom&nbsp;scapy.all&nbsp;import&nbsp;*&nbsp;def&nbsp;safe_print(s):&nbsp; &nbsp; sys.stdout.buffer.write((str(s) + ”\n”).encode(”utf-8”, errors=”replace”))&nbsp;# ---------- 解析单个 EAPOL-Key 帧 ----------def&nbsp;parse_eapol_key(pkt):&nbsp; &nbsp; raw =&nbsp;bytes(pkt[EAPOL])&nbsp; &nbsp; key_info =&nbsp;int.from_bytes(raw[5:7], ”big”)&nbsp; &nbsp; replay =&nbsp;int.from_bytes(raw[9:17], ”big”)&nbsp;&nbsp;&nbsp;# 优先用 scapy 的 EAPOL_KEY 层(内部已按规范处理好偏移),失败再 fallback 到手算&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; ek = pkt[EAPOL_KEY]&nbsp; &nbsp; &nbsp; &nbsp; key_nonce =&nbsp;bytes(ek.key_nonce)&nbsp; &nbsp; &nbsp; &nbsp; key_mic &nbsp; =&nbsp;bytes(ek.key_mic)&nbsp; &nbsp;&nbsp;except&nbsp;Exception:&nbsp; &nbsp; &nbsp; &nbsp; key_nonce = raw[17:49]&nbsp; &nbsp; &nbsp; &nbsp; key_mic &nbsp; = raw[81:97]&nbsp;&nbsp; &nbsp;&nbsp;return&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; ”raw”: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raw,&nbsp; &nbsp; &nbsp; &nbsp; ”key_info”: &nbsp; &nbsp; &nbsp;key_info,&nbsp; &nbsp; &nbsp; &nbsp; ”key_ack”: &nbsp; &nbsp; &nbsp; (key_info >>&nbsp;7) &&nbsp;1,&nbsp; &nbsp; &nbsp; &nbsp; ”key_mic_bit”: &nbsp; (key_info >>&nbsp;8) &&nbsp;1,&nbsp; &nbsp; &nbsp; &nbsp; ”install”: &nbsp; &nbsp; &nbsp; (key_info >>&nbsp;6) &&nbsp;1,&nbsp; &nbsp; &nbsp; &nbsp; ”version”: &nbsp; &nbsp; &nbsp; key_info &&nbsp;0x7,&nbsp; &nbsp; &nbsp; &nbsp; ”replay”: &nbsp; &nbsp; &nbsp; &nbsp;replay,&nbsp; &nbsp; &nbsp; &nbsp; ”nonce”: &nbsp; &nbsp; &nbsp; &nbsp; key_nonce,&nbsp; &nbsp; &nbsp; &nbsp; ”mic”: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key_mic,&nbsp; &nbsp; &nbsp; &nbsp; ”addr1”: &nbsp; &nbsp; &nbsp; &nbsp; pkt[Dot11].addr1,&nbsp; &nbsp; &nbsp; &nbsp; ”addr2”: &nbsp; &nbsp; &nbsp; &nbsp; pkt[Dot11].addr2,&nbsp; &nbsp; &nbsp; &nbsp; ”addr3”: &nbsp; &nbsp; &nbsp; &nbsp; pkt[Dot11].addr3,&nbsp; &nbsp; }&nbsp;# ---------- 按 replay counter 把 M1/M2 配对 ----------def&nbsp;find_handshake_pairs(pkts):&nbsp; &nbsp; frames = [parse_eapol_key(p)&nbsp;for&nbsp;p&nbsp;in&nbsp;pkts&nbsp;if&nbsp;EAPOL&nbsp;in&nbsp;p]&nbsp;&nbsp; &nbsp; m1_by_replay = {}&nbsp;# replay -> M1 frame&nbsp; &nbsp; pairs = []&nbsp;&nbsp; &nbsp;&nbsp;for&nbsp;f&nbsp;in&nbsp;frames:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;f[”key_ack”] ==&nbsp;1&nbsp;and&nbsp;f[”key_mic_bit”] ==&nbsp;0:&nbsp;&nbsp;# 这是 M1(或 M3 如果 install=1 且 mic=1,否则 M1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m1_by_replay.setdefault(f[”replay”], f)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;f[”key_ack”] ==&nbsp;0&nbsp;and&nbsp;f[”key_mic_bit”] ==&nbsp;1:&nbsp;&nbsp;# M2 或 M4(STA 发的带 MIC 帧)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m1 = m1_by_replay.get(f[”replay”])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;m1:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pairs.append((”M1+M2”, m1, f))&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;f[”key_ack”] ==&nbsp;1&nbsp;and&nbsp;f[”key_mic_bit”] ==&nbsp;1:&nbsp;&nbsp;# M3(AP 发的带 MIC 帧)— 也可以爆破,把它当作”M1”,配对自身算&nbsp;&nbsp;# 这里把它也存进候选,供后续单独爆破用&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pass&nbsp;&nbsp;# M3+M4 的爆破稍麻烦(M4 通常不含需验证的数据,但 M3 本身可以单独验证)&nbsp; &nbsp;&nbsp;return&nbsp;pairs, frames&nbsp;# ---------- 自动从 Beacon/ProbeResp 找 BSSID 对应的 SSID ----------def&nbsp;find_ssid(pkts, bssid):&nbsp; &nbsp;&nbsp;for&nbsp;p&nbsp;in&nbsp;pkts:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(Dot11Beacon&nbsp;in&nbsp;p&nbsp;or&nbsp;Dot11ProbeResp&nbsp;in&nbsp;p)&nbsp;and&nbsp;p[Dot11].addr3 == bssid:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elt = p[Dot11Elt]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;while&nbsp;elt&nbsp;and&nbsp;isinstance(elt, Dot11Elt):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;elt.ID ==&nbsp;0:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;elt.info.decode(”ascii”, errors=”replace”)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elt = elt.payload&nbsp; &nbsp;&nbsp;return&nbsp;None&nbsp;# ---------- 密钥派生 ----------def&nbsp;compute_ptk(pmk, ap_mac, sta_mac, anonce, snonce):&nbsp; &nbsp; A = b”Pairwise key expansion”&nbsp; &nbsp; B = (min(ap_mac, sta_mac) +&nbsp;max(ap_mac, sta_mac)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+&nbsp;min(anonce, snonce) +&nbsp;max(anonce, snonce))&nbsp; &nbsp; ptk = b””&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(4):&nbsp; &nbsp; &nbsp; &nbsp; ptk += hmac.new(pmk, A + b”\x00” + B +&nbsp;bytes([i]), hashlib.sha1).digest()&nbsp; &nbsp;&nbsp;return&nbsp;ptk[:64]&nbsp;def&nbsp;compute_mic(kck, eapol_zeroed, version):&nbsp; &nbsp;&nbsp;if&nbsp;version ==&nbsp;1:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;hmac.new(kck, eapol_zeroed, hashlib.md5).digest()&nbsp; &nbsp;&nbsp;elif&nbsp;version ==&nbsp;2:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;hmac.new(kck, eapol_zeroed, hashlib.sha1).digest()[:16]&nbsp; &nbsp;&nbsp;elif&nbsp;version ==&nbsp;3:&nbsp;&nbsp;# AES-128-CMAC,标准库没,用 pycryptodome&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;from&nbsp;Crypto.MAC&nbsp;import&nbsp;CMAC&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;from&nbsp;Crypto.Cipher&nbsp;import&nbsp;AES&nbsp; &nbsp; &nbsp; &nbsp; c = CMAC.new(kck, ciphermod=AES)&nbsp; &nbsp; &nbsp; &nbsp; c.update(eapol_zeroed)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;c.digest()[:16]&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;raise&nbsp;RuntimeError(f”未知 key_descriptor_version={version}”)&nbsp;# ---------- 用 scapy 的 key_mic 字段长度定位偏移 ----------def&nbsp;find_mic_offset(eapol_bytes):&nbsp;&nbsp;# 标准 802.11i 终稿: offset 81;早期 WPA1 (KeyLength 1字节): offset 80&nbsp;&nbsp;# 简单判断 EAPOL 帧的整体长度——配合 key_data_length 来反推更稳&nbsp;&nbsp;# 这里就用标准 81;如果 MIC 全零且尝试反复不对,再试 80&nbsp; &nbsp;&nbsp;return&nbsp;81&nbsp;def&nbsp;try_password(password, ssid, ap_mac, sta_mac, anonce, snonce,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_eapol, captured_mic, version, mic_offset=81):&nbsp; &nbsp; pmk = hashlib.pbkdf2_hmac(”sha1”, password.encode(), ssid.encode(),&nbsp;4096,&nbsp;32)&nbsp; &nbsp; ptk = compute_ptk(pmk, ap_mac, sta_mac, anonce, snonce)&nbsp; &nbsp; kck = ptk[:16]&nbsp; &nbsp; eapol_zeroed =&nbsp;bytearray(m_eapol)&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(16):&nbsp; &nbsp; &nbsp; &nbsp; eapol_zeroed[mic_offset + i] =&nbsp;0&nbsp; &nbsp; mic = compute_mic(kck,&nbsp;bytes(eapol_zeroed), version)&nbsp; &nbsp;&nbsp;return&nbsp;mic == captured_mic&nbsp;# ---------- 主流程 ----------def&nbsp;main():&nbsp; &nbsp; ap = argparse.ArgumentParser()&nbsp; &nbsp; ap.add_argument(”-c”, ”--cap”, &nbsp; &nbsp; &nbsp;required=True,&nbsp;help=”抓包文件 .cap/.pcap”)&nbsp; &nbsp; ap.add_argument(”-w”, ”--wordlist”, required=True,&nbsp;help=”字典文件”)&nbsp; &nbsp; ap.add_argument(”-s”, ”--ssid”, &nbsp; &nbsp;help=”手动指定 SSID(缺省自动从 Beacon 提取)”)&nbsp; &nbsp; args = ap.parse_args()&nbsp;&nbsp; &nbsp; pkts = rdpcap(args.cap)&nbsp; &nbsp; safe_print(f”读 {args.cap}: {len(pkts)} 个包”)&nbsp;&nbsp; &nbsp; pairs, all_frames = find_handshake_pairs(pkts)&nbsp; &nbsp; safe_print(f”找到 {len(pairs)} 对 M1+M2”)&nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;pairs:&nbsp; &nbsp; &nbsp; &nbsp; safe_print(”没有可用 M1+M2 对,无法爆破”);&nbsp;return&nbsp;1&nbsp;&nbsp; &nbsp; _, m1, m2 = pairs[0]&nbsp; &nbsp; ap_mac &nbsp;=&nbsp;bytes(int(b,&nbsp;16)&nbsp;for&nbsp;b&nbsp;in&nbsp;m1[”addr2”].split(”:”))&nbsp; &nbsp; sta_mac =&nbsp;bytes(int(b,&nbsp;16)&nbsp;for&nbsp;b&nbsp;in&nbsp;m2[”addr2”].split(”:”))&nbsp; &nbsp; anonce, snonce = m1[”nonce”], m2[”nonce”]&nbsp; &nbsp; captured_mic, version = m2[”mic”], m2[”version”]&nbsp; &nbsp; m2_raw = m2[”raw”]&nbsp;&nbsp; &nbsp; ssid = args.ssid&nbsp;or&nbsp;find_ssid(pkts, m1[”addr2”])&nbsp;or&nbsp;””&nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;ssid:&nbsp; &nbsp; &nbsp; &nbsp; safe_print(”无法自动提取 SSID,请用 -s 指定”);&nbsp;return&nbsp;1&nbsp; &nbsp; safe_print(f”SSID &nbsp;= {ssid}”)&nbsp; &nbsp; safe_print(f”AP &nbsp; &nbsp;= {m1['addr2']} &nbsp; &nbsp;STA = {m2['addr2']}”)&nbsp; &nbsp; safe_print(f”MIC &nbsp; = {captured_mic.hex()} &nbsp; &nbsp;Version = {version}”)&nbsp;&nbsp; &nbsp;&nbsp;with&nbsp;open(args.wordlist, ”r”, encoding=”utf-8”, errors=”replace”)&nbsp;as&nbsp;f:&nbsp; &nbsp; &nbsp; &nbsp; words = [w.strip()&nbsp;for&nbsp;w&nbsp;in&nbsp;f&nbsp;if&nbsp;w.strip()]&nbsp; &nbsp; safe_print(f”\n字典 {len(words)} 词,开始爆破”)&nbsp;&nbsp; &nbsp; t0 = time.time()&nbsp; &nbsp; mic_offset = find_mic_offset(m2_raw)&nbsp;&nbsp; &nbsp;&nbsp;for&nbsp;i, pwd&nbsp;in&nbsp;enumerate(words):&nbsp; &nbsp; &nbsp; &nbsp; ok = try_password(pwd, ssid, ap_mac, sta_mac,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anonce, snonce, m2_raw,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; captured_mic, version, mic_offset)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;ok:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elapsed = time.time() - t0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; safe_print(f”\n*** KEY FOUND: {pwd} ***”)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; safe_print(f”耗时 {elapsed:.2f}s”)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;0&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;i&nbsp;and&nbsp;i %&nbsp;500&nbsp;==&nbsp;0:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rate = i / (time.time() - t0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; safe_print(f” &nbsp;进度 {i}/{len(words)} &nbsp;速率 {rate:.1f} pwd/s”)&nbsp;&nbsp; &nbsp; safe_print(f”字典跑完未命中,耗时 {time.time()-t0:.2f}s”)&nbsp; &nbsp;&nbsp;return&nbsp;1&nbsp;if&nbsp;__name__ == ”__main__”:&nbsp; &nbsp; sys.exit(main())

密码是password(确实对上了题干:密码很简单),哥斯拉那个没看,不知道有啥用



碎碎念:

原来参加比赛是看谁准备的脚本多,谁脑子好使分析的快,有能力的抢枪一血,差一点的的做出来就行。

现在就看谁的本地模型好用,谁的harness能够发挥极限实力了。

AI发展的快,现在内部比武都开始库库用AI做题了,估计明年自动化一套都出来了。

个人感觉这个倒不是坏事,原来是“一台电脑一根烟,一个框架看一天”,现在AI能干的我躺着就好了,必要时按两下键盘再加个回车。

只是希望能够不忘初心吧,比赛归比赛,不要让AI这个“工具”吞噬了对未知探索的欲望~


最后是附件

https://peng1ai.lanzouv.com/iy1Yb40t4t4b

密码:cfm5


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:AI丽丝的人偶工坊 蓬莱人形 蓬莱人形《2026年山东省某市网络安全职业技能大赛(含题目、WP)》

评论:0   参与:  0