运行分析
- 需要破解Serial1和Serial2
PE分析
- Delphi文件,32位,无壳
静态分析&动态调试
- 找到关键字符串(Delphi程序的字符串一般都在最下方),进入关键函数
int __usercall TForm1_Button1Click@<eax>(_DWORD *a1@<eax>, int a2@<ebx>)
{
char v3; // zf
int v5; // [esp-14h] [ebp-24h]
int v6; // [esp-14h] [ebp-24h]
int v7; // [esp-14h] [ebp-24h]
int v8; // [esp-14h] [ebp-24h]
unsigned int v9[2]; // [esp-10h] [ebp-20h] BYREF
int *v10; // [esp-8h] [ebp-18h]
int v11; // [esp-4h] [ebp-14h]
int v12; // [esp+0h] [ebp-10h] BYREF
int Serial2; // [esp+4h] [ebp-Ch] BYREF
int Serial1; // [esp+8h] [ebp-8h] BYREF
int v15; // [esp+Ch] [ebp-4h] BYREF
int savedregs; // [esp+10h] [ebp+0h] BYREF
Serial2 = 0;
v12 = 0;
v11 = a2;
v10 = &savedregs;
v9[1] = (unsigned int)&loc_42D5AD;
v9[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)v9);
if ( dword_42F714
&& dword_42F718
&& (set(a1[120], &v15), v15) // v15 = Name
&& (set(a1[121], &Serial1), Serial1)
&& (set(a1[123], &Serial2), Serial2) )
{
if ( !dword_42F714 )
goto LABEL_20;
if ( !dword_42F718 )
goto LABEL_20;
sub_406550(dword_42F714, &v12);
v5 = v12;
set(a1[121], &v15); // v15 = Serial1
cmp(v5, v15);
if ( !v3 )
goto LABEL_20;
sub_406550(dword_42F718, &v12);
v6 = v12;
set(a1[123], &v15); // v15 = Serial2
cmp(v6, v15);
if ( v3 )
{
sub_42CA8C(&str_Hmmm_____Cracke[1]);
}
else
{
LABEL_20:
if ( dword_42F714 )
{
if ( dword_42F718 )
{
sub_406550(dword_42F714, &v12);
v7 = v12;
set(a1[121], &v15);
cmp(v7, v15);
if ( !v3 )
goto LABEL_16;
}
}
sub_406550(dword_42F718, &v12);
v8 = v12;
set(a1[123], &v15);
cmp(v8, v15);
if ( !v3 )
{
LABEL_16:
sub_42CA8C(&str_Nice_try____but[1]); // 成功弹窗
dword_42F714 = 0;
dword_42F718 = 0;
sub_419E10(a1[120], 0);
sub_419E10(a1[121], 0);
sub_419E10(a1[123], 0);
}
}
}
else
{
sub_42CA8C(&str_Fill_all_boxes_[1]); // 失败弹窗
dword_42F714 = 0;
dword_42F718 = 0;
sub_419E10(a1[120], 0);
sub_419E10(a1[121], 0);
sub_419E10(a1[123], 0);
}
__writefsdword(0, v9[0]);
v10 = (int *)&loc_42D5B4;
sub_403544(&v12);
return sub_403568(&Serial2, 3);
}
- 静态分析关键函数得出下列结论:
- 1、Name、Serial1、Serial2必须不为空,同时dword_42F714和dword_42F718两个地址的值也不能为空
- 2、sub_406550(dword_42F714, &v12)得到v12,v12要与Serial1相等
- 3、sub_406550(dword_42F718, &v12)得到v12,v12要与Serial2相等
- 4、猜测dword_42F714和dword_42F718应该与Name有关
- 使用x32dbg动态调试,在关键函数头下断点
- 在dword_42F714处下内存写入断点(在dword_42F714变化时跳转至运行位置)
- Name处输入A,跳转至该位置
- 用ida定位该位置,发现是switch函数
- 当输入Name每个字符时,根据输入字符的值对dword_42F714和dword_42F718进行计算
- 在sub_406550函数处下断点,输入Name和Serial运行
- dword_42F714的值为BA50,运行sub_406550后,得到栈中变量0226B604的值为47696
- BA50正好是47696的十六进制数,即sub_406550函数的作用是将dword_42F714的十六进制数转为十进制数
算法分析
Name = 'concealbear'
Serial1 = ''
Serial2 = ''
dword_42F714 = 0
dword_42F718 = 0
# switch函数
def switch(byte):
global dword_42F718
global dword_42F714
if ord(byte) == 8:
dword_42F714 = 0;
dword_42F718 = 0;
if ord(byte) == 0x41:
dword_42F714 += 1064;
dword_42F718 += 5648;
if ord(byte) == 0x42:
dword_42F714 += 726576;
dword_42F718 += 2;
if ord(byte) == 0x43:
dword_42F714 += 3462;
dword_42F718 += 9999;
if ord(byte) == 0x44:
dword_42F714 += 4516;
dword_42F718 += 74445628;
if ord(byte) == 0x45:
dword_42F714 += 73482;
dword_42F718 += 35644;
if ord(byte) == 0x46:
dword_42F714 += 15554;
dword_42F718 += 34328;
if ord(byte) == 0x47:
dword_42F714 += 254376;
dword_42F718 += 444444;
if ord(byte) == 0x48:
dword_42F714 += 37348;
dword_42F718 += 2615621;
if ord(byte) == 0x49:
dword_42F714 += 27458;
dword_42F718 += 3131331;
if ord(byte) == 0x4A:
dword_42F714 += 333476;
dword_42F718 += 12121212;
if ord(byte) == 0x4B:
dword_42F714 += 275546;
dword_42F718 += 71111;
if ord(byte) == 0x4C:
dword_42F714 += 1834457;
dword_42F718 += 76628;
if ord(byte) == 0x4D:
dword_42F714 += 10349;
dword_42F718 += 734348;
if ord(byte) == 0x4E:
dword_42F714 += 1025;
dword_42F718 += 897376628;
if ord(byte) == 0x4F:
dword_42F714 += 1652;
dword_42F718 += 3243223;
if ord(byte) == 0x50:
dword_42F714 += 156;
dword_42F718 += 8247348;
if ord(byte) == 0x51:
dword_42F714 += 342;
dword_42F718 += 236752;
if ord(byte) == 0x52:
dword_42F714 += 34343;
dword_42F718 += 783434;
if ord(byte) == 0x53:
dword_42F714 += 7635344;
dword_42F718 += 8734342;
if ord(byte) == 0x54:
dword_42F714 += 42344;
dword_42F718 += 78368;
if ord(byte) == 0x55:
dword_42F714 += 87442;
dword_42F718 += 12334;
if ord(byte) == 0x56:
dword_42F714 += 7641;
dword_42F718 += 7235;
if ord(byte) == 0x57:
dword_42F714 += 15552;
dword_42F718 += 323528;
if ord(byte) == 0x58:
dword_42F714 += 9834;
dword_42F718 += 732523528;
if ord(byte) == 0x59:
dword_42F714 += 33553;
dword_42F718 += 7238;
if ord(byte) == 0x5A:
dword_42F714 += 52763;
dword_42F718 += 726628;
if ord(byte) == 0x61:
dword_42F714 += 1063;
dword_42F718 += 121;
if ord(byte) == 0x62:
dword_42F714 += 1724;
dword_42F718 += 111;
if ord(byte) == 0x63:
dword_42F714 += 1169;
dword_42F718 += 738;
if ord(byte) == 0x64:
dword_42F714 += 18253;
dword_42F718 += 762;
if ord(byte) == 0x65:
dword_42F714 += 1024;
dword_42F718 += 14;
if ord(byte) == 0x66:
dword_42F714 += 1744;
dword_42F718 += 13;
if ord(byte) == 0x67:
dword_42F714 += 1661;
dword_42F718 += 12;
if ord(byte) == 0x68:
dword_42F714 += 1872;
dword_42F718 += 11;
if ord(byte) == 0x69:
dword_42F714 += 1084;
dword_42F718 += 99;
if ord(byte) == 0x6A:
dword_42F714 += 1892;
dword_42F718 += 888;
if ord(byte) == 0x6B:
dword_42F714 += 192;
dword_42F718 += 77;
if ord(byte) == 0x6C:
dword_42F714 += 10109;
dword_42F718 += 555;
if ord(byte) == 0x6D:
dword_42F714 += 2078;
dword_42F718 += 90;
if ord(byte) == 0x6E:
dword_42F714 += 3591;
dword_42F718 += 98;
if ord(byte) == 0x6F:
dword_42F714 += 142;
dword_42F718 += 7468;
if ord(byte) == 0x70:
dword_42F714 += 632432;
dword_42F718 += 575475;
if ord(byte) == 0x71:
dword_42F714 += 3415;
dword_42F718 += 648;
if ord(byte) == 0x72:
dword_42F714 += 24555;
dword_42F718 += 538;
if ord(byte) == 0x73:
dword_42F714 += 2224;
++dword_42F718;
if ord(byte) == 0x74:
dword_42F714 += 1211;
dword_42F718 += 64;
if ord(byte) == 0x75:
dword_42F714 += 2242;
dword_42F718 += 75;
if ord(byte) == 0x76:
dword_42F714 += 7334;
dword_42F718 += 78;
if ord(byte) == 0x77:
dword_42F714 += 9502;
dword_42F718 += 5;
if ord(byte) == 0x78:
dword_42F714 += 917;
dword_42F718 += 38;
if ord(byte) == 0x79:
dword_42F714 += 11539;
dword_42F718 += 8;
if ord(byte) == 0x7A:
dword_42F714 += 6400;
dword_42F718 += 456;
# 计算dword_42F714和dword_42F718
for i in Name:
switch(i)
Serial1 = str(dword_42F714)
Serial2 = str(dword_42F718)
print(Name + '的Serial1为:' + Serial1)
print(Name + '的Serial2为:' + Serial2)
- 输入任意Name,得到Serial1和Serial2,验证成功
- 注意输入Name的时候要逐个字符输入,不能复制粘贴,否则无法每个字符都触发switch函数