查閱資料:
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 }
看起來很麻煩
進入函數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技術,然后就去查了一下,可惜沒查出什么,不過我想了一下既然他是在放出字符串之前進行的動態加載,那么我是不是等他字符串出來后再去附加進程就可以了呢?果不其然!
然后拿着這串密文去解密
本題感悟:寫的題好少,目前寫題都需要查許多資料,說明自己在知識儲備上的不足,這道題就是一個明顯的體現,其次需要加深對加密代碼的映象,所以我選擇的方法是逆一遍自己寫的加密算法並寫出其解密算法來進行訓練,其次是加深匯編的功底和逆向的效率這兩個一直都是我的致命缺點