1. Prepare
get information:
- 32 files
2.IDA Open
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. Code Analysis
Open sub_401480 (Buf) function
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 charDST; // [ESP + 5H] [EBP-37h] 10 . 11 V6 = 0 ; 12 is V1 = the this ; // the this address for the input character string, a length of 28, do not contain the ending character 13 is Memset (& Dst , 0 , 0x31u ); // Dst is the size of the space 49 14 IF (strlen (V1) =! 28 ) // input a string of 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 }
First of all, I note that the first 24 lines of code comparison, byte_402120 [] = "AdtxA66nbbdxA71tUAE2AOlnnbtrAp1nQzGtAQGtrjC7 ===", which is encrypted string section, and from a comparison of the array v6 v2, v2 is a function sub_401070 ((int) v1, 28u) return value is passed v1 our input string.
Open sub_401070 ((int) v1, 28u)
This encryption method is base32
Quoted from: https://www.ichunqiu.com/writeup/detail/815
base64 encoding is 64 (6th power of 2) ASCII characters to represent 256 (2 ^ 8) of ASCII characters, i.e. three encoded binary array after the display becomes four ASCII characters in length than the original increased by a third.
Similarly, base32 is to use 32 (fifth power of 2) two specific ASCII code 256 to indicate the ASCII code. So, five ASCII characters after base32 encoded becomes 8 characters (divisor 40), increase the length of 3/5. 8n insufficient use "=" to make up.
base16 256 ASCII characters is represented by 16 (2 to the power 4) -th specific ASCII code. After a base16 encoded ASCII characters will become two characters in length doubled. Less than 2n with "=" complement
At the same time we are concerned that the first 41 lines of code, sub_401000 (); function
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; }
This function will regenerate encryption table, available in OD dynamic debugging
Therefore, the overall operation is, will we enter the string, using the encryption table, base32 encryption newly generated, get AdtxA66nbbdxA71tUAE2AOlnnbtrAp1nQzGtAQGtrjC7 === encrypted string
4. The script gets
Use anybase32 package to decrypt: 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!}