运行分析
- 需要破解Name和Serial
PE分析
- 32位,未知程序,未知是否有壳
静态、动态分析
- ida发现关键字符串Yeah You Did It!!!
- 发现有个ACG.key,可能是注册文件,进入函数看看
注册
void __noreturn start()
{
HANDLE FileA; // eax
FileA = CreateFileA(FileName, 0x80000000, 0, 0, 3u, 0x80u, 0);// 读取ACG.key
if ( FileA != (HANDLE)-1 )
{
hFile = FileA;
if ( GetFileSize(FileA, 0) == 12 ) // ACG.key长度为12
{
lpBuffer = GlobalAlloc(0, 0xCu); // 定义lpBuffer
ReadFile(hFile, lpBuffer, 0xCu, &NumberOfBytesRead, 0);// LpBuffer = ACG.key内容
if ( __ROL4__(*(_BYTE *)lpBuffer ^ 0x1B, 2) == 360// 执行计算,result = ((byte[lpBuffer] ^ 0x1b) * 4) ^ 0x160
&& __ROL4__(*((_BYTE *)lpBuffer + 1) ^ 0x1B, 2) == 0x160
&& __ROL4__(*((_BYTE *)lpBuffer + 2) ^ 0x1B, 2) == 0x170
&& __ROL4__(*((_BYTE *)lpBuffer + 3) ^ 0x1B, 2) == 0xEC
&& __ROL4__(*((_BYTE *)lpBuffer + 4) ^ 0x1B, 2) == 0x13C
&& __ROL4__(*((_BYTE *)lpBuffer + 5) ^ 0x1B, 2) == 0x1CC
&& __ROL4__(*((_BYTE *)lpBuffer + 6) ^ 0x1B, 2) == 0x1F8
&& __ROL4__(*((_BYTE *)lpBuffer + 7) ^ 0x1B, 2) == 0xEC
&& __ROL4__(*((_BYTE *)lpBuffer + 8) ^ 0x1B, 2) == 0x164
&& __ROL4__(*((_BYTE *)lpBuffer + 9) ^ 0x1B, 2) == 0x1F8
&& __ROL4__(*((_BYTE *)lpBuffer + 10) ^ 0x1B, 2) == 0x1A0
&& __ROL4__(*((_BYTE *)lpBuffer + 11) ^ 0x1B, 2) == 0x1BC )
{
MessageBoxA(0, Text, Caption, 0); // 找不到ACG.key,则弹窗错误
}
}
}
hInstance = GetModuleHandleA(0);
DialogBoxParamA(hInstance, TemplateName, 0, DialogFunc, 0);// 进入Name和Serial判定函数
ExitProcess(0);
}
- 先读取同目录下ACG.key文件,长度必须为12
- ACG.key内容中每一位字符做运算,相等进入下一级段
CODE:00401068 ; 12: if ( __ROL4__(*(_BYTE *)lpBuffer ^ 0x1B, 2) == 360// 执行亦或计算
CODE:00401068 ; 13: && __ROL4__(*((_BYTE *)lpBuffer + 1) ^ 0x1B, 2) == 0x160
CODE:00401068 ; 14: && __ROL4__(*((_BYTE *)lpBuffer + 2) ^ 0x1B, 2) == 0x170
CODE:00401068 ; 15: && __ROL4__(*((_BYTE *)lpBuffer + 3) ^ 0x1B, 2) == 0xEC
CODE:00401068 ; 16: && __ROL4__(*((_BYTE *)lpBuffer + 4) ^ 0x1B, 2) == 0x13C
CODE:00401068 ; 17: && __ROL4__(*((_BYTE *)lpBuffer + 5) ^ 0x1B, 2) == 0x1CC
CODE:00401068 ; 18: && __ROL4__(*((_BYTE *)lpBuffer + 6) ^ 0x1B, 2) == 0x1F8
CODE:00401068 ; 19: && __ROL4__(*((_BYTE *)lpBuffer + 7) ^ 0x1B, 2) == 0xEC
CODE:00401068 ; 20: && __ROL4__(*((_BYTE *)lpBuffer + 8) ^ 0x1B, 2) == 0x164
CODE:00401068 ; 21: && __ROL4__(*((_BYTE *)lpBuffer + 9) ^ 0x1B, 2) == 0x1F8
CODE:00401068 ; 22: && __ROL4__(*((_BYTE *)lpBuffer + 10) ^ 0x1B, 2) == 0x1A0
CODE:00401068 ; 23: && __ROL4__(*((_BYTE *)lpBuffer + 11) ^ 0x1B, 2) == 0x1BC )
CODE:00401068 mov edi, ds:lpBuffer ; [edi] = lpBuffer,即读取ACG.key
CODE:0040106E xor ebx, ebx ; ebx = 0
CODE:00401070 mov bl, [edi] ; bl = edi单个字符
CODE:00401072 xor bl, 1Bh ; bl = bl ^ 0x1b
CODE:00401075 rol ebx, 2 ; 循环左移,ebx = ebx * 4,低位补0
CODE:00401078 xor ebx, 168h ; ebx = ebx ^ 0x168
CODE:0040107E test ebx, ebx
CODE:00401080 jnz loc_40117E
CODE:00401086 inc edi ; edi = edi + 1
CODE:00401087 mov bl, [edi] ; 以下为重复计算步骤
CODE:00401089 xor bl, 1Bh
CODE:0040108C rol ebx, 2
CODE:0040108F xor ebx, 160h
CODE:00401095 test ebx, ebx
CODE:00401097 jnz loc_40117E
- 分析汇编代码,得出关键计算步骤为ebx = ((ebx ^ 0x1b) * 4) = 0x160
- 逆向运算后,ebx = ( 0x160 / 4) ^ 0x1b
res = [0x168,0x160,0x170,0xEC,0x13C,0x1CC,0x1F8,0xEC,0x164,0x1F8,0x1A0,0x1BC]
key = ''
for i in range(len(res)):
key += chr((res[i] // 4) ^ 0x1b)
print(key)
- 写出逆向算法,得出ACG.key的值为ACG The Best
- 创建ACG.key后再运行exe文件,发现弹出已破解
继续破解Name和Serial
- ida找到字符串Yeah You Did It!!!,进入函数
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
INT_PTR result; // eax
HMODULE ModuleHandleA; // eax
CHAR *Name_; // edi
int Name_byte; // ebx
int Name_byte_plus; // eax
int Serial_byte; // ebx
int v10; // edi
CHAR *i; // esi
HWND DesktopWindow; // eax
int v13; // [esp-24h] [ebp-24h]
result = a2;
if ( (_WORD)a2 == 2 || (_WORD)a2 == 16 )
goto LABEL_6;
if ( (_WORD)a2 != 273 )
{
if ( (_WORD)a2 != 272 )
return 0;
dword_402012 = (int)LoadIconA(hInstance, (LPCSTR)0x69);
SendMessageA(hDlg, 0x80u, 0, dword_402012);
GetWindowRect(hDlg, &Rect);
DesktopWindow = GetDesktopWindow();
GetWindowRect(DesktopWindow, &stru_4020F6);
dword_4020F2 = Rect.bottom - Rect.top;
dword_4020EE = Rect.right - Rect.left;
return MoveWindow(
hDlg,
(unsigned int)(stru_4020F6.right - (Rect.right - Rect.left)) >> 1,
(unsigned int)(stru_4020F6.bottom - (Rect.bottom - Rect.top)) >> 1,
Rect.right - Rect.left,
Rect.bottom - Rect.top,
0);
}
if ( a3 != 1003 )
{
if ( a3 != 1005 )
{
if ( a3 == 1004 )
return MessageBoxA(hDlg, aHiToJeTrailCra, Caption, 0);
return result;
}
LABEL_6:
if ( ++dword_40231C == 1 )
sub_40141F();
return EndDialog(hDlg, 0);
}
if ( *(&loc_401246 + 1) != 0x84 )
{
MessageBoxA(hDlg, aGdzieMiGrzebie, Caption, 0);
goto LABEL_6;
}
ModuleHandleA = GetModuleHandleA(ModuleName);
if ( *(_BYTE *)GetProcAddress(ModuleHandleA, ProcName) == 0xCC )
{
MessageBoxA(hDlg, aNoBpxAllowedIO, Caption, 0);
}
else if ( GetDlgItemTextA(hDlg, 1001, Name, 40) >= 5 )// 获取Name,长度要>= 5
{
GetDlgItemTextA(hDlg, 1002, Serial, 40); // 获取Serial
Name_ = Name;
Name_byte = 0;
Name_byte_plus = 0;
while ( (unsigned __int8)*Name_ >= 32u ) // name的ascii值需要大于32
{
LOBYTE(Name_byte) = *Name_; // Name_byte = Name单个字符的值
Name_byte_plus += Name_byte; // Name_byte_plus为所有Name的值相加
if ( !*++Name_ ) // 当Name到达最后一位时执行
{
v13 = __ROL4__(Name_byte_plus, 3) ^ 0x515A5;// v13 = (Name_byte_plus * 8) ^ 0x515a5
Serial_byte = 0;
v10 = 0;
for ( i = Serial; ; ++i ) // i = Serial地址
{
LOBYTE(Serial_byte) = *i; // Serial_byte = Serial单个字符的值
if ( !Serial_byte )
break;
if ( (unsigned __int8)Serial_byte < 48u || (char)Serial_byte > 57 )// 不能执行此跳转,Serial_byte的ascii值要在48~57之间,即数字0-9
goto LABEL_25;
Serial_byte -= 48;
v10 = Serial_byte + 10 * v10;
}
if ( (v10 ^ 0x87CA) + v13 == 0x797E7 )
{
MessageBoxA(hDlg, aYeahYouDidItCz, Caption, 0);// 破解成功弹窗
return v13;
}
break;
}
}
}
LABEL_25:
MessageBoxA(hDlg, aNicZTego, Caption, 0x10u);
SetDlgItemTextA(hDlg, 1002, &byte_4020DD);
return v13;
}
- 分析函数,前面的不重要,从获取Name和Serial处开始分析
- Name每个字符ascii相加,在通过运算得到v13 =(Name_byte_plus * 8) ^ 0x515a5
- Serial每个字符ascii通过运算v10 += Serial_byte + 10 * v10
- 验算(v10 ^ 0x87CA) + v13 == 0x797E7,相等则注册成功
算法分析
Name = 'concealbear'
Serial = ''
# 计算v13
Name_byte_plus = 0
for i in range(len(Name)):
Name_byte_plus += ord(Name[i])
v13 = (Name_byte_plus * 8) ^ 0x515A5
# 计算v10
v10 = (0x797E7 - v13) ^ 0x87CA
# 爆破Serial,暂定长度为1-7
for Serial_byte1 in range(0,10):
for Serial_byte2 in range(0, 10):
for Serial_byte3 in range(0, 10):
for Serial_byte4 in range(0, 10):
for Serial_byte5 in range(0, 10):
for Serial_byte6 in range(0, 10):
for Serial_byte7 in range(0, 10):
v10 = (((((((((Serial_byte1 * 10) + Serial_byte2) * 10) +Serial_byte3) *10) + Serial_byte4) * 10) + Serial_byte5) * 10 + Serial_byte6) * 10 + Serial_byte7
# print(v10)
if (v10 ^ 0x87CA) + v13 == 0x797E7:
Serial = str(Serial_byte1) + str(Serial_byte2) + str(Serial_byte3) + str(Serial_byte4) + str(Serial_byte5) + str(Serial_byte6)+ str(Serial_byte7)
print(Name + "的Serial为:\n"+Serial)
exit()
- 首先确定Name,暂定Serial为7位,再通过爆破的方式得出Serial
- 输入任意Name,执行算法得到Serial,验证成功