1. 程式人生 > >安恆X計劃平臺10月月賽逆向題BASE++題目思路

安恆X計劃平臺10月月賽逆向題BASE++題目思路

這道題比賽時就看到了名字  沒下載到

一直在找題目附件  發現52破解上yechen123師傅發了帖子

就下載下來分析了一波  現在來記錄一下

IDA載入靜態分析可知

關鍵程式碼就在main()

程式與我們拿到flag有關的步驟就是 

0x01:判斷my_str_len(ps:就是我們輸入的字串的長度)是否小於32  正確的輸入最後算出來正好等於32  所以將會繼續向下執行

0x02:sub_91100()將我們得輸入my_str中的字母進行替換

0x03:通過sub_91360()與sub_91440()他倆配合的變種base64(ps:分析可知,只是替換了編碼表而已) 進行編碼

0x04:得到的串需要等於"TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D===="

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [esp+30h] [ebp-28h]
  int v5; // [esp+34h] [ebp-24h]

  printf(std::cout, "please input your flag:");
  scanf(std::cin, my_str);
  if ( strlen(my_str) < 32 )                    // 我們的輸入 my_str長度必須小於32
    goto LABEL_14;
  sub_91100(my_str);                            // 這裡將my_str中的小寫字母進行替換
  v5 = strcmp(my_str, "guvf_vf_n_snxr_synt_____________");
  if ( v5 )
    v5 = -(v5 < 0) | 1;
  if ( v5 )
  {
LABEL_14:
    sub_91360();                                // 替換了base32編碼的密碼錶
    sub_91440(strlen(my_str), my_str, a0);      // 進行變種base32編碼  用32個字元表示256個ASC字元,也就是說5個ASC字元一組可以生成8個Base字元
    v4 = strcmp(a0, "TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D====");// 用變種base32加密後 與這個串進行比較
    if ( v4 )
      v4 = -(v4 < 0) | 1;
    if ( v4 )
      printf(std::cout, "soooooooooorry\n");
    else                                        // 如果v4等於0 則輸出"Congratulations!!!"
      printf(std::cout, "Congratulations!!!\n");
    system("pause");
    result = 0;
  }
  else
  {
    printf(std::cout, "try harder!\n");
    result = 0;
  }
  return result;
}

IDA動態除錯時

F7進入sub_91360()可以看到 地址0009507C開始存放著這麼一個字串byte_9507C

這個就是要使用的密碼錶

NoPqRsTuVwXyZaBcDeFgHiJkLm765432

有了編碼表之後  可以很容易求得編碼之前的串

import string
import base64
my_base64table = "NoPqRsTuVwXyZaBcDeFgHiJkLm765432"
std_base64table ="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
s = "TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D===="
s = s.translate(string.maketrans(my_base64table,std_base64table))
print base64.b32decode(s)
#10n78ppn3ro00o70r2opop5s3roqq937

但是這裡就可以發現  長度正好是32位

那就肯定經過了0x02這個步驟

signed int __thiscall sub_91100(const char *this)
{
  const char *v1; // edi
  unsigned int i; // esi
  char v3; // cl

  v1 = this;
  i = 0;
  if ( strlen(this) )        //this 就是我們的my_str
  {
    do
    {
      v3 = v1[i];
      if ( (v3 - 0x61) <= 0x19u )    //如果有小寫字母就進行這種操作
        v1[i] = (v3 - 0x54) % 26 + 0x61;    
      if ( (v3 - 0x41) <= 0x19u )    //如果有大寫字母就進行這種操作
        v1[i] = (v3 - 0x34) % 26 + 0x41;
      ++i;
    }
    while ( i < strlen(v1) );
  }
  return 1;
}

因為base32解碼之後只有小寫字母

那我們只要把它們逆一下即可

這裡是yechen123師傅的指令碼

先生成密碼錶

然後對應下標即可(ps:又get到一個姿勢)

key = "10n78ppn3ro00o70r2opop5s3roqq937"
asciis = []
g = [] 
for i in range(97,123):
    asciis.append(chr(((i-84)%26)+97))#生成移位之後的表
for i in range(0,32):
    if (97<=ord(key[i])<=122):#小寫才用改  數字就算了
        temp = ord(key[i])-97
        g.append(asciis[temp])
        continue
    g.append(key[i])
flag = ""
for i in g:
    flag += i
print (flag)
#10a78cca3eb00b70e2bcbc5f3ebdd937

 

推薦大家看師傅寫的 非常詳細

https://www.52pojie.cn/forum.php?mod=viewthread&tid=813470&extra=page%3D1&page=1