2020易霖博杯——Re題目部分WP

文章目錄

re1

拿到程序以後拖進IDA裏shift+F12看一下:
在這裏插入圖片描述
雙擊跟進去,查看一下交叉引用,F5轉一下僞代碼就出來了:
在這裏插入圖片描述
flag爲:flag{Sign_fDfkl_CTF}}

re2與re3

目前網上仍沒有公佈WP,當時參賽選手都沒解出來...

re4

拖IDA看一下,發現是ELF文件:
在這裏插入圖片描述
看一下main()函數的僞代碼:
在這裏插入圖片描述

這是main()函數的僞代碼:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int i; // [esp+20h] [ebp-28h]
  char s[17]; // [esp+2Bh] [ebp-1Dh]
  unsigned int v6; // [esp+3Ch] [ebp-Ch]

  v6 = __readgsdword(0x14u);
  memcpy(&password, "IKAWTEQWJHQTVRCF", 0x10u);		//初始化password
  memset(s, 0, 0x11u);
  printf("Enter the password: ");
  __isoc99_scanf("%16s", s);						//獲取鍵盤輸入的16個字符
  for ( i = 0; i <= 15; ++i )						//將字符串放入循環
    s[i] = complex_function(s[i], 18 - i);			//這裏是重點,將字符串存到s這個數組裏,並調用complex_function()這個函數進行處理,然後在返回到s裏。
  if ( check_equals_IKAWTEQWJHQTVRCF(s, 16) )		//這裏調用check_equals_IKAWTEQWJHQTVRCF()函數對處理後的password進行最多16次判斷
    puts("Good Job.");								//若結果爲真則輸出Good job.
  else
    puts("Try again.");								//若結果爲假則輸出Try again.
  return 0;
}

我們在看一下它對我們輸入的password進行了怎樣的處理,也就是看一下complex_function()函數:
在這裏插入圖片描述
簡單分析一下:

int __cdecl complex_function(signed int a1, int a2)
{
  if ( a1 <= 64 || a1 > 90 )	//password對應的十進制只能在64~90之間
  {
    puts("Try again.");			//若超出64~90則輸出Try again.
    exit(1);					//運行到這裏直接結束當前進程
  }
  return (a1 - 65 + 29 * a2) % 26 + 65;	//如果語句沒有執行,那麼passwd經過處理後返回
}

接着我們分析它調用check_equals_IKAWTEQWJHQTVRCF()進行的判斷:
在這裏插入圖片描述

分析一下僞代碼,這裏a1就是經過處理後的password,a2是16:

_BOOL4 __cdecl check_equals_IKAWTEQWJHQTVRCF(int a1, unsigned int a2)
{
  int v3; // [esp+8h] [ebp-8h]
  unsigned int i; // [esp+Ch] [ebp-4h]

  v3 = 0;							//定義一個局部變量v3用來存值
  for ( i = 0; a2 > i; ++i )		//開始循環,每次循環結束i進行自加,最多循環16次
  {
    if ( *(_BYTE *)(i + a1) == *(_BYTE *)(i + 0x804C038) )	//這裏是對原password跟處理後的password進行對比,如果相等就執行下面的語句,如果不相等就直接跳出去
      ++v3;							//相等後進行自加
  }
  return v3 == a2;					
}
/**
這裏return v3 == a2的作用我感覺就是把結果轉成0或1,
然後存到eax裏,進行判斷後選擇跳或者不跳,如果程序成功執行了16次,
也就是v3 == a2成立,那麼結果就是0,反之爲1
**/

這是check_equals_IKAWTEQWJHQTVRCF()函數執行後的流程圖,這裏如果jnz判斷不成立,也就是eax爲0,那麼就輸出"Good job.“反之輸出"Try again.”,跟我們分析的一樣:
在這裏插入圖片描述
在這裏插入圖片描述
分析到這裏我們就有解題思路了,有兩種解題方法:

  1. 從complex_function()函數下手,直接爆破一下加密後的password。
  2. 從check_equals_IKAWTEQWJHQTVRCF()函數下手,破解程序。

這裏還是爆破比較方便,也比較簡單:

passwd = 'IKAWTEQWJHQTVRCF'		#定義原passwd
flag = ''  						#定義flag用來存值
for i in range(len(passwd)):	#返回passwd的長度,也就是16
    for a1 in range(64,91):		#把64~90依次傳給a1
        if (a1 - 65 + (18-i)*29)%26 + 65 == ord(passwd[i]):  #如果經過計算後a1的十進制結果如果等於原passwd的十進制結果
            flag += chr(a1)  								 #那麼將結果依次轉爲對應的ASCII碼賦值給flag
  
print('flag{%s}'%(flag))			#輸出flag

成功拿到flag:flag{GLEDDRGPFGSYDCQW}

re5

這題我看流程圖感覺是將輸入的內容進行異或,然後將異或的結果進行判斷,若結果爲真則結束進程,若爲假則輸出“err…"並結束進程:

這是它main()函數的僞代碼
在這裏插入圖片描述這裏的關鍵就是在sub_400606()這個函數,它的僞代碼非常複雜,很多個循環語句嵌套,水平實在是不夠,分析不了,如果有大牛能分析或者感興趣,私信我一起學習一下!

上一下sub_400606()函數的僞代碼:

__int64 __fastcall sub_400606(signed int *a1)
{
  signed __int64 v1; // rax
  __int64 result; // rax
  int v3; // [rsp+10h] [rbp-10h]
  __int16 v4; // [rsp+14h] [rbp-Ch]

  *a1 = 0;
  do
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                do
                {
                  v1 = *((_QWORD *)a1 + 1) + 6LL * *a1;
                  v3 = *(_DWORD *)v1;
                  v4 = *(_WORD *)(v1 + 4);
                  ++*a1;
                }
                while ( BYTE1(v3) && BYTE1(v3) != a1[1] );
                result = (unsigned __int8)v3;
                if ( (unsigned __int8)v3 != 7 )
                  break;
                *a1 = *(signed __int16 *)(2LL * SHIWORD(v3) + *((_QWORD *)a1 + 2));
              }
              if ( (signed int)result > 7 )
                break;
              if ( (_DWORD)result == 3 )
              {
                if ( *(_WORD *)(2LL * SHIWORD(v3) + *((_QWORD *)a1 + 2)) == *(_WORD *)(2LL * v4 + *((_QWORD *)a1 + 2)) )
                  a1[1] = 1;
                else
                  a1[1] = 2;
              }
              else if ( (signed int)result > 3 )
              {
                if ( (_DWORD)result == 5 )
                {
                  *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *(_WORD *)(2LL * v4 + *((_QWORD *)a1 + 2));
                }
                else if ( (signed int)result > 5 )
                {
                  *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *a1;
                }
                else
                {
                  *a1 += SHIWORD(v3);
                }
              }
              else if ( (_DWORD)result == 1 )
              {
                *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *(_WORD *)(2LL * SHIWORD(v3) + *((_QWORD *)a1 + 2))
                                                                    + *(_WORD *)(2LL * v4 + *((_QWORD *)a1 + 2));
              }
              else if ( (_DWORD)result == 2 )
              {
                *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *(_WORD *)(2LL * SHIWORD(v3) + *((_QWORD *)a1 + 2))
                                                                    - *(_WORD *)(2LL * v4 + *((_QWORD *)a1 + 2));
              }
            }
            if ( (_DWORD)result != 10 )
              break;
            *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *((_WORD *)a1
                                                                  + *(signed __int16 *)(2LL * v4 + *((_QWORD *)a1 + 2))
                                                                  + 8LL
                                                                  + 4);
          }
          if ( (signed int)result > 10 )
            break;
          if ( (_DWORD)result == 8 )
          {
            *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = v4;
          }
          else if ( (_DWORD)result == 9 )
          {
            puts("err..");
          }
        }
        if ( (_DWORD)result != 12 )
          break;
        *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *(_WORD *)(2LL * SHIWORD(v3) + *((_QWORD *)a1 + 2)) ^ *(_WORD *)(2LL * v4 + *((_QWORD *)a1 + 2));
      }
      if ( (signed int)result >= 12 )
        break;
      *(_WORD *)(*((_QWORD *)a1 + 2) + 2LL * SHIWORD(v3)) = *((_WORD *)a1
                                                            + *(signed __int16 *)(2LL * v4 + *((_QWORD *)a1 + 2))
                                                            + 32LL);
    }
  }
  while ( (_DWORD)result != 255 );
  return result;
}

這道題目前網上沒有什麼分析,只有一個解題腳本,也是通過異或試出來的:

a=[0x003C, 0x0030, 0x003F, 0x0007, 0x0019, 0x0012, 0x0000, 0x001E, 0x0018, 0x001A, 0x001A, 0x0042, 0x0046, 0x0010, 0x0010, 0x0010, 0x0014, 0x001F, 0x000C, 0x00FD]  
x=90  
for i in a:  
    print(chr(i^x),end='')  
    x+=2    

運行後成功獲得flag:flag{vfvrvt24dfhncr}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章