crackMe
crackMe
- 首先查壳,发现无壳,且为exe32位程序
- 拖入IDA,F5反编译
int wmain()
{
FILE *v0; // eax
FILE *v1; // eax
char v3; // [esp+3h] [ebp-405h]
char v4; // [esp+4h] [ebp-404h] BYREF
char v5[255]; // [esp+5h] [ebp-403h] BYREF
char Format; // [esp+104h] [ebp-304h] BYREF
char v7[255]; // [esp+105h] [ebp-303h] BYREF
char v8; // [esp+204h] [ebp-204h] BYREF
char v9[255]; // [esp+205h] [ebp-203h] BYREF
char v10; // [esp+304h] [ebp-104h] BYREF
char v11[255]; // [esp+305h] [ebp-103h] BYREF
printf("Come one! Crack Me~~~\n");
v10 = 0;
memset(v11, 0, sizeof(v11));
v8 = 0;
memset(v9, 0, sizeof(v9));
while ( 1 )
{
do
{
do
{
printf("user(6-16 letters or numbers):");
scanf("%s", &v10);
v0 = (FILE *)sub_4024BE(); //返回指向数据off_414000的指针给v0
fflush(v0);
}
while ( !(unsigned __int8)sub_401000(&v10) );
printf("password(6-16 letters or numbers):");
scanf("%s", &v8);
v1 = (FILE *)sub_4024BE(); //返回指向数据off_414000的指针给v1
fflush(v1);
}
while ( !(unsigned __int8)sub_401000(&v8) );
sub_401090(&v10);
Format = 0;
memset(v7, 0, sizeof(v7));
v4 = 0;
memset(v5, 0, sizeof(v5));
v3 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&Format, &v4);
if ( (unsigned __int8)sub_401830(&v10, &v8) )
{
if ( v3 )
break;
}
printf(&v4);
}
printf(&Format);
return 0;
}
- 函数首先定义了许多变量,然后将用户输入的user放入char变量v10中,将password放入v8中,进入sub_401000函数,发现其他函数,这几个函数应该是检查字母和数字的
char __cdecl sub_401000(const char *a1)
{
signed int v2; // [esp+8h] [ebp-10h]
signed int i; // [esp+Ch] [ebp-Ch]
v2 = strlen(a1);
for ( i = 0; i < v2; ++i )
{
if ( !isalnum(a1[i]) )
return 0;
}
return 1;
}
- 观察sub_401090函数,应该是对byte_416050进行赋值
BYTE *__cdecl sub_401090(_BYTE *a1)
{
_BYTE *result; // eax
int v2; // [esp+Ch] [ebp-18h]
int v3; // [esp+10h] [ebp-14h]
_BYTE *v4; // [esp+14h] [ebp-10h]
int i; // [esp+18h] [ebp-Ch]
char v7; // [esp+20h] [ebp-4h]
char v8; // [esp+22h] [ebp-2h]
unsigned __int8 v9; // [esp+23h] [ebp-1h]
for ( i = 0; i < 256; ++i )
byte_416050[i] = i;
v2 = 0;
v9 = 0;
v3 = 0;
result = a1;
v4 = a1;
do
LOBYTE(result) = *v4;
while ( *v4++ );
while ( v2 < 256 )
{
v8 = byte_416050[v2];
v9 += v8 + a1[v3];
v7 = byte_416050[v9];
++v3;
byte_416050[v9] = v8;
byte_416050[v2] = v7;
result = (_BYTE *)v3;
if ( v3 >= v4 - (a1 + 1) )
v3 = 0;
++v2;
}
return result;
}
- 观察sub_401830函数,
bool __cdecl sub_401830(int a1, const char *a2)
{
int v3; // [esp+18h] [ebp-22Ch]
int v4; // [esp+1Ch] [ebp-228h]
int v5; // [esp+28h] [ebp-21Ch]
unsigned int v6; // [esp+30h] [ebp-214h]
char v7; // [esp+36h] [ebp-20Eh]
char v8; // [esp+37h] [ebp-20Dh]
char v9; // [esp+38h] [ebp-20Ch]
unsigned __int8 v10; // [esp+39h] [ebp-20Bh]
unsigned __int8 v11; // [esp+3Ah] [ebp-20Ah]
char v12; // [esp+3Bh] [ebp-209h]
int v13; // [esp+3Ch] [ebp-208h] BYREF
char v14; // [esp+40h] [ebp-204h] BYREF
char v15[255]; // [esp+41h] [ebp-203h] BYREF
char v16; // [esp+140h] [ebp-104h] BYREF
char v17[255]; // [esp+141h] [ebp-103h] BYREF
v4 = 0;
v5 = 0;
v11 = 0;
v10 = 0;
v16 = 0;
memset(v17, 0, sizeof(v17));
v14 = 0;
memset(v15, 0, sizeof(v15));
v9 = 0;
v6 = 0;
v3 = 0;
while ( v6 < strlen(a2) )
{
if ( isdigit(a2[v6]) )
{
v8 = a2[v6] - 48;
}
else if ( isxdigit(a2[v6]) )
{
if ( *((_DWORD *)NtCurrentPeb()->SubSystemData + 3) != 2 )
a2[v6] = 34;
v8 = (a2[v6] | 0x20) - 87;
}
else
{
v8 = ((a2[v6] | 0x20) - 97) % 6 + 10;
}
__rdtsc();
__rdtsc();
v9 = v8 + 16 * v9;
if ( !((int)(v6 + 1) % 2) )
{
*(&v14 + v3++) = v9;
v9 = 0;
}
++v6;
}
while ( v5 < 8 )
{
v10 += byte_416050[++v11];
v12 = byte_416050[v11];
v7 = byte_416050[v10];
byte_416050[v10] = v12;
byte_416050[v11] = v7;
if ( ((int)NtCurrentPeb()->UnicodeCaseTableData & 0x70) != 0 )
v12 = v10 + v11;
*(&v16 + v5) = byte_416050[(unsigned __int8)(v7 + v12)] ^ *(&v14 + v4);
if ( (unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{
v10 = -83;
v11 = 43;
}
sub_401710(&v16, a1, v5++);
v4 = v5;
if ( v5 >= (unsigned int)(&v14 + strlen(&v14) + 1 - v15) )
v4 = 0;
}
v13 = 0;
sub_401470(&v16, &v13);
return v13 == 0xAB94;
}
IDA中各种前缀:https://www.jianshu.com/p/c0afd9186610
sub_ 指令和子函数起点
locret_ 返回指令
loc_ 指令
off_ 数据,包含偏移量
seg_ 数据,包含段地址值
asc_ 数据,ASCII字符串
byte_ 数据,字节(或字节数组)
word_ 数据,16位数据(或字数组)
dword_ 数据,32位数据(或双字数组)
qword_ 数据,64位数据(或4字数组)
flt_ 浮点数据,32位(或浮点数组)
dbl_ 浮点数,64位(或双精度数组)
tbyte_ 浮点数,80位(或扩展精度浮点数)
stru_ 结构体(或结构体数组)
algn_ 对齐指示
unk_ 未处理字节
IDA Pro7.0使用技巧总结:https://xz.aliyun.com/t/4205
C语言fflush()函数:清空文件缓冲区(或标准输入输出缓冲区)

浙公网安备 33010602011771号