先总体看看
int __usercall wmain@<eax>(int a1@<ebx>)
{
FILE *v1; // eax
FILE *v2; // eax
char v4; // [esp+3h] [ebp-405h]
char v5; // [esp+4h] [ebp-404h]
char v6; // [esp+5h] [ebp-403h]
char v7; // [esp+104h] [ebp-304h]
char v8; // [esp+105h] [ebp-303h]
char v9; // [esp+204h] [ebp-204h]
char v10; // [esp+205h] [ebp-203h]
char v11; // [esp+304h] [ebp-104h]
char v12; // [esp+305h] [ebp-103h]
printf("Come one! Crack Me~~~\n");
v11 = 0;
memset(&v12, 0, 0xFFu);
v9 = 0;
memset(&v10, 0, 0xFFu);
while ( 1 )
{
do
{
do
{
printf("user(6-16 letters or numbers):");// 输入用户名
scanf("%s", &v11);
v1 = (FILE *)sub_4024BE();
fflush(v1);
}
while ( !sub_401000(&v11) ); // 检查用户名合法性
printf("password(6-16 letters or numbers):");
scanf("%s", &v9); // 输入密码
v2 = (FILE *)sub_4024BE();
fflush(v2);
}
while ( !sub_401000(&v9) ); // 检查密码合法性
sub_401090(&v11); // 处理byte数组
v7 = 0;
memset(&v8, 0, 0xFFu);
v5 = 0;
memset(&v6, 0, 0xFFu);
v4 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&v7, &v5);
if ( sub_401830(a1, (int)&v11, &v9) ) // 处理用户名和密码
{
if ( v4 )
break;
}
printf(&v5);
}
printf(&v7);
return 0;
}
进入sub_401090
char *__cdecl sub_401090(char *a1)
{
char *result; // eax
char v2; // ST1F_1
char v3; // ST22_1
char v4; // ST20_1
signed int v5; // [esp+Ch] [ebp-18h]
char *v6; // [esp+10h] [ebp-14h]
char *v7; // [esp+14h] [ebp-10h]
signed int i; // [esp+18h] [ebp-Ch]
unsigned __int8 v9; // [esp+23h] [ebp-1h]
for ( i = 0; i < 256; ++i )
byte_416050[i] = i;
v5 = 0;
v9 = 0;
v6 = 0;
result = a1;
v7 = a1;
do
{
LOBYTE(result) = *v7;
v2 = *v7++;
}
while ( v2 );
while ( v5 < 256 )
{
v3 = byte_416050[v5];
v9 += v3 + a1[(_DWORD)v6];
v4 = byte_416050[v9];
++v6;
byte_416050[v9] = v3;
byte_416050[v5] = v4;
result = v6;
if ( (signed int)v6 >= v7 - (a1 + 1) )
v6 = 0;
++v5;
}
return result;
}
可以看到用户名a1没有被更改,改变的是byte数组
其中
v9 += v3 + a1[(_DWORD)v6];
v4 = byte_416050[v9];
非常不合理,因为随着v9在增大,一定会大于255,会造成数组越界,其实v9是个8位数,不会大于255,会循环下去
unsigned __int8 v9; // [esp+23h] [ebp-1h]
那打扰了。。。
bool __usercall sub_401830@<al>(int ebx0@<ebx>, int a1, const char *a2)
{
int v4; // [esp+18h] [ebp-22Ch]
signed int v5; // [esp+1Ch] [ebp-228h]
signed int v6; // [esp+28h] [ebp-21Ch]
unsigned int v7; // [esp+30h] [ebp-214h]
char v8; // [esp+36h] [ebp-20Eh]
char v9; // [esp+37h] [ebp-20Dh]
char v10; // [esp+38h] [ebp-20Ch]
unsigned __int8 v11; // [esp+39h] [ebp-20Bh]
unsigned __int8 v12; // [esp+3Ah] [ebp-20Ah]
char v13; // [esp+3Bh] [ebp-209h]
int v14; // [esp+3Ch] [ebp-208h]
char v15; // [esp+40h] [ebp-204h]
char v16; // [esp+41h] [ebp-203h]
char v17; // [esp+140h] [ebp-104h]
char v18; // [esp+141h] [ebp-103h]
v5 = 0;
v6 = 0;
v12 = 0;
v11 = 0;
v17 = 0;
memset(&v18, 0, 0xFFu);
v15 = 0;
memset(&v16, 0, 0xFFu);
v10 = 0;
v7 = 0;
v4 = 0;
while ( v7 < strlen(a2) )
{
if ( isdigit(a2[v7]) )
{
v9 = a2[v7] - 48; // 取原始数字
}
else if ( isxdigit(a2[v7]) )
{
if ( *(_DWORD *)(*(_DWORD *)(__readfsdword(0x30u) + 24) + 12) != 2 )
a2[v7] = 34;
v9 = (a2[v7] | 0x20) - 87; // 十六进制保留原始含义
}
else
{
v9 = ((a2[v7] | 0x20) - 97) % 6 + 10; // 其他小写处理后,%6 + 10
}
v10 = v9 + 16 * v10;
if ( !((signed int)(v7 + 1) % 2) ) // v7为奇数结算一次
{
*(&v15 + v4++) = v10;
ebx0 = v4;
v10 = 0;
}
++v7; // 总得来说,就是
// 前一位*16 + 后一位 = v15 的一位
// 换言之,就是v15 = 两个十六进制组合起来的值
}
while ( v6 < 8 )
{
v11 += byte_416050[++v12];
v13 = byte_416050[v12];
v8 = byte_416050[v11];
byte_416050[v11] = v13;
byte_416050[v12] = v8;
if ( *(_DWORD *)(__readfsdword(0x30u) + 104) & 0x70 )// 反调试
v13 = v11 + v12;
*(&v17 + v6) = byte_416050[(unsigned __int8)(v8 + v13)] ^ *(&v15 + v5);// 处理v17
if ( *(_DWORD *)(__readfsdword(0x30u) + 2) & 0xFF )// 反调试
{
v11 = -83;
v12 = 43;
}
sub_401710((int)&v17, (const char *)a1, v6++);// 反调试
v5 = v6;
if ( v6 >= (unsigned int)(&v15 + strlen(&v15) + 1 - &v16) )
v5 = 0;
}
v14 = 0;
sub_401470(ebx0, &v17, &v14); // 用v17处理v14
//这个函数说明v17 = dbappsec
return v14 == 43924;
}
其中__readfsdword(0x30u)是反调试
sub_401710()里的GetStartupInfoW(…)也是反调试
更多有关反调试的知识请看 ctfwiki
或者https://www.cnblogs.com/Crisczy/p/7575521.html
题目给了我们用户名welcomebeijing
说明byte数组是固定的,进一步说明处理v17的那行代码中
byte_416050[(unsigned __int8)(v8 + v13)]也是固定的
而v17我们有了,即可反推
我们不必自己计算这些值,直接让程序输入用户名跑起来即可得到
所以动态调试,注意绕过反调试
之后上python
box = [0x2a,0xd7,0x92,0xe9,0x53,0xe2,0xc4,0xcd]
a =[100,98,97,112,112,115,101,99]
for i in range(8):
print(hex(a[i]^box[i])[2:],end = '')
得出结果md5加密即可