Take The Maze
首先拿進PEID里查一下有沒有殼:

無殼,果斷拖進IDA。可是Graph View中找不到主程序的位置,在函數表里尋找主函數:

函數太多阻擾了我們找到主程序,運行一下程序找一些關鍵詞來搜索主程序位置:

得知主程序中應當含有“welcome to zsctf!”字符串,在IDA中搜索來找到主程序:

成功找到主函數,雙擊進入主函數,F5出偽代碼:

可以看出輸入的KEY為24位由0-9,a-f構成的字符串,且需要根據sub_45E593()的返回值確定是否為正確KEY。其他函數先放下,先分析一下sub_45E593():

多個if對應多個處理函數,且根據dlru初步猜測是迷宮問題。先來看看這個byte_541168存着什么:

該數組存的是"delru0123456789",在回過頭分析四個if上面的switch語句:

可以根據兩次的自加操作判斷,輸入的數據兩兩為一組。而且drc的值被用於在下面的if語句中判斷是byte_541168[]前五個中的哪一個字符,所以drc就決定了迷宮的走向。stp是朝着byte_541168[drc]方向行走的步數。
點開四個if對應的函數分別分析一下:

從這個函數可以推測出這個迷宮一行有26個元素。根據中pos == 311則return true,而311 == 11 * 26 + 25,再加上每一行的列標號從零開始,所以相當於從地圖的左上角走到地圖的(12, 25)的位置,即左上角走到右下角。
而且在上圖向下走的函數中,往下走能否可行是根據dword_540548[i] ^ dword_540068[i]的值來確定的,所以可以直接根據四個方向函數中的數組地址寫出IDC腳本來判斷某個節點是否可以往某個特定的方向走。IDC腳本如下:
1 auto i;
2 for(i = 0;i <= 311; ++i){
3 if(Dword(0x540548 + i * 4) ^ Dword(0x540068 + i * 4))
4 Message(".");
5 else
6 Message("D");
7
8 if(Dword(0x5404DC + i * 4) ^ Dword(0x53FFFC + i * 4))
9 Message(".");
10 else
11 Message("L");
12
13 if(Dword(0x5404E4 + i * 4) ^ Dword(0x540004 + i * 4))
14 Message(".");
15 else
16 Message("R");
17
18 if(Dword(0x540478 + i * 4) ^ Dword(0x53FF98 + i * 4))
19 Message(".");
20 else
21 Message("U");
22
23 Message(" ");
24 if(!((i + 1) % 26))
25 Message("\n\n");
26 }
27 return 0;
在IDA中執行效果如下:

放到記事本里走一遍迷宮:

手動走迷宮走出來的字符串為06360836063b0839073e0639,結果輸到程序里發現還是錯誤的KEY,返回到主函數檢查一下有沒有加密函數:

v5因為地址和v4緊挨着,所以v5其實就是v4[16],所以v5 ^= 1就相當於v4[16] ^= 1。這是加密的第一部分,分析一下疑似為加密函數的sub_45C748():

。。。。。。這tm是什么玩意兒。
看不太懂這是什么神奇加密,移步OD碰下運氣。
令輸入的字符串為24個“1”,步過這加密函數后它變成了這樣:

右下角的框框高亮部分就是經過加密函數的樣子。
。。。。。。這不就是按位異或嗎加密函數那么復雜作死啊??
再試驗一組24個“0”,發現其實是按位異或了一下,python腳本如下:
1 a = list("06360836063b0839073e0639")
2 a[16] = chr(ord(a[16]) ^ 1)
3 for i in range(24):
4 print chr(ord(a[i])^i),
跑出來結果如下:

去掉空格就是真正的KEY了,輸進程序里面:

工作目錄下便生成了一個.png文件,點開發現是個二維碼:

掃出來:

把之前解出來的KEY后面加上Docupa就是zsctf{}中括號里的內容啦!