1. 程式人生 > >2018/12/15-Bugku-逆向-Take the maz

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}。