-
-
[原创]Hide Window Hotkey V2.5注册算法分析(适合新手)
-
-
[原创]Hide Window Hotkey V2.5注册算法分析(适合新手)
【文章标题】: Hide Window HotkeyV2.5注册算法分析
【文章作者】: TyroneKing
【作者邮箱】: tyroneking@126.com
【软件名称】: Hide Window Hotkey
【下载地址】: HWHSetup.rar
【KeyGen】: KeyGen.rar
【加壳方式】: ASPack 2.12 -> Alexey Solodovnikov
【保护方式】: 注册名+序列号
【编写语言】: Borland Delphi 6.0 - 7.0
【使用工具】: OD + PEiD+DeDe + MD5计算器+AspackDie+ IDA (可以不用,加强分析)
【操作平台】: WIN XP +SP3、 VC++6.0
【软件介绍】: 隐藏运行的窗口和应用程序软件。
【作者声明】: 只是为了学习,没有其他目的。失误之处敬请诸位大侠赐教!
【分析过程】
1、用PEiD查壳,为ASPack 2.12 -> Alexey Solodovnikov,用ESP定律很容易就可以脱壳了,不过这里还是用AspackDie,不对如何脱壳详说(我也是新手,脱一些简单的行,强壳,还得继续努力呀,:))。
2、用AspackDie脱壳,用PEiD查为Borland Delphi 6.0 - 7.0编写, KANAL 算法识别插件分析,软件用了MD5(地址004B549A)算法,用,直接运行脱壳后程序没啥反应,应该是自检验了。
3、用OD加载下bp GetFileSize 断点,程序中断在GetFileSize函数中,按Alt+F9返回程序领空 004030A1
MD5_CTX context;
long dtLength;
int i;
int len;
int j;
TCHAR *szKeyStr="5497312680";
TCHAR sTemp=' ';
TCHAR szName[MAXINPUTLEN]={0};
TCHAR szHash[MAXINPUTLEN]={0};
TCHAR szBuffer[MAXINPUTLEN]={0};
dtLength=GetDlgItemText(hWnd, IDC_TXT0, szName, sizeof(szName)/sizeof(TCHAR)+1);
len=strlen(szName);
if (len<=8)//长度判断
{
SetDlgItemText(hWnd, IDC_TXT1, "Name必须大于8位!");
return FALSE;
}
for(i=0;i < len; i++)//是否包含 空格
if(szName[i]==' ')
{
SetDlgItemText(hWnd, IDC_TXT1, "Name不能包含空格!");
return FALSE;
}
sTemp=szName[0];
i=1;
while(i<len)
{
if(sTemp==szName[i])
i++;
else
break;
}
if(i>=len)
{
SetDlgItemText(hWnd, IDC_TXT1, "Name不能为单一字符!");
return FALSE;
}
for(i=0;i < len -1; i++)
szName[i]=szName[i] | szName[i+1];
szName[len-1]=szName[len-1] | sTemp;//各字节进行 OR 运算
sTemp=szName[len-1];
for(i=len-1; i > 0 ;i--)
szName[i]=szName[i-1];
szName[0]=sTemp;//循环右移一字节
MD5Init(&context);
MD5Update(&context, szName, dtLength);//该函数里的MD5Transform函数变形了
MD5Final(szHash, &context);
for(i=0; i < 16; i++) // 将szHash[]中的16进制转换成字符形式显示
{
wsprintf(&szBuffer[i*2], "%02X", *(byte*)(szHash+i));
}//变形MD5
i=0;
len=0;
while(len<10 && i<32)
{
if(szBuffer[i]>='0' && szBuffer[i]<='9')
{
szName[len]=szBuffer[i];
len+=1;
}
i++;
}//取前10位数字
szName[len]='\0';
if(len<1)
{
SetDlgItemText(hWnd, IDC_TXT1,"注册码为空?!");
return TRUE;
}
sTemp=szName[len-1];
for(i=len-1; i > 0 ;i--)
szName[i]=szName[i-1];
szName[0]=sTemp;//循环右移一字节
for(i=0; i < len ;i++)
{
j=szName[i]-'0';
szName[i]=szKeyStr[j];//根据szName[i]值对取应szKeyStr值
}
SetDlgItemText(hWnd, IDC_TXT1,szName);
return TRUE;
00403097 |. 6A 00 PUSH 0 ; /pFileSizeHigh = NULL
00403099 |. 8B03 MOV EAX,DWORD PTR DS:[EBX] ; |
0040309B |. 50 PUSH EAX ; |hFile
0040309C |. E8 FBE1FFFF CALL <JMP.&kernel32.GetFileSize> ; \GetFileSize
004030A1 |. 8BF0 MOV ESI,EAX ; EAX=文件大小
……
004030C8 \. C3 RETN
004C4B86 |. E8 79DDF3FF CALL unpacked.00402904 ; 取文件大小
004C4B8B |. 3D 20A10700 CMP EAX,7A120 ; EAX为文件大小
004C4B90 |. 7E 15 JLE SHORT unpacked.004C4BA7 ; <=7A120则跳,原文件大小6E000,现EAX=1A2000没跳
004C4B92 |. 8D85 ACFEFFFF LEA EAX,DWORD PTR SS:[EBP-154] ; 将4C4B90跳为JMP,或将7A120改为比1A2000即可
004C4B98 |. E8 3FE3F3FF CALL unpacked.00402EDC
004C4B9D |. E8 62DDF3FF CALL unpacked.00402904
004C4BA2 |. E8 49F9F3FF CALL unpacked.004044F0 ; 该函数中调用ExitProcess,退出程序
004C4BA7 |> 8D85 ACFEFFFF LEA EAX,DWORD PTR SS:[EBP-154]
004B609C /. 55 PUSH EBP ; OKButton
……
004B60BE |. 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
004B60C1 |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C] ; TfrmRegister.eName
004B60C7 |. E8 5061FAFF CALL <Crack.TControl.GetText(TControl)> ; 这里函数名是作了标签的,具体是哪个函数参考DeDe
004B60CC |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; Tips:知道函数名后进入函数,按Shift+;(即输入冒号)给该函数作标签
004B60CF |. E8 ECE7F4FF CALL <Crack.@LStrLen(String)>
004B60D4 |. 83F8 08 CMP EAX,8
004B60D7 |. 7D 3E JGE SHORT Crack.004B6117 ; Name的长度<8 则提示错误
004B60D9 |. 6A 10 PUSH 10
004B60DB |. 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
004B60DE |. A1 30E74C00 MOV EAX,DWORD PTR DS:[4CE730]
004B60E3 |. E8 4005F5FF CALL <Crack.LoadResString(PResStringRec)>
004B60E8 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
004B60EB |. E8 D0E9F4FF CALL <Crack.@LStrToPChar(String)>
004B60F0 |. 50 PUSH EAX
004B60F1 |. 8D55 F4 LEA EDX,DWORD PTR SS:[EBP-C]
004B60F4 |. A1 C4E64C00 MOV EAX,DWORD PTR DS:[4CE6C4]
004B60F9 |. E8 2A05F5FF CALL <Crack.LoadResString(PResStringRec)> ; 在资源文件中提取“提示字符串”,避免通过字符串查找破解
004B60FE |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
004B6101 |. E8 BAE9F4FF CALL <Crack.@LStrToPChar(String)>
004B6106 |. 50 PUSH EAX ; |Text
004B6107 |. E8 5010F5FF CALL <JMP.&user32.GetActiveWindow> ; |[GetActiveWindow
004B610C |. 50 PUSH EAX ; |hOwner
004B610D |. E8 7A12F5FF CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004B6112 |. E9 4F010000 JMP Crack.004B6266
004B6117 |> 8D55 F0 LEA EDX,DWORD PTR SS:[EBP-10]
004B611A |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C] ; (初始 cpu 选择)
004B6120 |. E8 F760FAFF CALL <Crack.TControl.GetText(TControl)>
004B6125 |. 8B55 F0 MOV EDX,DWORD PTR SS:[EBP-10] ; 取Name
004B6128 |. B8 DC624B00 MOV EAX,Crack.004B62DC ; 空格 20H
004B612D |. E8 D2EAF4FF CALL <Crack.@LStrPos> ; Name是否包含空格
004B6132 |. 85C0 TEST EAX,EAX
004B6134 |. 7E 3E JLE SHORT Crack.004B6174 ; 不包含则跳
……
004B6174 |> 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C]
004B6177 |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C]
004B617D |. E8 9A60FAFF CALL <Crack.TControl.GetText(TControl)>
004B6182 |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
004B6185 |. E8 36E7F4FF CALL <Crack.@LStrLen(String)>
004B618A |. 8BF0 MOV ESI,EAX
004B618C |. 83EE 02 SUB ESI,2
004B618F |. 7C 36 JL SHORT Crack.004B61C7 ; Name的长度小于2,则错误
004B6191 |. 46 INC ESI ; /------------------------
004B6192 |. BF 02000000 MOV EDI,2
004B6197 |> 8D55 E0 /LEA EDX,DWORD PTR SS:[EBP-20]
004B619A |. 8B83 2C030000 |MOV EAX,DWORD PTR DS:[EBX+32C]
004B61A0 |. E8 7760FAFF |CALL <Crack.TControl.GetText(TControl)> ; 取Name
004B61A5 |. 8B45 E0 |MOV EAX,DWORD PTR SS:[EBP-20]
004B61A8 |. 8A4438 FF |MOV AL,BYTE PTR DS:[EAX+EDI-1] ; AL=Name[EDI-1]
004B61AC |. 50 |PUSH EAX
004B61AD |. 8D55 DC |LEA EDX,DWORD PTR SS:[EBP-24]
004B61B0 |. 8B83 2C030000 |MOV EAX,DWORD PTR DS:[EBX+32C]
004B61B6 |. E8 6160FAFF |CALL <Crack.TControl.GetText(TControl)>
004B61BB |. 8B45 DC |MOV EAX,DWORD PTR SS:[EBP-24]
004B61BE |. 5A |POP EDX
004B61BF |. 3A10 |CMP DL,BYTE PTR DS:[EAX] ; Name[EDI-1]与Name[0]比较
004B61C1 |. 75 04 |JNZ SHORT Crack.004B61C7
004B61C3 |. 47 |INC EDI ; 相等则 EDI+1
004B61C4 |. 4E |DEC ESI
004B61C5 |.^ 75 D0 \JNZ SHORT Crack.004B6197
004B61C7 |> 8D55 D8 LEA EDX,DWORD PTR SS:[EBP-28]
004B61CA |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C]
004B61D0 |. E8 4760FAFF CALL <Crack.TControl.GetText(TControl)>
004B61D5 |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
004B61D8 |. E8 E3E6F4FF CALL <Crack.@LStrLen(String)>
004B61DD |. 3BF8 CMP EDI,EAX
004B61DF |. 7E 3B JLE SHORT Crack.004B621C ; EDI>EAX 提示出错
004B61E1 |. 6A 10 PUSH 10 ; \若用户名为单一字符,出提示错误
……
004B621C |> 8D55 CC LEA EDX,DWORD PTR SS:[EBP-34]
004B621F |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C]
004B6225 |. E8 F25FFAFF CALL <Crack.TControl.GetText(TControl)> ; 取Name
004B622A |. 8B55 CC MOV EDX,DWORD PTR SS:[EBP-34]
004B622D |. 8BC3 MOV EAX,EBX
004B622F |. E8 CC020000 CALL Crack.004B6500 ; 计算Code
004B6234 |. 8D55 C8 LEA EDX,DWORD PTR SS:[EBP-38]
004B6237 |. 8B83 30030000 MOV EAX,DWORD PTR DS:[EBX+330]
004B623D |. E8 DA5FFAFF CALL <Crack.TControl.GetText(TControl)> ; 取假Code
004B6242 |. 8B55 C8 MOV EDX,DWORD PTR SS:[EBP-38]
004B6245 |. 8D83 38030000 LEA EAX,DWORD PTR DS:[EBX+338] ; 保假Code
004B624B |. E8 04E4F4FF CALL <Crack.@LStrAsg>
004B652D |. 837D F8 00 CMP DWORD PTR SS:[EBP-8],0
004B6531 |. 0F84 FB000000 JE Crack.004B6632 ; Name为空?
004B6537 |. 8D45 F4 LEA EAX,DWORD PTR SS:[EBP-C] ; /-----------
004B653A |. 8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8]
004B653D |. E8 56E1F4FF CALL <Crack.@LStrLAsg(void;void;void;v>
004B6542 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
004B6545 |. E8 76E3F4FF CALL <Crack.@LStrLen(String)> ; 取Name的长度
004B654A |. 8BF8 MOV EDI,EAX
004B654C |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C] ; Name
004B654F |. 8A00 MOV AL,BYTE PTR DS:[EAX] ; AL=Name[0]
004B6551 |. 8845 F3 MOV BYTE PTR SS:[EBP-D],AL
004B6554 |. 8BF7 MOV ESI,EDI ; ESI=Name的长度
004B6556 |. 4E DEC ESI
004B6557 |. 85F6 TEST ESI,ESI
004B6559 |. 7E 22 JLE SHORT Crack.004B657D
004B655B |. BB 01000000 MOV EBX,1
004B6560 |> 8D45 F4 /LEA EAX,DWORD PTR SS:[EBP-C]
004B6563 |. E8 B0E5F4FF |CALL <Crack.InternalUniqueString> ; UniqueString is used only in cases where an application casts a string to a PChar or PWideChar and then modifies the contents of the string.
004B6568 |. 8B55 F4 |MOV EDX,DWORD PTR SS:[EBP-C]
004B656B |. 8A541A FF |MOV DL,BYTE PTR DS:[EDX+EBX-1] ; DL=Name[EBX-1]
004B656F |. 8B4D F4 |MOV ECX,DWORD PTR SS:[EBP-C]
004B6572 |. 0A1419 |OR DL,BYTE PTR DS:[ECX+EBX] ; DL=Name[EBX-1] OR Name[EBX]
004B6575 |. 885418 FF |MOV BYTE PTR DS:[EAX+EBX-1],DL ; 结果存在[EBP-C]的EBX-1中
004B6579 |. 43 |INC EBX
004B657A |. 4E |DEC ESI
004B657B |.^ 75 E3 \JNZ SHORT Crack.004B6560 ; 处理完Len-1位了?
004B657D |> 8D45 F4 LEA EAX,DWORD PTR SS:[EBP-C]
004B6580 |. E8 93E5F4FF CALL <Crack.InternalUniqueString>
004B6585 |. 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]
004B6588 |. 8A543A FF MOV DL,BYTE PTR DS:[EDX+EDI-1] ; DL=Name的最后一位
004B658C |. 0A55 F3 OR DL,BYTE PTR SS:[EBP-D] ; 与004B6551对应,即Name[0]
004B658F |. 885438 FF MOV BYTE PTR DS:[EAX+EDI-1],DL ; DL=Name[Len-1] OR Name[0]
004B6593 |. 8D4D EC LEA ECX,DWORD PTR SS:[EBP-14] ; \--对Name的第i位与第i+1位(最后一位与第0位)进行OR运算
004B6596 |. 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C] ; 记为NameOR,这里="][_OOOKOOW"
004B6599 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
004B659C |. E8 C3000000 CALL Crack.004B6664 ; 第二层运算
[培训]科锐逆向工程师培训第53期2025年7月8日开班!