测试文件:https://www.lanzous.com/iaxqvbg
1 int __usercall wmain@<eax>(int a1@<ebx>) 2 { 3 FILE *v1; // eax 4 FILE *v2; // eax 5 char v4; // [esp+3h] [ebp-405h] 6 char v5; // [esp+4h] [ebp-404h] 7 char v6; // [esp+5h] [ebp-403h] 8 char v7; // [esp+104h] [ebp-304h] 9 char v8; // [esp+105h] [ebp-303h] 10 char v9; // [esp+204h] [ebp-204h] 11 char v10; // [esp+205h] [ebp-203h] 12 char v11; // [esp+304h] [ebp-104h] 13 char v12; // [esp+305h] [ebp-103h] 14 15 printf("Come one! Crack Me~~~\n"); 16 v11 = 0; // user 17 memset(&v12, 0, 0xFFu); 18 v9 = 0; // password 19 memset(&v10, 0, 0xFFu); 20 while ( 1 ) 21 { 22 do 23 { 24 do 25 { 26 printf("user(6-16 letters or numbers):"); 27 scanf("%s", &v11); 28 v1 = (FILE *)file_ptr(); // 文件流指针 29 fflush(v1); // 更新缓存 30 } 31 while ( !check_len_str(&v11) ); // 判断输入长度和类型是否符合要求 32 printf("password(6-16 letters or numbers):"); 33 scanf("%s", &v9); 34 v2 = (FILE *)file_ptr(); 35 fflush(v2); 36 } 37 while ( !check_len_str(&v9) ); 38 sub_401090(&v11); 39 v7 = 0; 40 memset(&v8, 0, 0xFFu); 41 v5 = 0; 42 memset(&v6, 0, 0xFFu); 43 v4 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&v7, &v5); 44 if ( sub_401830(a1, (int)&v11, &v9) ) 45 { 46 if ( v4 ) 47 break; 48 } 49 printf(&v5); 50 } 51 printf(&v7); 52 return 0; 53 }
前面的代码不需要说什么,主要分析sub_401830函数,应该是需要我们返回True的
1 bool __usercall sub_401830@<al>(int ebx0@<ebx>, int a1, const char *a2) 2 { 3 int v4; // [esp+18h] [ebp-22Ch] 4 signed int v5; // [esp+1Ch] [ebp-228h] 5 signed int v6; // [esp+28h] [ebp-21Ch] 6 unsigned int v7; // [esp+30h] [ebp-214h] 7 char v8; // [esp+36h] [ebp-20Eh] 8 char v9; // [esp+37h] [ebp-20Dh] 9 char v10; // [esp+38h] [ebp-20Ch] 10 unsigned __int8 v11; // [esp+39h] [ebp-20Bh] 11 unsigned __int8 v12; // [esp+3Ah] [ebp-20Ah] 12 char v13; // [esp+3Bh] [ebp-209h] 13 int v14; // [esp+3Ch] [ebp-208h] 14 char v15; // [esp+40h] [ebp-204h] 15 char v16; // [esp+41h] [ebp-203h] 16 char v17; // [esp+140h] [ebp-104h] 17 char v18; // [esp+141h] [ebp-103h] 18 19 v5 = 0; 20 v6 = 0; 21 v12 = 0; 22 v11 = 0; 23 v17 = 0; 24 memset(&v18, 0, 0xFFu); 25 v15 = 0; 26 memset(&v16, 0, 0xFFu); 27 v10 = 0; 28 v7 = 0; 29 v4 = 0; 30 while ( v7 < strlen(a2) ) 31 { 32 if ( isdigit(a2[v7]) ) // 判断密码是不是数字 33 { 34 v9 = a2[v7] - 48; // 字符转整型 35 } 36 else if ( isxdigit(a2[v7]) ) // 检测是否为16进制数字 37 { 38 if ( *(_DWORD *)(*(_DWORD *)(__readfsdword(0x30u) + 24) + 12) != 2 ) 39 a2[v7] = 34; 40 v9 = (a2[v7] | 0x20) - 87; // 转为整型数字 41 } 42 else 43 { 44 v9 = ((a2[v7] | 0x20) - 97) % 6 + 10; // 按照字母次序,6个一组,对应10~15 45 } 46 v10 = v9 + 16 * v10; 47 if ( !((signed int)(v7 + 1) % 2) ) 48 { 49 *(&v15 + v4++) = v10; // 存储a2偶数位变换后v9的值 50 ebx0 = v4; 51 v10 = 0; 52 } 53 ++v7; 54 } 55 while ( v6 < 8 ) // 进行某种变换 56 { 57 v11 += byte_416050[++v12]; 58 v13 = byte_416050[v12]; 59 v8 = byte_416050[v11]; 60 byte_416050[v11] = v13; 61 byte_416050[v12] = v8; 62 if ( *(_DWORD *)(__readfsdword(0x30u) + 104) & 0x70 ) 63 v13 = v11 + v12; 64 *(&v17 + v6) = byte_416050[(unsigned __int8)(v8 + v13)] ^ *(&v15 + v5);// v17的生成,通过byte_416050和v15异或 65 if ( *(_DWORD *)(__readfsdword(0x30u) + 2) & 0xFF ) 66 { 67 v11 = -83; 68 v12 = 43; 69 } 70 sub_401710((int)&v17, (const char *)a1, v6++); 71 v5 = v6; 72 if ( v6 >= (unsigned int)(&v15 + strlen(&v15) + 1 - &v16) ) 73 v5 = 0; 74 } 75 v14 = 0; 76 sub_401470(ebx0, &v17, &v14); 77 return v14 == 43924; 78 }
整体这个函数我们可以分成三部分
我们能够反过来推倒,首先查看sub_401470函数
_DWORD *__usercall sub_401470@<eax>(int a1@<ebx>, _BYTE *a2, _DWORD *a3) { int v3; // ST28_4 int v4; // ecx _DWORD *_EAX; // eax int v6; // edx int v8; // ST20_4 int v9; // eax int v10; // edi int v11; // ST1C_4 int v12; // edx char v13; // di int v14; // ST18_4 int v15; // eax int v16; // ST14_4 int v17; // edx char v18; // al int v19; // ST10_4 int v20; // ecx char _AL; // al int v23; // ST0C_4 int v24; // eax _DWORD *result; // eax int v26; // edx if ( *a2 == ‘d‘ ) { *a3 |= 4u; v4 = *a3; } else { *a3 ^= 3u; } v3 = *a3; if ( a2[1] == ‘b‘ ) { _EAX = a3; *a3 |= 0x14u; v6 = *a3; } else { *a3 &= 0x61u; _EAX = (_DWORD *)*a3; } __asm { aam } if ( a2[2] == ‘a‘ ) { *a3 |= 0x84u; v9 = *a3; } else { *a3 &= 0xAu; } v8 = *a3; v10 = ~(a1 >> -91); if ( a2[3] == ‘p‘ ) { *a3 |= 0x114u; v12 = *a3; } else { *a3 >>= 7; } v11 = *a3; v13 = v10 - 1; if ( a2[4] == ‘p‘ ) { *a3 |= 0x380u; v15 = *a3; } else { *a3 *= 2; } v14 = *a3; if ( *(_DWORD *)(*(_DWORD *)(__readfsdword(0x30u) + 24) + 12) != 2 ) { if ( a2[5] == ‘f‘ ) { *a3 |= 0x2DCu; v17 = *a3; } else { *a3 |= 0x21u; } v16 = *a3; } if ( a2[5] == ‘s‘ ) { *a3 |= 0xA04u; v18 = (char)a3; v20 = *a3; } else { v18 = (char)a3; *a3 ^= 0x1ADu; } v19 = *a3; _AL = v18 - v13; __asm { daa } if ( a2[6] == ‘e‘ ) { *a3 |= 0x2310u; v24 = *a3; } else { *a3 |= 0x4Au; } v23 = *a3; if ( a2[7] == ‘c‘ ) { result = a3; *a3 |= 0x8A10u; v26 = *a3; } else { *a3 &= 0x3A3u; result = (_DWORD *)*a3; } return result; }
应该是需要我们满足其中的每一个条件,因此得到v17的值"dbappsec"
有了v17的值,我们知道第二部分代码第64行,通过byte_416050与变换后的密码异或得到v17。我们已知账号为welcomebeijing,求密码。因此我们需要通过动态调试,获取byte_416050的值
记录下byte_416050的值为
0x2a, 0xd7, 0x92, 0xe9, 0x53, 0xe2, 0xc4, 0xcd
变换后的密码格式为两两组成的十六进制
# -*- coding:utf-8 -*- import hashlib box = [0x2a, 0xd7, 0x92, 0xe9, 0x53, 0xe2, 0xc4, 0xcd] s = "dbappsec" secret = [] for i in range(len(s)): secret.append(hex(ord(s[i])^box[i]).replace("0x",‘‘)) flag = ‘‘.join(secret) md = hashlib.md5() md.update(flag.encode(‘utf-8‘)) print ("flag{"+md.hexdigest()+"}")
flag{d2be2981b84f2a905669995873d6a36c}
原文:https://www.cnblogs.com/Mayfly-nymph/p/12624018.html