2017第二屆廣東省強網杯線上賽--Nonstandard

測試文件:http://static2.ichunqiu.com/icq/resources/fileupload/CTF/echunqiu/qwb/Nonstandard_26195e1832795caa18fd4c7cfbd56600.zipgit

 

1.準備

得到信息:github

  • 32位文件

 

2.IDA打開

int __cdecl main(int argc, const char **argv, const char **envp)
{
  FILE *v3; // eax
  FILE *v4; // eax
  FILE *v5; // eax
  char Buf[16]; // [esp+0h] [ebp-24h]
  __int64 v8; // [esp+10h] [ebp-14h]
  int v9; // [esp+18h] [ebp-Ch]
  __int16 v10; // [esp+1Ch] [ebp-8h]

  v9 = 0;
  _mm_storeu_si128((__m128i *)Buf, (__m128i)0i64);
  v10 = 0;
  v8 = 0i64;
  v3 = _iob_func();
  fputs("Place Input Flag:\n", v3 + 1);
  v4 = _iob_func();
  fgets(Buf, 29, v4);
  if ( sub_401480(Buf) == 1 )
  {
    v5 = _iob_func();
    fputs("yes\n", v5 + 1);
  }
  return 0;
}

 

3.代碼分析

打開 sub_401480(Buf)函數數組

 1 signed int __thiscall sub_401480(const char *this)
 2 {
 3   const char *v1; // esi
 4   const char *v2; // eax
 5   unsigned int v3; // eax
 6   unsigned int v4; // kr04_4
 7   signed int result; // eax
 8   char v6; // [esp+4h] [ebp-38h]
 9   char Dst; // [esp+5h] [ebp-37h]
10 
11   v6 = 0;
12   v1 = this;                                    // this爲輸入的字符串的地址,長度爲28,不包含最後的結束符
13   memset(&Dst, 0, 0x31u);                       // Dst爲大小爲49的空間
14   if ( strlen(v1) != 28 )                       // 輸入字符串長度爲28
15     goto LABEL_10;
16   v2 = sub_401070((int)v1, 28u);
17   strncpy_s(&v6, 0x32u, v2, 0x30u);
18   v3 = 0;
19   v4 = strlen(&v6);
20   if ( !v4 )
21     goto LABEL_10;
22   do
23   {
24     if ( byte_402120[v3] != *(&v6 + v3) )
25       break;
26     ++v3;
27   }
28   while ( v3 < v4 );
29   if ( v3 == 48 )
30     result = 1;
31   else
32 LABEL_10:
33     result = -1;
34   return result;
35 }

首先,我注意到第24行代碼的比較,byte_402120[]="AdtxA66nbbdxA71tUAE2AOlnnbtrAp1nQzGtAQGtrjC7===",這是一段被加密的字符串,而比較的v6數組來自v2,v2是函數sub_401070((int)v1, 28u)的返回值,傳入的v1是咱們的輸入字符串。函數

打開sub_401070((int)v1, 28u)測試

sub_401070((int)v1, 28u)

 

這段加密方式是base32this

引自:https://www.ichunqiu.com/writeup/detail/815編碼

 base64編碼是用64(2的6次方)個ASCII字符來表示256(2的8次方)個ASCII字符,也就是三位二進制數組通過編碼後變爲四位的ASCII字符顯示,長度比原來增長1/3。
 一樣,base32就是用32(2的5次方)個特定ASCII碼來表示256個ASCII碼。因此,5個ASCII字符通過base32編碼後會變爲8個字符(公約數爲40),長度增長3/5.不足8n用"="補足。
 base16就是用16(2的4次方)個特定ASCII碼錶示256個ASCII字符。1個ASCII字符通過base16編碼後會變爲2個字符,長度增長一倍。不足2n用"="補足加密

 

同時咱們關注到第41行代碼,sub_401000();函數spa

signed __int16 sub_401000()
{
  signed int v0; // eax
  int v1; // esi
  char *v2; // edx
  char v3; // cl
  signed __int16 result; // ax

  v0 = 1;
  do
  {
    byte_403020[v0] += 32;
    v0 += 2;
  }
  while ( v0 < 26 );
  v1 = 0;
  v2 = &aMnopqrstuvwxyz[13];
  do
  {
    v3 = byte_40301F[++v1];
    byte_40301F[v1] = *v2;
    *v2-- = v3;
  }
  while ( (signed int)v2 > (signed int)aMnopqrstuvwxyz );
  *(_DWORD *)&aMnopqrstuvwxyz[14] = '3567';
  result = '12';
  word_40303E = '12';
  byte_403040 = 0;
  return result;
}

這段函數將加密表從新生成,能夠在OD動態調試中得到3d

 

所以整體操做就是,將咱們輸入的字符串,使用新生成的加密表,base32加密,獲得AdtxA66nbbdxA71tUAE2AOlnnbtrAp1nQzGtAQGtrjC7===加密字符串

 

4.腳本獲取

使用anybase32包來解密:https://github.com/alanblevins/anybase32

from __future__ import print_function
import anybase32

arbitrary_alphabet = b"zYxWvUtSrQpOnMlKjIhGfEdCbA765321"

encoded = b"nAdtxA66nbbdxA71tUAE2AOlnnbtrAp1nQzGtAQGtrjC7"

flag = anybase32.decode(encoded, arbitrary_alphabet)

print(flag)

 

5.get flag!

flag{f1ag_1s_enc0de_bA3e32!}

相關文章
相關標籤/搜索