1. 程式人生 > >【bugku】【RE】file WriteUp

【bugku】【RE】file WriteUp

FILE

  查殼後顯示無殼,拖進IDA:

  執行程式時傳遞的第一個引數為一個檔名,並開啟該檔案。下面點進去encode函式分析一下:

  for迴圈中每三個為一組,進行Base64的操作,接下來兩個if分別判斷Base64後的尾部是加一個“=”還是兩個“=”還是不加“=”。具體Base64編碼方式可以參考我的這篇部落格:https://www.cnblogs.com/reddest/p/9554948.html。所以encode()是對傳入的字串進行Base64編碼。回到主函式看看encode()被用在哪裡了:

  圈出來的部分就是判斷輸入的資料是否是正確的KEY了,並且可以發現並沒有用到encode()的返回值v11和v12,所以encode()就是個擺在那裡打擾分析思路的。老夫40米巨劍何在。

  根據異或的可逆性,v14[k] = k ^ flllag[k] ^ v13[k]。現在我們只缺v13陣列中是哪些元素了,分析sub_400EB9():

  sub_400EB9()的返回值根據sub_400E6A()來定,跟進分析sub_400E6A():

  這裡把傳入的某個元素判斷是否符合某個區間,然後分別返回不同的值。該函式傳進來的是sttr_home[]字串中的元素,主函式中雙擊該字串:

  獲取了sttr_home的元素後寫個指令碼跑出v13[],指令碼如下:

 1 #include <cstdio>
 2 char str[110] = "664e06226625425d562e766e042d422c072c45692d125c7e6552606954646643
"; 3 int jdg(int id){ 4 if(str[id] >= '0' && str[id] <= '9') 5 return str[id] - '0'; 6 if(str[id] >= 'A' && str[id] <= 'F') 7 return str[id] - '7'; 8 if(str[id] < 'a' && str[id] > 'f') 9 return 0xFFFFFFFFLL; 10 return
str[id] - 'W'; 11 } 12 int calc(int x, int y){ 13 return 16 * jdg(x) + jdg(y); 14 } 15 int main(){ 16 for(int i = 0;i < 64;i += 2){ 17 printf("%d, ", calc(i, i + 1)); 18 } 19 return 0; 20 }

  接著寫出根據v14[k] = k ^ flllag[k] ^ v13[k]寫出相應指令碼跑出KEY,並把KEY存到檔案中,程式碼如下:

  接著用gcc編譯並執行後,把a.txt作為引數傳給file執行:

  把a.txt的MD5線上計算一下:

  把MD5加上flag{}就OKK啦!