运行分析
- 需要破解Hard Coded和Name+Serial
PE分析
- ASM程序,32位,无壳
静态分析&动态调试
Hard Coded
- ida发现关键字符串,进入Hard Code函数
LRESULT __stdcall sub_401178(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam)
{
const char *v4; // eax
CHAR *i; // ebx
switch ( Msg )
{
case 2u:
PostQuitMessage(0);
break;
case 1u:
CreateWindowExA(0, aStatic, aHardCoded, 0x50000080u, 10, 2, 100, 25, hWndParent, (HMENU)6, hInstance, 0);
CreateWindowExA(0, aStatic, aName, 0x50000080u, 10, 65, 100, 25, hWndParent, (HMENU)7, hInstance, 0);
CreateWindowExA(0, aStatic, aSerial, 0x50000080u, 10, 105, 100, 25, hWndParent, (HMENU)7, hInstance, 0);
hWnd = CreateWindowExA(0x200u, aEdit, 0, 0x50800080u, 101, 0, 175, 25, hWndParent, (HMENU)3, hInstance, 0);
dword_403494 = CreateWindowExA(
0x200u,
aEdit,
0,
0x50800080u,
101,
60,
175,
25,
hWndParent,
(HMENU)4,
hInstance,
0);
dword_403498 = CreateWindowExA(
0x200u,
aEdit,
0,
0x50800080u,
101,
100,
175,
25,
hWndParent,
(HMENU)5,
hInstance,
0);
SetFocus(hWnd);
dword_403488 = (int)CreateWindowExA(
0,
aButton,
aCheckHardcoded,
0x50000001u,
75,
30,
140,
25,
hWndParent,
(HMENU)1,
hInstance,
0);
dword_40348C = (int)CreateWindowExA(
0,
aButton,
aNameSerialChec,
0x50000001u,
75,
130,
140,
25,
hWndParent,
(HMENU)2,
hInstance,
0);
break;
case 0x111u:
if ( (_WORD)wParam == 1 ) // 第一个按钮
{
if ( !HIWORD(wParam) )
{
GetWindowTextA(hWnd, String, 32); // 获得Hard Code
v4 = "HardCoded";
for ( i = String; ; ++i )
{
if ( !*v4 )
{
MessageBoxA(0, "Congratulations, you got the hard coded serial", Caption, 0);
return 0;
}
if ( *v4 != *i ) // Hard Code = "HardCoded"
break;
++v4;
}
MessageBoxA(0, aSorryPleaseTry, Caption, 0);
}
}
else if ( (_WORD)wParam == 2 ) // 第二个按钮
{
if ( !HIWORD(wParam) )
sub_4015E4(dword_403494, dword_403498);// Name和Serial函数
}
else if ( wParam == 1000 )
{
SendMessageA(hWndParent, 0x112u, 0xF060u, 0);
}
else if ( wParam == 1100 )
{
MessageBoxA(0, aYourMissionIsT, Caption, 0);
}
break;
default:
return DefWindowProcA(hWndParent, Msg, wParam, lParam);
}
return 0;
}
- Hard Coded明文出现了,为HardCoded
Name & Serial
- 通过sub_4015E4(dword_403494, dword_403498);进入Name和Serial判断函数
int __stdcall sub_4015E4(HWND a1, HWND hWnd)
{
int WindowTextA; // eax
int v3; // eax
int v4; // ebx
int v5; // edx
int v6; // ebx
int i; // ebx
WindowTextA = GetWindowTextA(hWnd, Serial, 32);
if ( !WindowTextA )
return MessageBoxA(0, aPleaseEnterYou_0, Caption, 0);// 弹窗'Please enter your serial number.'
dword_403467 = WindowTextA;
v3 = GetWindowTextA(a1, Name, 11); // Name最大取11位
if ( !v3 )
return MessageBoxA(0, aPleaseEnterYou, Caption, 0);// 弹窗'Please enter your name.'
Name_length = v3;
v4 = 0;
do
{
v5 = (v4 ^ (Name[v4] % 10)) + 2;
if ( (char)v5 >= 10 )
LOBYTE(v5) = (v4 ^ (Name[v4] % 10)) - 8;
res_Name[v4++] = v5;
}
while ( v4 != Name_length ); // 通过上述计算得到res_Name
v6 = 0;
do
{
res_Serial[v6] = Serial[v6] % 10;
++v6;
}
while ( v6 != dword_403467 ); // 通过上述计算得到res_Serial
for ( i = 0; ; ++i )
{
if ( i == Name_length )
return MessageBoxA(0, aGoodJobNowKeyg, Caption, 0);// 弹窗'Good job, now keygen it.'
if ( res_Name[i] != res_Serial[i] ) // 若res_Name == res_Serial,则弹出上面弹窗
break;
}
return MessageBoxA(0, aSorryPleaseTry, Caption, 0);// 弹窗'Sorry, please try again.'
}
- 通过一系列计算得到res_Name和res_Serial
- 若res_Name == res_Serial,则弹窗破解成功
算法分析
Name = 'concealbear'
Serial = ''
res_Name = []
res_Serial = []
# 通过Name计算res_Name
for v4 in range(len(Name)):
v5 = (v4 ^ (ord(Name[v4]) % 10)) + 2
if (v5 >= 10):
v5 = (v4 ^ (ord(Name[v4]) % 10)) - 8
res_Name.append(v5)
# 逆向计算Serial
res_Serial = res_Name
for i in range(len(res_Serial)):
res_Serial[i] = res_Serial[i] + 100 # 因为是求余,res_Serial都是各位数字,ascii码值中个位数字+100都是小写字母
Serial += chr(res_Serial[i])
print(Name + '的Serial为:\n' + Serial)
- 通过算法,输入任意Name得到Serial,验证成功