闲来无事,就找看雪2007Crackeme比赛的Crackme来练习一下~~~
拿到的第一个程序,“crackme_by_topmint.exe”,首先打开它熟悉一下。
连续输入2次,得到以上结果,我们可以得知,key的格式必须为xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx,以及一些提示字符串。
既然有了提示,那么就用IDA寻找一下String的位置。
运气挺好,在String-View中直接得到明文提示,转到IDA-View中,Ctrl+x回溯,往上滑动几下后来到关键函数StartAddress(),尝试F5分析一波~~~
DWORD __stdcall StartAddress(LPVOID lpThreadParameter)
{
HWND v1; // eax@1
int len_of_name; // ebx@1
HWND v4; // eax@3
int len_of_serial; // ebp@3
HWND v6; // eax@5
HWND v7; // eax@5
int sum_of_char; // edx@5
int j; // ecx@5
CHAR x; // al@6
signed int i; // edx@13
const CHAR *v12; // [sp-Ch] [bp-11Ch]@25
HWND v13; // [sp-8h] [bp-118h]@4
const CHAR *v14; // [sp-8h] [bp-118h]@25
CHAR name[256]; // [sp+10h] [bp-100h]@1
__int16 v16; // [sp+10Ch] [bp-4h]@1
char v17; // [sp+10Eh] [bp-2h]@1
EnableWindow(hWnd, 0);
memset(name, 0, 0xFCu);
v16 = 0;
v17 = 0;
v1 = GetDlgItem(hDlg, 1000);
len_of_name = GetWindowTextLengthA(v1);
if ( (unsigned int)len_of_name > 0xFF ) //name长度和255比较,大于则弹出错误提示
{
MessageBoxA(hDlg, aTheLengthOfThe, aError, 0x10u);
EnableWindow(hWnd, 1);
return 0;
}
v4 = GetDlgItem(hDlg, 1001);
len_of_serial = GetWindowTextLengthA(v4);
if ( len_of_serial ) //serial不为空
{
v6 = GetDlgItem(hDlg, 1000);
GetWindowTextA(v6, name, 255);
v7 = GetDlgItem(hDlg, 1001);
GetWindowTextA(v7, String, 100);
sum_of_char = 0;
j = 0;
if ( len_of_name <= 0 ) //serial长度小于等于0
{
LABEL_13:
for ( i = sum_of_char + 1; i > 7040; i >>= 2 )
;
dword_40AAB0 = i;
//进行serial格式对比
if ( len_of_serial == 39
&& byte_40AA08 == '-'
&& byte_40AA0D == '-'
&& byte_40AA12 == '-'
&& byte_40AA17 == '-'
&& byte_40AA1C == '-'
&& byte_40AA21 == '-'
&& byte_40AA26 == '-' )
{
sub_401640();
if ( dword_40AAB0 == dword_40AB5C ) //关键比较
{
MessageBoxA(hDlg, aWelcomeToHarbi, aWelcome, 0x40u);
v13 = hWnd;
}
else
{
MessageBoxA(hDlg, aTryAgainNeverG, aSorry, 0x10u);
v13 = hWnd;
}
goto LABEL_29;
}
v14 = aError;
v12 = aTheKeyMustBeXx;
}
else
{
while ( 1 )
{
//x遍历name,累加到sum_of_char
x = name[j];
if ( (x < '0' || x > '9') && (x < 'A' || x > 'Z') && (x < 'a' || x > 'z') )
break;
sum_of_char += x;
//当遍历name完成,则跳转到LABEL_13
if ( ++j >= len_of_name )
goto LABEL_13;
}
v14 = aError;
v12 = aTheNameContain;
}
MessageBoxA(hDlg, v12, v14, 0x10u);
v13 = hWnd;
}
else
{
MessageBoxA(hDlg, aPleaseInputThe, aError, 0x10u);
v13 = hWnd;
}
LABEL_29:
EnableWindow(v13, 1);
return 0;
}
F5分析得已经很明显了。程序首先判断name长度是否超过255,不超过则遍历name将其中的字符累加到sum_of_char中,然后跳转到LABEL_13。LABEL_13中,首先赋值i=sum_of_char+1,如果i>7040,i=i/4,否则i不变。接下来,将i赋值给dword_40AAB0,再进行serial格式判断,如果serial格式合格,最后再判断dword_40AAB0==dword_40AB5C,等于则成功。
由以上分析可知,我们目前不知道的是dword_40AB5C这个变量,所以上(OD)动态调试观察此处。
可以清楚的看到,经过004017ED . E8 4EFEFFFF call crackme_.00401640之后,40AB5C=0x1B80(7040),而40AAB0处依然是“Fucker”的累加之和+1---0x261。综上,最后需要name的累加之和=7039。
所以,得出一组code,name:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO
serial:1234-1234-1234-1234-2134-8520-7894-9632(serial随意)