主要就是在sub_91830这个函数里面
上面部分是对密码进行一个变换,就是将字符转换为对应的十进制数字,然后存储到v16中
while ( v7 < strlen(password) )
{
if ( isdigit(password[v7]) ) // 数字,0-9
{
v9 = password[v7] - 48;
}
else if ( isxdigit(password[v7]) ) // 检测是否是16进制字符,即A-F
{
if ( *((_DWORD *)NtCurrentPeb()->ProcessHeap + 3) != 2 )
password[v7] = 34;
v9 = (password[v7] | 0x20) - 87;
}
else
{
v9 = ((password[v7] | 0x20) - 97) % 6 + 10;// 字母
}
__rdtsc();
__rdtsc();
v10 = v9 + 16 * v10;
if ( !((int)(v7 + 1) % 2) ) // 奇数
{
v16[v4++ - 1] = v10;
a1 = v4;
v10 = 0;
}
++v7;
}
下面就是对v16进行变换,其中byte_A6050的值是通过username来得到的,可以动调出来,经过一系列变换后最终变换的结果存储到v17中
while ( v6 < 8 )
{
v11 += byte_A6050[++v12];
v13 = byte_A6050[v12];
v8 = byte_A6050[v11];
byte_A6050[v11] = v13;
byte_A6050[v12] = v8;
if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )
v13 = v11 + v12;
v17[v6] = byte_A6050[(unsigned __int8)(v8 + v13)] ^ v16[v5 - 1];// v16是password变换后的
if ( !(unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{
v11 = -83;
v12 = 43;
}
sub_91710((int)v17, (const char *)username, v6++);
v5 = v6;
if ( v6 >= (unsigned int)(&v16[strlen(&v15)] - v16) )// v6 >= 4
v5 = 0;
}
v14 = 0;
sub_91470(a1, v17, &v14); // 检测flag是否正确
return v14 == 0xAB94;
}
byte_A6050的值
这里可以得到v17的值 dbappsec 或者 dbappfec
unsigned int *__usercall sub_91470@<eax>(int a1@<ebx>, _BYTE *a2, unsigned int *a3)
{
char v5; // al
unsigned int *result; // eax
if ( *a2 != 'd' )
*a3 ^= 3u;
else
*a3 |= 4u;
if ( a2[1] != 'b' )
{
*a3 &= 0x61u;
_EAX = *a3;
}
else
{
_EAX = (unsigned int)a3;
*a3 |= 0x14u;
}
__asm { aam }
if ( a2[2] != 'a' )
*a3 &= 0xAu;
else
*a3 |= 0x84u;
if ( a2[3] != 'p' )
*a3 >>= 7;
else
*a3 |= 0x114u;
if ( a2[4] != 'p' )
*a3 *= 2;
else
*a3 |= 0x380u;
if ( *((_DWORD *)NtCurrentPeb()->ProcessHeap + 3) != 2 )
{
if ( a2[5] != 'f' )
*a3 |= 0x21u;
else
*a3 |= 0x2DCu;
}
if ( a2[5] != 's' )
{
v5 = (char)a3;
*a3 ^= 0x1ADu;
}
else
{
*a3 |= 0xA04u;
v5 = (char)a3;
}
_AL = v5 - (~(a1 >> 5) - 1);
__asm { daa }
if ( a2[6] != 'e' )
*a3 |= 0x4Au;
else
*a3 |= 0x2310u;
if ( a2[7] != 'c' )
{
*a3 &= 0x3A3u;
return (unsigned int *)*a3;
}
else
{
result = a3;
*a3 |= 0x8A10u;
}
return result;
}
在异或的地方下断点,记录byte_7D6050[eax] 的值,即cl的值
这里if语句里面都是检测动态调试的,可以看这个反调试 - PEB(BeingDebugged ,NtGlobalFlag)
if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )
v13 = v11 + v12;
v17[v6] = byte_A6050[(unsigned __int8)(v8 + v13)] ^ v16[v5 - 1];// v16是password变换后的
if ( !(unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{
v11 = -83;
v12 = 43;
}
用ida动调的时候都是会直接跳过的,就不用修改了,直接执行就好
if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )
v13 = v11 + v12;
if ( !(unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{
v11 = -83;
v12 = 43;
}
直接挨个记录cl的值就好,得到的值为:{0x2A,0xD7,0x92,0xE9,0x53,0xE2,0xC4,0xCD}
写个脚本解密
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main()
{
int a[] = {0x2A,0xD7,0x92,0xE9,0x53,0xE2,0xC4,0xCD};
char b1[] = "dbappsec";
for(int i = 0 ; i < 8 ; i++)
{
printf("%x",a[i] ^ b1[i]);
}
return 0;
}
“dbappsec” 解密结果为: 4eb5f3992391a1ae md5加密结果 d2be2981b84f2a905669995873d6a36c,试一下刚好是最终flag,
最终flag:flag{d2be2981b84f2a905669995873d6a36c}