re學習筆記(22)愛春秋CTF答題奪旗賽(第四季)-re-basebasebase

在這裏插入圖片描述
題目下載:
鏈接:https://pan.baidu.com/s/1ArbrvREhcbzVPFsHGoo2yA
提取碼:3khv

IDA載入,尋找main函數
在這裏插入圖片描述
sub_401000()函數內部是一個反調試
在這裏插入圖片描述
而nullsub_1無法打開
在這裏插入圖片描述
查看main函數的彙編代碼,發現有未定義的函數
在這裏插入圖片描述
繼續下滑發現有關鍵代碼
在這裏插入圖片描述
在函數頭摁下快捷鍵P,將其定義爲一個函數,摁下F5鍵發現還是無法F5
在這裏插入圖片描述
找到IDA設置,打開stack pointer
在這裏插入圖片描述
在這裏插入圖片描述
發現函數的最後,retn的棧小於0了,導致不能F5
在這裏插入圖片描述
先在pop 或者call那裏,將棧指針調整(快捷鍵Alt+k),使得retn的棧指針大於等於0
如果出現下圖情況(一會出現一會不出現,,玄學問題)

  1. 點進這個地址,讓IDA自動分析一下,退出來就能F5
  2. 這道題,此call剛開始未定義,然後輸出“Successful”的代碼在此call的上面,可以判斷此call並不是關鍵代碼,因此將其取消定義(右鍵→undefine)
    在這裏插入圖片描述
void __usercall hanshu1(int a1@<ebp>)
{
  int v1; // ecx

  *(a1 - 132) = 0;
  *(a1 - 40) = 89;
  *(a1 - 39) = 110;
  *(a1 - 38) = 123;
  *(a1 - 37) = 107;
  *(a1 - 36) = 89;
  *(a1 - 35) = 32;
  *(a1 - 34) = 119;
  *(a1 - 33) = 106;
  *(a1 - 32) = 90;
  *(a1 - 31) = 91;
  *(a1 - 30) = 77;
  *(a1 - 29) = 111;
  *(a1 - 28) = 91;
  *(a1 - 27) = 67;
  *(a1 - 26) = 90;
  *(a1 - 25) = 42;
  *(a1 - 24) = 90;
  *(a1 - 23) = 67;
  *(a1 - 22) = 119;
  *(a1 - 21) = 101;
  *(a1 - 20) = 86;
  *(a1 - 19) = 110;
  *(a1 - 18) = 85;
  *(a1 - 17) = 67;
  *(a1 - 16) = 89;
  *(a1 - 15) = 91;
  *(a1 - 14) = 73;
  *(a1 - 13) = 121;
  *(a1 - 12) = 89;
  *(a1 - 11) = 91;
  *(a1 - 10) = 42;
  *(a1 - 9) = 41;
  *(a1 - 8) = 3;
  printf(Format);
  *(a1 - 76) = 0;
  *(a1 - 75) = 0;
  *(a1 - 71) = 0;
  *(a1 - 67) = 0;
  *(a1 - 63) = 0;
  *(a1 - 59) = 0;
  *(a1 - 55) = 0;
  *(a1 - 51) = 0;
  *(a1 - 47) = 0;
  scanf(aS, a1 - 76);                           // a1-76  爲用戶的輸入
  *(a1 - 128) = a1 - 76;                        // a1-128  是一個指針,指向用戶輸入
  *(a1 - 144) = *(a1 - 128) + 1;                // a1-144存儲用戶輸入第二個字符
  do
    *(a1 - 113) = *(*(a1 - 128))++;
  while ( *(a1 - 113) );
  *(a1 - 140) = *(a1 - 128) - *(a1 - 144);
  *(a1 - 148) = hanshu2((a1 - 76), *(a1 - 140), (a1 - 136));// a1-140  爲編碼之前的長度
                                                // a1-136  爲base64編碼後的長度
  for ( *(a1 - 124) = 0; *(a1 - 124) < 33; ++*(a1 - 124) )// a1-124 爲計數器   <33   33位
    *(a1 + *(a1 - 124) - 112) = *(*(a1 - 124) + *(a1 - 148)) ^ 3;// base64編碼後與3異或
                                                // 賦給a1-112
  for ( *(a1 - 120) = 0; *(a1 - 120) < *(a1 - 136); ++*(a1 - 120) )// a1-120爲計數器,循環次數爲base64編碼後的長度
  {
    if ( *(a1 + *(a1 - 120) - 112) != *(a1 + *(a1 - 120) - 40) )// base64編碼後,再與3異或,然後與a1-40比較
    {
      printf(asc_40302C);
      exit(0);
    }
    if ( *(a1 + *(a1 - 120) - 112) == *(a1 + *(a1 - 120) - 40) )
      ++*(a1 - 132);                            // 如果不相等,a1-132就不加,不加的話,下面判斷就會失敗
  }
  if ( *(a1 - 132) == *(a1 - 136) )
    printf(aSuccessful);
  v1 = a1 ^ *(a1 - 4);
  JUMPOUT(loc_40121B);
}

在這裏插入圖片描述
可以發現他把所有的變量都用指針來表示了,,,
定義了一個字符串,(從a1-40到a1-8)
這是最後與變換後的flag比較的字符串
hanshu2()是一個base64加密
可以參考Base16,Base32,Base64編碼詳細學習
查看其字符表,發現是一個自定義字符表的base64加密
在這裏插入圖片描述
其中&amp;=&是一個轉義字符串

轉義字符串(Escape String),即字符實體(Character Entity)分成三部分:第一部分是一個&符號,英文叫ampersand;第二部分是實體(Entity)名字或者是#加上實體(Entity)編號;第三部分是一個分號。
在這裏插入圖片描述

總體流程爲,程序將用戶的輸入進行base64加密,然後與3異或,最後與存儲在棧上的字符串進行比對

寫腳本
在這裏插入圖片描述
因爲text長度爲33,而base64將原字符串長度變爲4/3,所以密文長度要能被4整除
所以密文的長度應該爲36,需要加上三個"="

import base64
text = [89,110,123,107,89,32,119,106,90,91,77,111,91,67,90,42,90,67,119,101,86,110,85,67,89,91,73,121,89,91,42,41,3]
for i in range(len(text)):
    text[i] ^= 3
    text[i] = chr(text[i])
text = ''.join(text)
text += "==="
print(base64.b64decode(text.translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz)!@#$%^&*(+/","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")).encode('utf-8')))

最後得出flag爲flag{base_f4ck_Reverse}

發佈了50 篇原創文章 · 獲贊 7 · 訪問量 3540
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章