別到LSB提取message)
每天都會(huì)在攻防世界刷兩三道題這個(gè)習(xí)慣保持了挺長(zhǎng)一段時(shí)間。“每日好幾練”這個(gè)系列我打算堅(jiān)持寫下去記錄自己踩過(guò)的坑和整理過(guò)的思路。第2篇想聊聊Misc方向重點(diǎn)拆一道關(guān)鍵詞里帶message的圖片題。說(shuō)實(shí)話Misc題在很多新手眼里像開盲盒不知道從哪里下手。但做得多了會(huì)發(fā)現(xiàn)它其實(shí)有非常清晰的套路文件識(shí)別、隱寫檢測(cè)、編碼解碼、上下文推理每一步都有對(duì)應(yīng)的工具和判斷邏輯。今天就把這道題的完整推理過(guò)程連同我做題時(shí)的思考、卡殼和復(fù)盤原原本本寫下來(lái)。不論你是剛開始接觸CTF還是已經(jīng)在刷平臺(tái)題庫(kù)有一陣子這篇都值得花幾分鐘看完。文章結(jié)尾還有我最近踩過(guò)的幾個(gè)坑看完至少能幫你少走半天彎路。1. 刷題前的選題思路1.1 為什么今天選了Misc方向同一個(gè)平臺(tái)的題庫(kù)里有Web、逆向、Pwn、Crypto、Misc好幾個(gè)大類。我給自己定的節(jié)奏是每天至少覆蓋兩個(gè)方向其中一定保留一道Misc。Misc這個(gè)方向挺吃虧因?yàn)榭雌饋?lái)“沒(méi)有技術(shù)含量”。Web題考注入和繞過(guò)逆向和Pwn考底層功底Crypto考數(shù)學(xué)和算法思維Misc給人的第一印象就像是在“找東西”。但我的體感正好相反Misc恰恰是對(duì)綜合能力要求最雜的方向你要會(huì)看文件頭要懂編碼要熟悉常見(jiàn)隱寫算法還得有一點(diǎn)腦洞和聯(lián)想能力。圖片、壓縮包、流量、音頻、日志都可能成為載體沒(méi)有固定的知識(shí)邊界。今天選它會(huì)有一個(gè)好處題目來(lái)源不算偏門題型經(jīng)典不需要接觸復(fù)雜的漏洞利用鏈也可以把思考重心放在信息提取的思路上。把Misc練順手了對(duì)做Web也有幫助——很多Web題目里藏的提示文件、備份文件、編碼后的參數(shù)本質(zhì)上就是在考察你從冗余信息中定位關(guān)鍵線索的能力。1.2 刷題環(huán)境準(zhǔn)備我刷題用的就是平時(shí)工作的那臺(tái)電腦沒(méi)有做額外的虛擬機(jī)配置。不過(guò)有幾個(gè)小工具是每次做題前都會(huì)提前確認(rèn)的不然等題目讀到一半發(fā)現(xiàn)工具鏈缺了節(jié)奏很容易斷。file命令查看文件真實(shí)類型這個(gè)最常用。binwalk用于檢測(cè)文件里是否嵌入了其他文件。strings直接抓取文件中的可打印字符。xxd或010 Editor看hex內(nèi)容適合手工分析文件頭。StegSolve圖片通道分析必備。zsteg檢測(cè)PNG和BMP的LSB隱寫速度很快。Python環(huán)境處理編碼轉(zhuǎn)換、寫簡(jiǎn)單腳本時(shí)會(huì)用到。這些工具我在之前的練習(xí)里都裝好了Windows和Linux兩邊都有對(duì)應(yīng)版本。我的習(xí)慣是拿到題先扔Linux跑完一輪基礎(chǔ)命令沒(méi)結(jié)果再切到Windows的圖形化工具做像素級(jí)分析。兩條路互補(bǔ)比單一環(huán)境穩(wěn)得多。提示如果你用的發(fā)行版沒(méi)有預(yù)裝binwalk不要只試apt install binwalk有些舊版本自帶庫(kù)不全分離時(shí)容易報(bào)錯(cuò)。我一般直接拉取最新release或從源碼編譯雖然多點(diǎn)時(shí)間但后面不會(huì)因?yàn)榘姹締?wèn)題翻車。2. 一道帶message關(guān)鍵詞的圖片題完整解題過(guò)程2.1 第一步文件識(shí)別與基礎(chǔ)信息收集這道題拿到手是個(gè)圖片附件文件名里沒(méi)帶什么有用的版本號(hào)大小看著也很正常。文件名本身可以記一下但別太當(dāng)真CTF出題人為了制造干擾是會(huì)用文件名誤導(dǎo)你的真正拿主意還得看文件內(nèi)容。我先把圖片丟進(jìn)Linux環(huán)境用file命令看它的真實(shí)類型。file message.png message.png: PNG image data, 800 x 600, 8-bit/color RGBA, non-interlaced底確實(shí)是PNG尺寸800x600RGBA色彩空間。這組信息本身就值得多看一眼PNG是CTF題的高頻載具因?yàn)樗菬o(wú)損壓縮可以逐像素提取數(shù)據(jù)也方便在通道里藏信息。接下來(lái)跑一輪最基礎(chǔ)的信息收集把圖片不太老實(shí)的地方暴露出來(lái)。exiftool message.pngEXIF信息里沒(méi)看到什么異常的注釋字段只有常規(guī)的創(chuàng)建時(shí)間。不過(guò)這并不能說(shuō)明它是干凈的很多出題人不會(huì)把提示寫在EXIF里尤其是當(dāng)題目關(guān)鍵詞本身就叫message的時(shí)候信息大概率是藏在圖像內(nèi)容里的而不是寫在元數(shù)據(jù)表面。再跑一下strings把所有可打印字符拉出來(lái)篩選一遍。strings message.png | head -50輸出結(jié)果里除了PNG標(biāo)準(zhǔn)塊IHDR、IDAT、IEND之外沒(méi)有出現(xiàn)類似flag或base64長(zhǎng)串的內(nèi)容。到這里常規(guī)的信息收集算是做完進(jìn)入第二步。2.2 第二步分離隱藏?cái)?shù)據(jù)的標(biāo)準(zhǔn)姿勢(shì)題目名加了message這個(gè)詞我心里立刻有一個(gè)預(yù)設(shè)方向這個(gè)message要么是被直接拼在圖片數(shù)據(jù)里要么是通過(guò)某種隱寫算法編碼到像素中。先處理第一種可能——文件拼接。在CTF里經(jīng)常有這種情況出題人把一個(gè)文本文件直接接到圖片文件后面收尾的IEND塊后面其實(shí)還有大量數(shù)據(jù)。Windows下雙擊圖片看著還是正常的因?yàn)閳D片查看器到IEND就停止解析了后面的數(shù)據(jù)不會(huì)被顯示出來(lái)但文件體積會(huì)明顯偏大。我用binwalk做了一次快速掃描binwalk message.png這個(gè)輸出會(huì)列出文件里可能的嵌入數(shù)據(jù)塊。跑完以后發(fā)現(xiàn)DECIMAL列下出現(xiàn)了不止一個(gè)條目除了開頭PNG自身的圖像數(shù)據(jù)外在文件偏移量尾部還存在一段可疑數(shù)據(jù)塊。這正是“圖片內(nèi)還有額外文件”的典型信號(hào)。順手再用foremost做一次基于文件簽名提取的嘗試foremost message.png -o extracted如果嵌入部分是一個(gè)完整獨(dú)立的文件格式foremost通常會(huì)直接把它撈出來(lái)。不過(guò)這道題沒(méi)有走到這一步因?yàn)楹竺娣治霭l(fā)現(xiàn)信息并不是以文件形式嵌入的foremost撈不出完整結(jié)構(gòu)很正常。binwalk的結(jié)論出來(lái)以后需要確認(rèn)一下偏移量位置。把圖片拖進(jìn)010 Editor定位到PNG文件尾部的IEND標(biāo)記然后看它后面的字節(jié)內(nèi)容。這也是一個(gè)很關(guān)鍵的習(xí)慣不依賴工具的一句話結(jié)論自己親眼看到多出來(lái)的那一段數(shù)據(jù)長(zhǎng)什么樣。2.3 第三步從碎片內(nèi)容拼出message010 Editor里翻到IEND后面發(fā)現(xiàn)確實(shí)還有一串肉眼可讀的ASCII字符不是亂碼也不是二進(jìn)制碎片而是有明確含義的文本片段。內(nèi)容大致是一段經(jīng)過(guò)編碼的字符串從上下文推斷應(yīng)該是用base64處理過(guò)的。到這里做一次常規(guī)還原echo base64字符串 | base64 -d解出來(lái)以后是一串人話但并不是最終結(jié)果而是繼續(xù)指向下一個(gè)線索。它把信息的藏身之處引向了圖像的像素通道也就是經(jīng)典的LSB隱寫思路。所謂LSB隱寫指的是把信息逐位拆開替換掉圖像每個(gè)像素最低位的數(shù)值。因?yàn)樽畹鸵晃坏淖兓瘜?duì)人眼來(lái)說(shuō)幾乎不可見(jiàn)所以成品圖和原圖看起來(lái)沒(méi)什么區(qū)別實(shí)際卻可以塞下一整段文本。對(duì)RGBA格式的PNG圖每個(gè)像素有R、G、B、A四個(gè)通道每個(gè)通道都能用最低位承載1比特?cái)?shù)據(jù)。既然是LSB隱寫直接用zsteg掃一遍是比較快的驗(yàn)證方法zsteg message.pngzsteg會(huì)嘗試按常見(jiàn)順序和方向把藏在最低位的比特串提取出來(lái)。跑了沒(méi)兩秒它就在某一組通道組合下輸出了一段可讀內(nèi)容正是題目要的那個(gè)message。拿到內(nèi)容之后我用在線網(wǎng)站復(fù)核了一遍解密結(jié)果確認(rèn)不是zsteg的誤報(bào)這才落筆提交。復(fù)盤這道題真實(shí)思路并不復(fù)雜先用文件識(shí)別確定載體類型再用binwalk和編輯器確認(rèn)圖片末尾是否有附加數(shù)據(jù)發(fā)現(xiàn)附加數(shù)據(jù)是base64編碼的提示順著提示轉(zhuǎn)入像素隱寫分析最后用zsteg拿到真正的message。熟練以后整套流程十分鐘內(nèi)可以完成但第一次接觸的人很容易卡在第二步binwalk掃出了內(nèi)容卻沒(méi)有耐心去讀附加數(shù)據(jù)的含義急著去做各種花哨的工具操作結(jié)果繞遠(yuǎn)了。3. 順手復(fù)習(xí)的信息隱藏知識(shí)點(diǎn)3.1 隱寫題的常見(jiàn)藏法做完這道題我把最近在攻防世界上碰到過(guò)的同類題型整理了一下。信息隱藏類題目看著花樣多常見(jiàn)套路其實(shí)就那么幾類按頻率排個(gè)序隱藏方式典型特征快速檢測(cè)手段文件拼接文件尾部有明顯附加字節(jié)binwalk / 010 Editor看IEND后EXIF字段元數(shù)據(jù)里出現(xiàn)超長(zhǎng)注釋exiftool 翻字段LSB隱寫圖片通道低位有規(guī)律變化zsteg / StegSolveDCT域隱寫常見(jiàn)于JPEG通道數(shù)據(jù)被改動(dòng)專用腳本檢測(cè)調(diào)色板隱寫色塊數(shù)量異常像素索引替換StegSolve逐個(gè)通道看動(dòng)態(tài)圖分離GIF多幀藏文本或二維碼convert逐幀導(dǎo)出文件拼接是最不需要技巧但最容易漏掉的一種。很多題目只是把一個(gè)壓縮包或者文本文件默默地續(xù)在圖片后面制作者甚至不會(huì)對(duì)附加內(nèi)容做任何處理。判斷的核心就是binwalk掃描加上文件體積對(duì)比如果一張看起來(lái)平平無(wú)奇的圖片體積卻有幾十MB或者IEND塊后面還跟著看得懂的字符基本可以直接進(jìn)下一步。LSB隱寫則要麻煩一點(diǎn)難點(diǎn)在于排列順序。同樣是12個(gè)像素紅色通道最低位在前、還是綠色通道最低位在前、或者按RGBA一輪輪排都會(huì)得到完全不同的比特流。zsteg的價(jià)值就在于此它會(huì)把各種常見(jiàn)排列方式全試一遍然后找到能輸出可讀文本的那一組。相比之下手工遍歷通道的話效率就太低StegSolve看通道分布可以輔助判斷但提取數(shù)據(jù)還是腳本工具更靠譜。EXIF隱藏是最適合新手入門的類型因?yàn)椴恍枰獙?duì)圖像做任何數(shù)學(xué)處理只在文件頭元數(shù)據(jù)區(qū)域的注釋字段里寫內(nèi)容就行。很多題目直接把提示或flag放在“作者”“注釋”“軟件”這類字段里用exiftool一把抓出來(lái)。但這種題目越來(lái)越少了現(xiàn)在多數(shù)出題人會(huì)把EXIF當(dāng)誤導(dǎo)里面寫一句“繼續(xù)努力吧”之類的廢話真實(shí)線索在別處。3.2 從圖片題延伸到Web題的一個(gè)小案例隱寫題的思維方式其實(shí)可以遷移到很多Web題里。攻防世界里的Web題有一個(gè)特點(diǎn)很多關(guān)卡把關(guān)鍵信息藏在響應(yīng)包的某個(gè)角落里而不是直接顯示在頁(yè)面上。我拿最近練的一道題舉例。題目頁(yè)面上有個(gè)輸入框提交參數(shù)后返回了一個(gè)很普通的字符串。單看頁(yè)面沒(méi)有報(bào)錯(cuò)沒(méi)有異常響應(yīng)一般新手到這里就停了。但當(dāng)時(shí)我把請(qǐng)求丟進(jìn)Burp Suite看完整響應(yīng)頭發(fā)現(xiàn)一處自定義頭字段里帶了一段url編碼的字符串。解出來(lái)以后是一份備份文件的路徑順著路徑下載下來(lái)又發(fā)現(xiàn)備份文件里殘留了一段注釋注釋里寫著一個(gè)過(guò)濾邏輯和繞過(guò)條件的線索。這就是典型的“信息在意外位置”思路。圖片題的message藏在像素最低位、Web題的線索藏在響應(yīng)headers里本質(zhì)上都在考察你有沒(méi)有把有待檢視的范圍擴(kuò)到界面之外。如果你只盯著頁(yè)面主流程等于在做Misc時(shí)只雙擊圖片看能不能預(yù)覽出隱藏文字那肯定找不到。這也解釋了為什么我練Misc對(duì)做Web幫助很大。不是知識(shí)點(diǎn)直接復(fù)用而是養(yǎng)成了一套行為習(xí)慣永遠(yuǎn)考慮到載體本身之外還有沒(méi)有別的東西對(duì)任何異常數(shù)據(jù)都保持敏感。4. 刷題過(guò)程中的坑與經(jīng)驗(yàn)4.1 常見(jiàn)卡點(diǎn)做Misc題最??ㄗ〉奈恢貌皇遣粫?huì)用工具而是思路順序不對(duì)。說(shuō)幾個(gè)我這段時(shí)間踩過(guò)、也在別人解題記錄里反復(fù)看到的坑。第一個(gè)坑是直接用StegSolve對(duì)圖片做一堆通道分析而不先跑一遍binwalk和strings。這樣做的問(wèn)題在于你把最省時(shí)間的可能性放在后面處理了。如果只是文件拼接或EXIF藏字StegSolve分析再多通道也得不到任何東西浪費(fèi)十幾分鐘后又繞回原點(diǎn)。穩(wěn)妥的順序是先低成本粗掃再做像素級(jí)細(xì)看。第二個(gè)坑是忽略文本內(nèi)容的上下文。我有一次掃描一張圖片尾部有一段用base64編碼的字符串解出來(lái)是/secret_flag.txt。我當(dāng)時(shí)下意識(shí)覺(jué)得這只是一個(gè)文件路徑提示就沒(méi)當(dāng)回事結(jié)果題目真正的入口是從這個(gè)路徑也可以訪問(wèn)到的隱藏頁(yè)面。很多線索不會(huì)直接寫成“flag在這”它只是一個(gè)路徑、一個(gè)文件名、一段殘缺的對(duì)話需要你去聯(lián)想它指向哪里。第三個(gè)坑是平臺(tái)環(huán)境本身的干擾。攻防世界這類平臺(tái)偶爾會(huì)出現(xiàn)網(wǎng)絡(luò)抖動(dòng)代碼提交后長(zhǎng)時(shí)間無(wú)響應(yīng)或者某道題目的容器需要稍等片刻才能啟動(dòng)別急著懷疑自己思路錯(cuò)了。另外有些題目下載附件的文件名會(huì)被瀏覽器自動(dòng)加了后綴做題前先核對(duì)一下下載下來(lái)的文件真實(shí)類型。第四個(gè)坑和編碼相關(guān)。提取出的字符串有時(shí)候不是標(biāo)準(zhǔn)的base64可能帶了個(gè)別字符被替換、或者尾部補(bǔ)了多余的回車換行。直接用命令行在線解碼容易因?yàn)楦袷絾?wèn)題報(bào)錯(cuò)先看一眼字符串長(zhǎng)度是不是4的倍數(shù)不是的話先檢查提取過(guò)程有沒(méi)有多讀或者漏讀。我把這些整理成一個(gè)簡(jiǎn)單的問(wèn)題速查表方便快速對(duì)照現(xiàn)象排查方向常用解法binwalk掃描無(wú)異常但文件尾有肉眼可見(jiàn)字符IEND塊后存在附加文本用編輯器直接讀尾部提取編碼串解碼圖片看上去沒(méi)有任何異常但體積明顯偏大大概率是文件拼接或嵌入了壓縮包binwalk -e嘗試遞歸分離zsteg提取結(jié)果全是亂碼提取通道或方向不對(duì)切換zsteg的通道參數(shù)或換StegSolve雙向查看解碼base64報(bào)錯(cuò)字符串里混了換行或者字符被替換先過(guò)濾非base64字符再補(bǔ)全填充提取出的文本很怪像英文但字母錯(cuò)位可能做過(guò)凱撒移位或其他簡(jiǎn)單替換先用在線工具試常見(jiàn)移位再考慮其他古典密碼4.2 刷題習(xí)慣建議每天保持做題這件事重要的不是一天做十道二十道而是穩(wěn)定地練。我現(xiàn)在給自己定的目標(biāo)是每天至少兩道一道保持手感的熟練題一道稍微超出當(dāng)前能力的題。超出能力的那道如果是Misc會(huì)先自己死磕40分鐘不碰題解40分鐘沒(méi)進(jìn)展再去看別人的WriteUp??碬riteUp也有技巧別從頭到尾當(dāng)小說(shuō)看先看對(duì)方的思路轉(zhuǎn)折點(diǎn)在哪。比如今天這道題轉(zhuǎn)折點(diǎn)就在“尾部附加數(shù)據(jù)是一段編碼提示”這個(gè)轉(zhuǎn)折之后的操作全是常規(guī)流程??搭}解時(shí)把這種轉(zhuǎn)折記進(jìn)自己的知識(shí)樹里下次碰到類似情況就有印象要先解碼再往下走了。另外我建議做一道題就在本地建一個(gè)文件夾把題目附件、自己跑過(guò)的命令、中間輸出和最終flag都留下來(lái)。這不是為了給誰(shuí)看主要方便事后復(fù)盤同一道題隔兩周再做一遍看自己還會(huì)不會(huì)卡在同樣的地方。如果還卡說(shuō)明那個(gè)知識(shí)點(diǎn)沒(méi)有真正變成自己的需要針對(duì)性地多找兩道同類題補(bǔ)練。注意刷題平臺(tái)賬號(hào)里的做題記錄只能看到提交時(shí)間看不到中途失敗的過(guò)程所以本地記錄反而成了最寶貴的資料。我回看我最早幾天的記錄發(fā)現(xiàn)自己當(dāng)時(shí)很多時(shí)間花在無(wú)意義的工具亂試上而現(xiàn)在再看同樣的題能直接判斷該先跑哪個(gè)命令。經(jīng)驗(yàn)就是這樣一點(diǎn)點(diǎn)堆出來(lái)的。寫在最后攻防世界的題目做得越多越能感受到一個(gè)道理大部分題不是考冷門知識(shí)而是考你有沒(méi)有把基礎(chǔ)功夫做扎實(shí)。文件識(shí)別、編碼解碼、信息定位、工具調(diào)用每一步單獨(dú)拿出來(lái)都不難難的是在有限時(shí)間里把這些動(dòng)作串成一條有效的路徑。今天這道以message為線索的圖片題走的正是一條很典型的路線從文件尾部發(fā)現(xiàn)附加數(shù)據(jù)解碼提示后轉(zhuǎn)入像素隱寫再用工具提取最終信息。我個(gè)人在實(shí)際做題中的體會(huì)是拿到任何一道Misc題不要急著開工具先花三十秒把題目文件從頭到尾的邏輯捋一遍。想象一下如果你是出題人會(huì)把message放在哪一層。這種“換位思考”的習(xí)慣幫了我很大忙也讓刷題不再只是機(jī)械地跑工具。希望這篇記錄能給你一點(diǎn)參考。下一篇我打算整理攻防世界上那些“看似是Misc其實(shí)是Web”的混淆題型這個(gè)分類陷阱我自己踩過(guò)好幾次到時(shí)候把判斷依據(jù)和繞過(guò)順序都寫出來(lái)。