戰(zhàn))
前陣子帶著一批入門MISC的選手刷題我發(fā)現(xiàn)一個(gè)特別有意思的現(xiàn)象流量包分析在很多人眼里是最“勸退”的題型——一個(gè)幾十MB的pcap文件扔過來Wireshark打開滿屏都是包根本不知道從哪起手。但刷到后面大家都會(huì)認(rèn)同一個(gè)結(jié)論流量包題目難不在技術(shù)而在“信息定位”。出題人把flag藏來藏去無非是那么幾個(gè)地方你只要掌握對(duì)應(yīng)的提取思路再配合Python腳本去做重復(fù)勞動(dòng)效率和正確率都能上來一大截。這篇文章我把最近實(shí)戰(zhàn)中總結(jié)的5種隱藏技巧完整拆開來講從HTTP響應(yīng)里的圖片尾巴到DNS請(qǐng)求里的一串可疑字符再到TCP流中手撿文件頭每一個(gè)都會(huì)給出可以直接復(fù)用的Python腳本。適合正在準(zhǔn)備CTF比賽、想進(jìn)階MISC方向的選手也適合做流量分析但想提升效率的安全工程師。文章里所有腳本都是我在實(shí)際刷題環(huán)境里剪出來改過的能跑、能改照著抄基本就能應(yīng)對(duì)大半流量包題目。1. 先摸清流量包里藏信息的三種路子流量分析題能玩的點(diǎn)其實(shí)繞不開三類信息載體。先把這三類搞清楚做題的時(shí)候就有了地圖看到一個(gè)pcap不會(huì)兩眼一抹黑。1.1 文件對(duì)象、協(xié)議元數(shù)據(jù)、載荷暗語(yǔ)這三類信息載體第一類是文件對(duì)象。HTTP協(xié)議在傳輸過程中最常見的載荷就是文件——圖片、壓縮包、PDF、甚至直接就是一段exe。這些文件通過HTTP響應(yīng)體傳過來肉眼在Wireshark里看不到完整結(jié)構(gòu)但用工具提取出來后可以做文件層面的隱寫分析。很多題目的flag不是直接寫在包里的而是藏在某個(gè)被傳輸?shù)膱D片的LSB位里或者附加在文件尾部。所以看到HTTP上傳下載的痕跡第一反應(yīng)就是“把文件撈出來”。第二類是協(xié)議元數(shù)據(jù)。不需要看載荷內(nèi)容光看協(xié)議字段本身就能藏信息。最典型的就是DNS查詢里的子域名出題人把編碼后的flag拆成一段段子域名字符串塞進(jìn)DNS請(qǐng)求里還有HTTP的頭部字段、TCP的序列號(hào)、TLS握手的SNI字段都有被改寫的可能。這類信息的特征是“藏得淺但隱蔽”因?yàn)橐话惴治稣邞械弥饤l看協(xié)議字段。第三類是載荷暗語(yǔ)。TCP或UDP的payload可能是一整段經(jīng)過編碼的字符串比如base64、十六進(jìn)制或者直接就是一段加密后的密文需要先解碼、再解密、再分析。有些題目甚至直接把壓縮包拆成多個(gè)切片分散在多個(gè)包里需要按序拼回去。這一類最考驗(yàn)解碼和恢復(fù)能力也是腳本發(fā)揮最大價(jià)值的地方。1.2 為什么用 Python Scapy而不是純 WiresharkWireshark當(dāng)然適合做人工邏輯分析它的圖形界面、過濾器、Follow TCP Stream都是神器。但它有兩個(gè)痛點(diǎn)一是大pcap文件手動(dòng)點(diǎn)著找太慢二是重復(fù)性的提取操作每次都重新點(diǎn)一遍就很折磨。所以我一般的主流程是用Wireshark做第一輪“人眼偵查”確認(rèn)可疑方向后再用Python的Scapy或者dpkt庫(kù)做第二輪批量挖掘。Scapy的rdpcap能把整個(gè)pcap讀成包列表每個(gè)包都能按層去索引比如pkt[TCP].payload直接拿TCP載荷配合pkt[IP].src、pkt[DNS].qd.qname這些字段就能快速過濾。如果你更喜歡命令行的方式tshark做文本導(dǎo)出也很順手但遇到復(fù)雜的解碼、重組邏輯最終還是Python順手。關(guān)于工具鏈建議安裝Scapy、PillowPIL、pyzipper這三個(gè)庫(kù)就夠了后面腳本都基于它們。解析大部分pcap和圖片隱寫操作都不用額外再裝什么重型依賴。2. 從流量包摳flag的5種隱藏技巧這五種技巧是我從一類類題目里篩出來的基本是流量包MISC題里出現(xiàn)頻率最高的五種藏法。每一種我都會(huì)講清楚“藏在哪里”、“怎么發(fā)現(xiàn)”、“怎么提取”有基礎(chǔ)的朋友可以直接跳到對(duì)應(yīng)小節(jié)看腳本思路。2.1 技巧一HTTP響應(yīng)里的文件先提取再檢查圖片尾巴和LSB這種題目的pcap里會(huì)有一個(gè)明顯的HTTP GET請(qǐng)求請(qǐng)求某個(gè)圖片或者壓縮包響應(yīng)體里就是這個(gè)文件。難點(diǎn)從來不在“拿到文件”而在于“拿到文件之后做什么”。我的標(biāo)準(zhǔn)流程是這樣的先用tshark把HTTP響應(yīng)里的文件數(shù)據(jù)導(dǎo)出來或者用Python腳本遍歷HTTP層抓http.file_data字段。拿到文件后先用file命令看真實(shí)類型用binwalk掃一遍有沒有附加數(shù)據(jù)再用strings拽一遍看有沒有明文字符串。如果這三步都沒有結(jié)果就要對(duì)圖片本身做隱寫分析檢查尾部是否被追加了數(shù)據(jù)處理LSB隱寫留意EXIF信息或PNG的tEXt注釋塊。我實(shí)際遇到過一道題pcap里傳輸了一張PNG表面上看是一張普通的二維碼。但binwalk顯示文件尾部有額外數(shù)據(jù)把尾部的一段十六進(jìn)制轉(zhuǎn)ASCII后直接就是flag{...}。這種屬于出題人給你送的溫暖。更常見的是尾部沒有額外數(shù)據(jù)但圖片用StegSolve打開后在Red plane 0、Green plane 0通道能看到一行若隱若現(xiàn)的字符這就是LSB隱寫。處理這類情況建議優(yōu)先用zsteg工具一鍵檢測(cè)比手動(dòng)提取RGB值快得多。這個(gè)技巧的核心經(jīng)驗(yàn)是不要在拿到文件的那一刻就以為題做完了文件本身就是分析對(duì)象。2.2 技巧二DNS查詢子域名里的變形字符串DNS請(qǐng)求里藏?cái)?shù)據(jù)在真實(shí)攻擊中也存在攻擊者會(huì)把竊取的數(shù)據(jù)拆成一段段字符串放在域名前綴里發(fā)出去繞過高延遲的HTTP通道。CTF題目里直接把這種思路改成了“把flag編碼后藏在子域名里”。分析方法第一步是過濾出所有DNS查詢請(qǐng)求也就是dns.qr 0的包。然后在Wireshark里看dns.qname字段如果你發(fā)現(xiàn)大量請(qǐng)求指向同一個(gè)根域名但每個(gè)請(qǐng)求的子域名部分是一串無意義字符基本就是中招了。這時(shí)候把子域名前綴全部拼接到一起再根據(jù)字符集形態(tài)選擇解碼方式。解碼方式的選擇是有門道的如果拼接后的字符串全是十六進(jìn)制字符0-9和a-f第一優(yōu)先嘗試hex解碼如果字符串長(zhǎng)度是32的倍數(shù)、字符集包含大寫字母A-Z和數(shù)字2-7那就是base32用Python的base64.b32decode直接解如果是大小寫混合的base64要注意DNS解析會(huì)把域名統(tǒng)一轉(zhuǎn)成小寫所以原大寫字母會(huì)被破壞這種情況下可以觀察字符串是否包含/等base64特征字符如果包含就嘗試手動(dòng)補(bǔ)全大小寫后再做base64解碼。我遇到的一道練習(xí)題比較常規(guī)域名是example.com前綴是幾段等長(zhǎng)的字符串拼接后長(zhǎng)度能被8整除通過base32解碼直接拿到了flag。還有一道進(jìn)階題把flag分成了多段放到了多次DNS請(qǐng)求里順序不是按時(shí)間排列的還需要根據(jù)請(qǐng)求序號(hào)或者子域名里的序號(hào)字段重新排序這個(gè)坑要在做題時(shí)特別注意。2.3 技巧三TCP流里手撿magic number提文件有些題目不走HTTP直接把一個(gè)文件拆成原始數(shù)據(jù)塞進(jìn)TCP流里。這時(shí)候Wireshark的“Follow TCP Stream”雖然能看內(nèi)容但文件是二進(jìn)制的話界面里全是亂碼得依賴腳本做自動(dòng)提取。我從實(shí)戰(zhàn)中總結(jié)出來一個(gè)很實(shí)用的搜索思路遍歷pcap中所有TCP載荷然后用Python的bytes.find()在整段拼接后的流數(shù)據(jù)里搜索各種文件頭特征也叫magic number。比如PK開頭的是ZIP壓縮包\x89PNG\r\n\x1a\n是PNG圖片\xff\xd8\xff是JPEG%PDF是PDF文檔7z\xbc\xaf\x27\x1c是7z壓縮包。一旦命中就把從這個(gè)位置開始的文件數(shù)據(jù)切出來保存。但這個(gè)操作有個(gè)隱含的坑TCP是流協(xié)議同一個(gè)連接的數(shù)據(jù)包可能在傳輸過程中亂序還可能重傳。如果直接按pcap里的包順序拼接數(shù)據(jù)提取出來的文件大概率是壞的。正確做法是以四元組源IP、源端口、目的IP、目的端口為維度做流重組并且按TCP序列號(hào)排序后再拼。腳本里我會(huì)用字典按流存數(shù)據(jù)、再按seq排序這樣提取出的文件才是完整的。如果提取出來的是加密ZIP就進(jìn)入下一個(gè)常見的處理鏈路先用zipfile測(cè)試是否能直接解壓如果不能去pcap里搜口令——這里就引出后面的技巧五了。2.4 技巧四兩張圖做像素運(yùn)算還原flag流量里出現(xiàn)兩張大小一致、肉眼看起來完全相同的圖片這種題目的flag通常就藏在“兩張圖的差別”里。常見的操作包括異或、相減、疊加、灰度通道拆分等。原理其實(shí)很簡(jiǎn)單如果出題人把一張干凈的圖片跟一張寫有flag的圖片做了異或處理得到的結(jié)果就是一張充滿噪點(diǎn)的“密圖”。解題時(shí)把那兩張?jiān)紙D重新做異或噪點(diǎn)會(huì)抵消flag信息就浮現(xiàn)出來了。做題的人只需要把兩張圖逐像素取出RGB值按位置做異或運(yùn)算再把結(jié)果寫回一張新圖片即可。我自己寫腳本的時(shí)候優(yōu)先用Pillow庫(kù)通過Image.open()讀取getdata()拿到全部像素再用生成器表達(dá)式做運(yùn)算最后putdata()寫回。這里必須注意兩點(diǎn)一是圖片尺寸必須一致否則逐像素運(yùn)算會(huì)報(bào)錯(cuò)如果不一致可以先用resize()統(tǒng)一尺寸二是通道數(shù)要一致有些圖是RGBA四通道直接跟RGB三通道做異或會(huì)出問題需要先轉(zhuǎn)成RGBA或者RGB格式。還有一種變體題目是兩張圖中一張是原始圖另一張是附加了flag的噪點(diǎn)圖直接相減就能出結(jié)果。這時(shí)候可以把自己的運(yùn)算函數(shù)參數(shù)化成op模式靈活選擇XOR、SUB、ADD三種運(yùn)算。2.5 技巧五加密壓縮包的口令藏在會(huì)話或其他載荷里流量包題里提取出ZIP后往往發(fā)現(xiàn)它是加密的這時(shí)候如果直接上爆破效率低不說成功率也不高。出題人不可能弄一個(gè)高強(qiáng)度密碼讓你硬剛密碼幾乎一定藏在pcap的某個(gè)角落。我常用的檢索方式是遍歷所有包的payload把可打印字符串提取出來然后用正則搜索包含password、pass、key、口令、密碼這些關(guān)鍵詞的上下文。很多時(shí)候密碼就在一段聊天流量里比如IRC消息、HTTP POST參數(shù)、或者某人通過FTP傳的txt文件里。也有變態(tài)一點(diǎn)的題目密碼被拆成幾段分散在多個(gè)UDP包的載荷末尾需要先拼出來再用。判斷加密方式是另一個(gè)關(guān)鍵細(xì)節(jié)傳統(tǒng)ZipCrypto加密的ZIP標(biāo)準(zhǔn)庫(kù)zipfile可以嘗試用密碼解壓但如果ZIP使用的是AES加密特征是壓縮包里有AES標(biāo)志zipfile不支持需要改用pyzipper庫(kù)。我第一次遇到AES加密ZIP時(shí)在zipfile上報(bào)RuntimeError: File is encrypted換到pyzipper后用同樣密碼秒解。還有一個(gè)實(shí)用信息有些加密ZIP會(huì)有一個(gè)明文“提示”文件比如注釋里寫了“密碼是生日”那就要關(guān)注流量里的日期信息如果寫了“密碼是MAC地址”那就去看ARP或DHCP包里的MAC信息。出題人不會(huì)無緣無故寫提示看到就直接去對(duì)應(yīng)位置找。3. 能直接跑的Python腳本集這部分直接放代碼。所有腳本我都拆成了獨(dú)立函數(shù)你完全可以只拷貝自己需要的部分pcap路徑改成自己的文件名就能跑。3.1 pcap讀取與流重組框架讀pcap最基礎(chǔ)的就是rdpcap但大文件容易內(nèi)存爆掉這時(shí)候建議用PcapReader做流式讀取一個(gè)包一個(gè)包地處理既能控內(nèi)存又能做流重組。下面這個(gè)函數(shù)會(huì)把整個(gè)pcap里的TCP載荷按四元組拆分、按序列號(hào)排序最終返回每個(gè)TCP流的完整字節(jié)流。from scapy.all import PcapReader, TCP, IP def reassemble_tcp_streams(pcap_path): streams {} with PcapReader(pcap_path) as packets: for pkt in packets: if not (pkt.haslayer(TCP) and pkt[TCP].payload): continue key ( pkt[IP].src, pkt[TCP].sport, pkt[IP].dst, pkt[TCP].dport ) streams.setdefault(key, []).append( (pkt[TCP].seq, bytes(pkt[TCP].payload)) ) for key, chunks in streams.items(): chunks.sort(keylambda x: x[0]) yield key, b.join(data for _, data in chunks)這個(gè)函數(shù)是用生成器的形式寫好的遍歷的時(shí)候直接for key, data in reassemble_tcp_streams(a.pcap):就可以。排序時(shí)注意只按seq排對(duì)于超大文件的亂序可能需要處理回繞但CTF題目一般不會(huì)考到那么深。3.2 從HTTP流自動(dòng)提取文件HTTP下的提取我建議不要自己寫HTTP解析器直接用Scapy的TCP載荷加簡(jiǎn)單的頭部分割就夠了。下面的腳本會(huì)識(shí)別HTTP響應(yīng)體把文件數(shù)據(jù)摳出來并用HTTP頭里的filename字段作為文件名保存到指定目錄。import os, re from scapy.all import PcapReader, TCP, IP def extract_http_files(pcap_path, outdirfiles): os.makedirs(outdir, exist_okTrue) files {} with PcapReader(pcap_path) as packets: for pkt in packets: if not (pkt.haslayer(TCP) and pkt[TCP].payload): continue payload bytes(pkt[TCP].payload) # 只挑HTTP響應(yīng) if payload.startswith(bHTTP/) or bHTTP/1.1 200 in payload[:40]: headers, _, body payload.partition(b\r\n\r\n) if not body: continue fname_match re.search( rbfilename?([^;])?, headers ) if fname_match: fname fname_match.group(1).decode(errorsignore) files[fname] files.get(fname, b) body elif bContent-Type: image in headers: fname fimg_{len(files)}.dat files[fname] files.get(fname, b) body for name, data in files.items(): with open(os.path.join(outdir, name), wb) as f: f.write(data) return list(files.keys())這個(gè)腳本的局限是它假設(shè)一個(gè)包就是完整的HTTP響應(yīng)體如果文件跨多個(gè)TCP包就要結(jié)合上面的流重組來做。穩(wěn)妥一點(diǎn)是把所有HTTP響應(yīng)流先重組再切分我一般習(xí)慣直接先跑流重組再對(duì)每個(gè)流用相同邏輯提取這樣對(duì)大文件更保險(xiǎn)。3.3 DNS可疑字符串解碼器DNS解碼腳本的核心只有兩步收集所有查詢域名然后剝掉根域名后綴。很多題目的根域名是固定的比如example.com所以我會(huì)把收集到的域名先按最后的兩個(gè)標(biāo)簽去掉剩下前面的標(biāo)簽拼接成一個(gè)字符串再做hex、base32、base64三種嘗試。import base64, binascii from scapy.all import PcapReader, DNS def collect_dns_queries(pcap_path, root_domainexample.com): labels [] with PcapReader(pcap_path) as packets: for pkt in packets: if pkt.haslayer(DNS) and pkt[DNS].qr 0: qname pkt[DNS].qd.qname.decode().rstrip(.) domain . root_domain if qname.endswith(domain): prefix qname[: -len(domain)].replace(., ) labels.append(prefix) return .join(labels) def try_decode(s): # 1. hex try: return fhex - {bytes.fromhex(s).decode(errorsignore)} except ValueError: pass # 2. base32 try: return fbase32 - {base64.b32decode(s.upper()).decode(errorsignore)} except Exception: pass # 3. base64 try: return fbase64 - {base64.b64decode(s * (-len(s) % 4)).decode(errorsignore)} except Exception: pass return no result s collect_dns_queries(dns.pcap) print(s) print(try_decode(s))如果DNS查詢里有多個(gè)不同根域名就把root_domain參數(shù)改成一個(gè)不含的域名或者直接把整段域名拼接起來再試著解碼。有一個(gè)容易被忽略的點(diǎn)DNS請(qǐng)求可能重復(fù)出現(xiàn)重試機(jī)制會(huì)產(chǎn)生相同的查詢所以收集時(shí)用set去重最好。3.4 從TCP流提取magic bytes文件這個(gè)腳本重點(diǎn)展示如何搜索文件頭。我定義了一組常見格式的magic bytes遍歷之前生成的流數(shù)據(jù)用bytes.find定位文件頭然后把文件頭開始處的數(shù)據(jù)全部保存。如果文件長(zhǎng)度未知就先把流尾部到文件頭之間的數(shù)據(jù)都截出來再根據(jù)流結(jié)束位置判斷文件是否完整。MAGIC { zip: bPK\x03\x04, zip_spanned: bPK\x07\x08, png: b\x89PNG\r\n\x1a\n, jpg: b\xff\xd8\xff, pdf: b%PDF, gz: b\x1f\x8b, 7z: b7z\xbc\xaf\x27\x1c, rar: bRar!\x1a\x07, } def extract_by_magic(data, outdirextracted): import os os.makedirs(outdir, exist_okTrue) result [] for name, magic in MAGIC.items(): pos data.find(magic) if pos ! -1: chunk data[pos:] path os.path.join(outdir, fstream_{name}_{len(result)}.bin) with open(path, wb) as f: f.write(chunk) result.append((name, path)) return result # 配合流重組函數(shù)使用 for key, stream_data in reassemble_tcp_streams(capture.pcap): found extract_by_magic(stream_data) for name, path in found: print(key, name, path)搜索出來的文件直接用file命令判斷是否完整如果報(bào)“ truncated”就說明切割長(zhǎng)度不對(duì)需要手動(dòng)調(diào)整。有些圖片文件后面還會(huì)跟著別的數(shù)據(jù)所以切的時(shí)候只取到magic number開始的區(qū)域即可后續(xù)內(nèi)容可以在文件層面繼續(xù)分析。3.5 像素運(yùn)算還原圖片最后這個(gè)函數(shù)用來做像素級(jí)運(yùn)算。傳入兩張圖片路徑和一個(gè)運(yùn)算模式返回運(yùn)算結(jié)果圖片。注意它會(huì)把兩張圖轉(zhuǎn)換成同一個(gè)尺寸和模式再逐像素處理。from PIL import Image def pixel_merge(img1_path, img2_path, opxor, out_pathmerged.png): im1 Image.open(img1_path).convert(RGB) im2 Image.open(img2_path).convert(RGB) if im1.size ! im2.size: im2 im2.resize(im1.size) p1 im1.load() p2 im2.load() out Image.new(RGB, im1.size) po out.load() for y in range(im1.size[1]): for x in range(im1.size[0]): r1, g1, b1 p1[x, y] r2, g2, b2 p2[x, y] if op xor: po[x, y] (r1 ^ r2, g1 ^ g2, b1 ^ b2) elif op sub: po[x, y] (abs(r1 - r2), abs(g1 - g2), abs(b1 - b2)) elif op add: po[x, y] (min(r1 r2, 255), min(g1 g2, 255), min(b1 b2, 255)) else: raise ValueError(unknown op) out.save(out_path)跑起來可能有點(diǎn)慢圖片如果太大的話可以先把尺寸壓小一點(diǎn)或者用NumPy向量化運(yùn)算加速。對(duì)于像素級(jí)隱寫圖片分辨率一般不會(huì)太高純Python循環(huán)也夠用。4. 常見問題與排查竅門實(shí)錄流量包分析翻車最多的不是思路不對(duì)而是細(xì)節(jié)沒處理好。我把刷題和帶人過程中遇到的高頻問題列出來按“現(xiàn)象、原因、解法”的方式整理成速查表方便你卡殼時(shí)快速對(duì)照。4.1 我會(huì)遇到的5個(gè)高頻坑第一個(gè)坑是DNS域名大小寫問題。DNS協(xié)議在傳輸過程中域名會(huì)被統(tǒng)一轉(zhuǎn)成小寫如果出題人用base64編碼flag大小寫字母一混合解碼必掛。我現(xiàn)在的做法是優(yōu)先試hex和base32因?yàn)檫@兩種編碼不依賴大小寫混合能規(guī)避大部分協(xié)議干擾。第二個(gè)坑是TCP亂序。直接用pcap原始順序拼文件經(jīng)常會(huì)拼出損壞文件。不要偷懶一定要按序列號(hào)排序重組。我之前在某個(gè)數(shù)據(jù)包中直接提取ZIP解壓時(shí)報(bào)BadZipFile最后發(fā)現(xiàn)是流重組沒按seq排序片段倒序了。這個(gè)坑很多人都會(huì)踩。第三個(gè)坑是Scapy層解析問題。有時(shí)候pcap文件不是標(biāo)準(zhǔn)的以太網(wǎng)幀比如某些采集環(huán)境是Linux cooked captureSLL封裝這時(shí)候包沒有Ether層直接pkt[IP]會(huì)報(bào)錯(cuò)。我的建議是寫解析腳本時(shí)先判斷pkt.haslayer(IP)再做IP層訪問不要假設(shè)一定有Ethernet。第四個(gè)坑是加密ZIP的AES誤判。zipfile解不開加密包時(shí)不要直接認(rèn)定密碼錯(cuò)誤。先看壓縮包里的加密算法如果提示AE-x這類參數(shù)說明是AES加密必須用pyzipper或7-Zip命令行。我當(dāng)時(shí)在某道題卡了半個(gè)多小時(shí)后來發(fā)現(xiàn)根本原因是用錯(cuò)了解壓庫(kù)。第五個(gè)坑是大pcap內(nèi)存溢出。rdpcap把整個(gè)pcap讀入內(nèi)存如果文件快1GB機(jī)器就會(huì)卡死。優(yōu)先用PcapReader迭代讀取這樣每條包只是臨時(shí)占用內(nèi)存。對(duì)刷題來說基本不會(huì)爆但處理真實(shí)流量樣本時(shí)必須養(yǎng)成這個(gè)習(xí)慣。4.2 排查思路速查表現(xiàn)象可能原因解決思路提取的文件打開后報(bào)損壞TCP流未按序列號(hào)重組按四元組分組后按seq排序再拼接base64解碼出來是亂碼DNS域名被轉(zhuǎn)小寫先嘗試hex、base32或手動(dòng)恢復(fù)大小寫zipfile解壓報(bào)File is encryptedZipCrypto或AES加密用pyzipper或7z命令行確認(rèn)密碼兩張圖片像素運(yùn)算報(bào)錯(cuò)尺寸或通道數(shù)不一致先resize、統(tǒng)一convert模式Scapy訪問IP層報(bào)錯(cuò)pcap基于SLL封裝用pkt.haslayer(IP)做保護(hù)或加載SLL層圖片用StegSolve打開沒東西隱寫不在可見通道用zsteg自動(dòng)掃描LSB檢查圖片尾部數(shù)據(jù)找不到任何文件頭數(shù)據(jù)被編碼后再傳輸先嘗試對(duì)整個(gè)TCP流做base64/hex解碼再搜索DNS子域名拼接后無法解碼請(qǐng)求順序錯(cuò)亂或重復(fù)用請(qǐng)求序號(hào)排序或者用set去重這個(gè)速查表是我實(shí)際使用頻率最高的復(fù)盤清單刷題遇到卡殼時(shí)先查一遍比自己瞎試快得多。我在做流量包題目時(shí)最深的體會(huì)是耐心比技術(shù)重要腳本比肉眼可靠。很多隱藏信息用Wireshark手動(dòng)翻也能看到但一個(gè)大pcap里可能混著幾千個(gè)包手翻既慢又容易漏腳本跑一遍就不會(huì)漏。所以我現(xiàn)在處理流量包的基本套路都是先Wireshark快速定位可疑協(xié)議再用Python腳本做批量提取和重組最后對(duì)提取出的文件做隱寫檢查。這套流程幫我解決了不少難題也希望這篇內(nèi)容能給你省下一些踩坑的時(shí)間。最后分享一個(gè)小經(jīng)驗(yàn)刷流量分析題一定要養(yǎng)成積累腳本的習(xí)慣把HTTP提取、DNS解碼、文件頭搜索這些基礎(chǔ)函數(shù)保存好下次套用就會(huì)很輕松。