[SCTF2019]creakme

查阅资料:

https://www.anquanke.com/post/id/181019#h3-16

https://blog.csdn.net/orbit/article/details/1497457

https://blog.csdn.net/qq_41071646/article/details/93536419

这道题看了好久,没看懂意思,后面看了师傅们的wp才看懂,原来是aes加密,并且对aes进行了一番学习

先贴下主函数的源码

  1 int sub_402540()
  2 {
  3   HMODULE v0; // eax
  4   int v1; // eax
  5   _DWORD *v2; // eax
  6   unsigned int v3; // edx
  7   _DWORD *v4; // ecx
  8   unsigned int v5; // ebx
  9   char *v6; // edi
 10   unsigned int v7; // esi
 11   unsigned int v8; // esi
 12   bool v9; // cf
 13   unsigned __int8 v10; // al
 14   unsigned __int8 v11; // al
 15   unsigned __int8 v12; // al
 16   signed int v13; // esi
 17   _BYTE *v14; // ecx
 18   _BYTE *v15; // ecx
 19   const char *v16; // edx
 20   int v17; // eax
 21   void *Memory; // [esp+10h] [ebp-70h]
 22   int v20; // [esp+20h] [ebp-60h]
 23   unsigned int v21; // [esp+24h] [ebp-5Ch]
 24   void *Dst; // [esp+28h] [ebp-58h]
 25   int v23; // [esp+38h] [ebp-48h]
 26   unsigned int v24; // [esp+3Ch] [ebp-44h]
 27   char Src; // [esp+40h] [ebp-40h]
 28   int v26; // [esp+7Ch] [ebp-4h]
 29 
 30   v0 = GetModuleHandleW(0);
 31   sub_402320(v0);
 32   sub_4024A0();
 33   v1 = sub_402870(std::cout, "welcome to 2019 sctf");
 34   std::basic_ostream<char,std::char_traits<char>>::operator<<(v1, sub_402AC0);
 35   sub_402870(std::cout, "please input your ticket:");
 36   sub_402AF0(std::cin, &Src);
 37   v23 = 0;
 38   v24 = 15;
 39   LOBYTE(Dst) = 0;
 40   sub_401D30(&Dst, &Src, strlen(&Src));
 41   v26 = 0;
 42   v2 = (_DWORD *)sub_4020D0(&Memory, &Dst);
 43   v3 = strlen(aPvfqyc4ttc2uxr);
 44   v4 = v2;
 45   if ( v2[5] >= 0x10u )
 46     v4 = (_DWORD *)*v2;
 47   v5 = v2[4];
 48   v6 = aPvfqyc4ttc2uxr;
 49   v7 = v2[4];
 50   if ( v3 < v5 )
 51     v7 = v3;
 52   v9 = v7 < 4;
 53   v8 = v7 - 4;
 54   if ( v9 )
 55   {
 56 LABEL_8:
 57     if ( v8 == -4 )
 58       goto LABEL_17;
 59   }
 60   else
 61   {
 62     while ( *v4 == *(_DWORD *)v6 )
 63     {
 64       ++v4;
 65       v6 += 4;
 66       v9 = v8 < 4;
 67       v8 -= 4;
 68       if ( v9 )
 69         goto LABEL_8;
 70     }
 71   }
 72   v9 = *(_BYTE *)v4 < (unsigned __int8)*v6;
 73   if ( *(_BYTE *)v4 != *v6
 74     || v8 != -3
 75     && ((v10 = *((_BYTE *)v4 + 1), v9 = v10 < (unsigned __int8)v6[1], v10 != v6[1])
 76      || v8 != -2
 77      && ((v11 = *((_BYTE *)v4 + 2), v9 = v11 < (unsigned __int8)v6[2], v11 != v6[2])
 78       || v8 != -1 && (v12 = *((_BYTE *)v4 + 3), v9 = v12 < (unsigned __int8)v6[3], v12 != v6[3]))) )
 79   {
 80     v13 = -v9 | 1;
 81     goto LABEL_18;
 82   }
 83 LABEL_17:
 84   v13 = 0;
 85 LABEL_18:
 86   if ( !v13 )
 87   {
 88     if ( v3 <= v5 )
 89       v13 = v3 < v5;
 90     else
 91       v13 = -1;
 92   }
 93   if ( v21 >= 0x10 )
 94   {
 95     v14 = Memory;
 96     if ( v21 + 1 >= 0x1000 )
 97     {
 98       v14 = (_BYTE *)*((_DWORD *)Memory - 1);
 99       if ( (unsigned int)((_BYTE *)Memory - v14 - 4) > 0x1F )
100         invalid_parameter_noinfo_noreturn(v14, v21 + 36);
101     }
102     sub_402F05(v14);
103   }
104   v26 = -1;
105   v20 = 0;
106   v21 = 15;
107   LOBYTE(Memory) = 0;
108   if ( v24 >= 0x10 )
109   {
110     v15 = Dst;
111     if ( v24 + 1 >= 0x1000 )
112     {
113       v15 = (_BYTE *)*((_DWORD *)Dst - 1);
114       if ( (unsigned int)((_BYTE *)Dst - v15 - 4) > 0x1F )
115         invalid_parameter_noinfo_noreturn(v15, v24 + 36);
116     }
117     sub_402F05(v15);
118   }
119   v16 = "Have fun!";
120   if ( v13 )
121     v16 = "A forged ticket!!";
122   v17 = sub_402870(std::cout, v16);
123   std::basic_ostream<char,std::char_traits<char>>::operator<<(v17, sub_402AC0);
124   system("pause");
125   return 0;
126 }
View Code

 

看起来很麻烦

进入函数sub_401D30里面看看,发现其是结构体在第20个字节后,便是字符串的长度size,然后其余的便是赋值。

再进入函数sub_4020D0里面看看,发现了这些

 

 

 

 

 

 

 可以发现这是一个aes的加密,由于函数sub_401690和函数sub_4013E0都有一个相同的参数,所以猜测这个v31是密钥(其实我点进去分析了,看了一阵子,太长了,不过看到赋值操作和偏移,感觉还是有点感觉的,汇编和C的代码审计还是有点拉胯)

 

不过既然知道是aes加密,那么从可以分析出,这是与前一个密文进行异或,这里进行加密

 

所以先异或后加密,每次都会执行便可以判断是CBC加密模式

 

然后查看v31这个函数发现里面有一个全局变量,给其赋值,

 

 

 

并且该函数还把也赋值进了v31的偏移,所以这两个里面有一个是key有一个是vi,把其化为字符串就可以发现xmmword_407360是sctfsctfsctfsctf看起来更像vi向量点,但在解密的时候,并没有解出来,后面感觉是动态加载的,想进入调试器调试,可是他有检测调试的方法,看了别的师傅的wp也没明白是什么,只知道一个名词SMP技术,然后就去查了一下,可惜没查出什么,不过我想了一下既然他是在放出字符串之前进行的动态加载,那么我是不是等他字符串出来后再去附加进程就可以了呢?果不其然!

 

 

然后拿着这串密文去解密

 

 

 本题感悟:写的题好少,目前写题都需要查许多资料,说明自己在知识储备上的不足,这道题就是一个明显的体现,其次需要加深对加密代码的映象,所以我选择的方法是逆一遍自己写的加密算法并写出其解密算法来进行训练,其次是加深汇编的功底和逆向的效率这两个一直都是我的致命缺点

 

posted @ 2020-09-24 22:16  PYozo_free  阅读(694)  评论(0编辑  收藏  举报