【bugku】【ZSCTF】【迷宮RE】Take The Maze WriteUp
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){ 3if(Dword(0x540548 + i * 4) ^ Dword(0x540068 + i * 4)) 4Message("."); 5else 6Message("D"); 7 8if(Dword(0x5404DC + i * 4) ^ Dword(0x53FFFC + i * 4)) 9Message("."); 10else 11Message("L"); 12 13if(Dword(0x5404E4 + i * 4) ^ Dword(0x540004 + i * 4)) 14Message("."); 15else 16Message("R"); 17 18if(Dword(0x540478 + i * 4) ^ Dword(0x53FF98 + i * 4)) 19Message("."); 20else 21Message("U"); 22 23Message(""); 24if(!((i + 1) % 26)) 25Message("\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): 4print chr(ord(a[i])^i),
跑出來結果如下:
去掉空格就是真正的KEY了,輸程序序裡面:
工作目錄下便生成了一個.png檔案,點開發現是個二維碼:
掃出來: