本題我們跟隨主人公飛停一起,尋找寶劍。本題耗時2天,吸引了超過2千人圍觀,最終11支戰隊奪旗成功!恭喜!
出題團隊簡介
崇文路大專是一個隸屬於重慶郵電大學資訊保安協會的CTF戰隊,其主要目標是培養對資訊保安感興趣的學弟學妹們,帶著新入門的成員一起參加比賽,致力於奪得各大比賽簽到題一血。同時也是重慶郵電大學資訊保安協會旗下的0xFA戰隊的附屬戰隊,0xFA戰隊曾多次進入XCTF線下總決賽、安洵杯線下總決賽、國賽總決賽。
專家點評
比賽第六題是一個有趣的42*42棋盤遊戲,使用了自己開發的混淆器進行混淆處理。選手需要編寫程式碼去除混淆拿到核心演算法程式碼再進行逆向。題目難度中等偏上,需要考驗選手的逆向和編寫指令碼的能力。
賽題設計思路
題目設計了一個巧妙的數學問題,既考察了各位選手的程式碼審計能力,又對資訊收集能力與程式設計解題能力有一定的要求。
首先程式會問36乘49等於多少,這是對題目演算法內容的一種暗示:36×49=42×42。
接著程式會讀取輸入,輸入不允許出現0-9、A-Z、"+-*/%="以外的其他字元。
然後程式會檢查輸入的長度是否為84,如果滿足則把輸入的字元兩兩一組以四十二進位制的方式解析成42個整數,存放在陣列裡,其中這42個整數必須是按照嚴格遞增的順序被輸入。
接下來,用一個42×42的二維陣列來抽象一個42×42個格子的棋盤,然後將該二維陣列一維化,將輸入的整數陣列中的每個整數當作下標,將對應下標的元素設定為true(兩位的四十二進位制剛好不會超過棋盤的大小)。
若某陣列元素為true,則代表棋盤中該元素對應的格子裡放了一顆棋子,反之則沒有放任何東西。
接下來檢查,是否每一行、每一列均只有一顆棋子(即:同一行/列中不能有多顆棋子,因為只可以放42顆棋子,所以剛好可以每行每列放一個)。
我規定某兩顆棋子的連線稱作它們的相對偏移線段(比如:第一行第一列的棋子和第二行第二列的棋子的相對偏移線段是一條長度為根號二、斜率為負一的線段),若兩條相對偏移線段的長度和斜率均相等,則稱它們相等。
後面的程式碼是檢驗是否任意兩顆棋子之間的相對偏移線段均不相等(注:相對偏移線段沒有“方向”這個概念,也就是說,“棋子A與棋子B的相對偏移線段”和“棋子B與棋子A的相對偏移線段”視作同一條相對偏移線段)。
若檢驗透過,則判斷輸入的開頭14個字元是否與指定的字串相等,換句話說我指定了棋盤上前7顆棋子的位置(按從左到右、從上到下的順序)。
若檢驗全透過,則輸出成功,否則輸出錯誤。
程式採用Release x64模式編譯,所用編譯器為Visual Studio 2019可選安裝的LLVM - clang-cl(版本為10.0),設定了生成除錯資訊:否、最佳化:已禁用、啟用內部函式:否、優選大小或速度:均不,編譯環境為Windows10 2004。
由於題目要求不允許使用第三方殼或VM,我認為ollvm或許會被認定為第三方,因此沒有采用ollvm方式編譯,題目難度稍有降低。
原創混淆器
本次比賽出題使用了我自己開發的“COP”混淆器,COP可以開啟並解析一個PE檔案,針對32/64位分別進行處理。
COP要求所給檔案必須具有.text段、.reloc段,且不含有花指令。
COP使用Capstone解析出程式檔案的所有彙編指令,將指令進行混淆,並且隨機打亂,膨脹後的指令無法塞進原.text段,因此將多餘的部分放入新的.cop段中。
順序被完全打亂的指令需要用某種方式連線它們,讓它們順序執行,我將非跳轉指令用“call+pop+add/xor+push+ret”的方式連線,將跳轉指令進行了不同程度的變形。
此外,COP還將程式所有基於相對偏移的指令進行了修復,透過重定位表將所有基於絕對地址的命令進行了修復,對64位程式的基於rip定址的指令進行了修復。
COP自行維護了一個獨立的重定位表,混淆後仍可以開啟地址隨機化。
為了提高混淆強度,對64位程式還將清空其.pdata段的內容。
COP還支援巢狀混淆(簡稱套娃),進一步提高混淆強度。
使用者可以選擇保留.reloc段或者去除,去除以後會進一步提高混淆強度,但不支援繼續巢狀混淆,且會關閉地址隨機化。
我使用COP將編譯出的程式進行了2次混淆,得到最終附件,考察了各位選手編寫指令碼的能力。
解題思路
拿到的附件使用IDA開啟,發現有非常多的重複的程式碼,且動態除錯的時候有效指令出現的頻率極低,因此可以考慮使用指令碼對檔案進行初步處理。
先拿到call後面的pop rax的地址,提取xor的第二個運算元,即可計算出下一條指令的位置。
計算相對偏移,將第一個push rax改成jmp到下一條指令。
這裡比較方便的是使用IDAPython編寫指令碼,因為IDA提供了很多有用的API。
如此操作完以後,可以發現還巢狀了一層混淆。
這裡可以採用的方法很多,我採用的順序遍歷+特徵匹配的方式定位被jmp連起來的程式碼碎塊,若一系列遍歷下去發現指令與模式匹配,則認為它是一個混淆指令塊,取pop rax的地址和add的第二個運算元(內層是add,外層是xor),計算下一條指令的位置,並把匹配的指令序列的第一個指令改成jmp,可以把程式碼還原成由jmp連線起來的零碎指令。
再用IDA開啟去混淆後的程式,從字串的交叉引用定位主函式。
但是可以看到可能因為我的去混淆程式碼寫得不是很好,IDA的F5外掛仍然無能為力,這裡可以考慮使用Capstone或者IDA自帶的API修一下程式碼,或許能提高反編譯的質量和準確率。
在去混淆到這種程度後,一個好辦法是動靜結合,再根據F5的部分殘破的語句,可以大致還原整個演算法(因為沒有開編譯器最佳化,因此可讀性比較強)。
拿到演算法後,可以選擇寫程式碼跑出結果,也可以上網進行資訊收集。
我們不難得知,前人已經對該問題進行過研究了,人們把它叫做科斯塔斯陣列(Costas Arrays)。
參考連結:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.137.8983&rep=rep1&type=pdf
已經有許多高效的演算法被前人發明,我們透過模仿與借鑑這些程式碼就能求出最終的結果。
最後,將求出的結果轉化成42個整數,以四十二進位制的方式轉換後即是最終flag。
賽題解析
本賽題解析由看雪論壇 KuCha128 給出:
具體解析可點選此連結:https://bbs.pediy.com/thread-267658.htm 檢視
往期解析
1. 看雪·深信服 2021 KCTF 春季賽 | 第二題設計思路及解析
2. 看雪·深信服 2021 KCTF 春季賽 | 第三題設計思路及解析
3. 看雪·深信服 2021 KCTF 春季賽 | 第四題設計思路及解析
4. 看雪·深信服 2021 KCTF 春季賽 | 第五題設計思路及解析
主辦方
看雪CTF(簡稱KCTF)是圈內知名度最高的技術競技之一,從原CrackMe攻防大賽中發展而來,採取線上PK的方式,規則設定嚴格周全,題目涵蓋Windows、Android、iOS、Pwn、智慧裝置、Web等眾多領域。
看雪CTF比賽歷史悠久、影響廣泛。自2007年以來,看雪已經舉辦十多個比賽,與包括金山、360、騰訊、阿里等在內的各大公司共同合作舉辦賽事。比賽吸引了國內一大批安全人士的廣泛關注,歷年來CTF中人才輩出,匯聚了來自國內眾多安全人才,高手對決,精彩異常,成為安全圈的一次比賽盛宴,突出了看雪論壇複合型人才多的優勢,成為企業挑選人才的重要途徑,在社會安全事業發展中產生了巨大的影響力。
合作伙伴
深信服科技股份有限公司成立於2000年,是一家專注於企業級安全、雲端計算及基礎架構的產品和服務供應商,致力於讓使用者的IT更簡單、更安全、更有價值。目前深信服在全球設有50餘個分支機構,員工規模超過7000名。
比賽火熱進行中!立即挑戰!
公眾號ID:ikanxue
官方微博:看雪安全
商務合作:wsc@kanxue.com