2018/12/15-Bugku-逆向-Take the maz
連結:https://pan.baidu.com/s/1476ONvrOcG0Jbzl1PEe30w
提取碼:az10
根據題目名稱可知道這是一個迷宮題,這個迷宮的實現比較有意思。
首先讓輸入24個字元。
然後sub_45C748是一個VM,試著輸入24個‘A’,然後動態除錯發現處理的資料很有規律,猜測驗證後確定sub_45C748的作用是input[i] = input[i] ^ i。
然後對處理後的資料進行驗證,若不在‘0’-‘9’,'a'-'f'之間則錯誤。
然後就是最後一層驗證,迷宮驗證。
我們來跟進sub_45E593,仔細分析一下迷宮和移動的實現。
首先可以看到函式裡面有三個switch結構,我們先看前兩個。
連結:https://pan.baidu.com/s/1476ONvrOcG0Jbzl1PEe30w
提取碼:az10
根據題目名稱可知道這是一個迷宮題,這個迷宮的實現比較有意思。
首先讓輸入24個字元。
然後sub_45C748是一個VM,試著輸入24個‘A’,然後動態除錯發現處理的資料很有規律,猜測驗證後確定sub_45C748的作用是input[i] = input[i] ^ i。
然後對處理後的資料進行驗證,若不在‘0’-‘9’,'a'-'f'之間則錯誤。
然後就是最後一層驗證,迷宮驗證。
我們來跟進sub_45E593,仔細分析一下迷宮和移動的實現。
首先可以看到函式裡面有三個switch結構,我們先看前兩個。
前兩個switch將輸入input每兩個為一組,然後第一個選擇來選擇方向,第二個來選擇步數。
然後看第三個switch。
byte_541168處儲存的是字串‘delru0123456789’,d,l,r,u就是控制方向的,byte_541168[v7] - '0'即是移動的步數。
四個方向的函式,第一個引數就是當前的座標,函式會改變這個座標,第二個引數是在這個方向上移動的步數。
然後分析每個方向的函式。
判斷上下左右很容易,例如。
出現+=26說明是向下,其它方向同理。‘
每個方向函式裡面有個地方比較有意思。
dword_540548[i] ^ dword_540068[i]怎麼理解呢,首先我們知道這個函式是向下方向,然後當兩個數相等時異或值為0,才不會return,如果return0退出了說明什麼呢,說明當前位置不能向下走,因為在這個地方退出了,就不能i += 26了。
同理,其它方向函式中每個if中的異或值判斷,也都是判斷當前位置能不能往這個方向走。
也就是說這個迷宮實現的意思是,這個地圖中,能向上向下向左向右走的座標是對應和固定的。比如迷宮(4,4)這個座標的i,能滿足向下和向右方向函式的異或值等於0,就說明在(4,4)這個座標上可以向下走和向右走,沒有滿足向上和向左函式中的異或值等於0,就說明不能向左和上走。
現在我們知道了迷宮移動的實現了,可以找到其實地址和結束地址。
v5表示當前地址,則起始地址為0,結束地址為311,其中311+1 = 12*26,可以知道這個迷宮有12行26列。
然後迷宮是從左上角走到右下角的,也就是說只有向下和向右方向的,我們只需要考慮向下和向右即可,然後這個方向中dump資料進行處理生成地圖。
我們選擇打印出來可以向右走的座標,用’→‘表示,可以向下走的座標,用’↓‘表示,可以同時向下和向右走的座標,用’↘‘表示。
我們使用IDAPython來寫指令碼,因為可以使用Ddowrd(0xaddress)函式來直接得到指定地址的一個deword的值。
map_d1 = 0x540548 map_d2 = 0x540068 map_r1 = 0x5404E4 map_r2 = 0x540004 for i in range(12 * 26): if(i % 26 == 0): print '\n' a = ( Dword(map_d1 + 4*i) == Dword(map_d2 + 4*i) ) b = ( Dword(map_r1 + 4*i) == Dword(map_r2 + 4*i) ) if(a & b): print '↘', else: if(a): print '↓', if(b): print '→', if((a == 0) & (b ==0)): print ' ',
執行後可以得到
然後箭頭方向即代表當前座標可以往哪個往走,從左上角走到右下角,我們可以輕鬆找到路徑。
然後將路徑還原為處理的input,即三個switch處理的資料,不再詳細分析,可以得到為”06360836063b0839173e0639“。
在前面有說一個VM的函式異或處理input後才得到這個資料。我們再寫一個指令碼即可得到應該的正確輸入。
flag = [] str = "06360836063b0839173e0639" for i in range(len(str)): flag.append(ord(str[i]) ^ i) print ''.join(map(chr,flag))
我們在程式中輸入”07154=518?9i<5=6!&!v$#%.“。
然後顯示輸入正確後,會生成flag.png,檢視圖片發現是一張二維碼,掃碼得到Congratulations! The flag is your input + "Docupa"。
flag即為zsctf{07154=518?9i<5=6!&!v$#%.Docupa}。