vovsoft Text Edit Plus v14 离线激活
vovsoft Text Edit Plus v14
程序信息text-edit
Text Edit Plus https://vovsoft.com/software/text-edit-plus/
Version: 14.7
PE32
操作系统: Windows(2000)[I386, 32 位, GUI]
链接程序: Turbo Linker(2.25*,Delphi)[GUI32,signed]
编译器: Embarcadero Delphi(10.3 Rio)[Professional]
语言: Object Pascal(Delphi)
签名工具: Windows Authenticode(2.0)[PKCS #7]
附加: Binary
证书: WinAuth(2.0)[PKCS #7]
证书: WinAuth(2.0)[PKCS #7]
Delphi程序,IDR 启动!
程序联网会进行网络校验,联网一定不通过!包括离线注册的时侯
定位按钮事件
NagScreen: TNagScreen
关注‘ok’ 按钮事件
TNagScreen.BitBtn3Click
object BitBtn3: TSpeedButton
Left = 1
Top = 1
Width = 198
Height = 37
Align = alClient
Caption = 'OK'
Flat = True
Font.Charset = DEFAULT_CHARSET
Font.Color = clWhite
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
OnClick = BitBtn3Click
ExplicitLeft = 2
ExplicitTop = 17
ExplicitWidth = 183
ExplicitHeight = 39
end
点击ok后激活计时器
int __fastcall TNagScreen_BitBtn3Click(int a1)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v15 = 0;
v14 = 0;
v13 = 0;
v11 = &savedregs;
v10 = &loc_9A2CC5;
ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)&ExceptionList);
Mask::TCustomMaskEdit::GetText(*(Mask::TCustomMaskEdit **)(a1 + 0x428));
if ( (unsigned __int8)Siteedit::TSiteActionsListEditorHelper::GetFieldsList(v17, L" ") )
{
sub_9A611C((int)L"Activation", (int)&v14);
v8 = UStrToPWChar(v14);
sub_9A611C((int)L"Please enter your license key!", (int)&v13);
v6 = (const WCHAR *)UStrToPWChar(v13);
TApplication_MessageBox(*Application, v6, v8, 0x10u);
}
else
{
LOWORD(v2) = 0xFFED;
sub_67A55C(*Screen, v2, v3, v12, v11, v10, ExceptionList);
TControl_SetColor(*(_DWORD *)(a1 + 0x42C), 0xFF00000F);
// mov eax,dword ptr [ebx+430];TNagScreen.BitBtn3:TSpeedButton
// …………
// call dword ptr [ecx+94];TControl.SetEnabled
(*(void (__fastcall **)(_DWORD, _DWORD))(**(_DWORD **)(a1 + 0x430) + 0x94))(*(_DWORD *)(a1 + 0x430), 0);
// license key
Mask::TCustomMaskEdit::GetText(*(Mask::TCustomMaskEdit **)(a1 + 0x428));
Trim(v15, &v16);
UStrAsg(license_key_BB2A20, v16, v4);
ischecker_created_over_00BACF6C = 0;
LOBYTE(v5) = 1;
// mov eax,dword ptr [ebx+3EC];TNagScreen.TimerActivator:TTimer
TTimer_SetEnabled_5F9D74(*(_DWORD *)(a1 + 0x3EC), v5);
}
__writefsdword(0, (unsigned int)ExceptionList);
v11 = (int *)&loc_9A2CCC;
UStrArrayClr(&v13, 2);
UStrClr(&v15);
UStrClr(&v16);
return UStrClr(&v17);
}
TNagScreen.TimerContinueTimer
Continue
?网络校验时?
TNagScreen.TimerActivatorTimer
负责创建TChecker校验线程和响应激活结果
int __fastcall TNagScreen_TimerActivatorTimer(Forms::TCustomForm *this)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v24[1] = (unsigned int)&loc_9A4322;
v24[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)v24);
if ( ischecker_created_over_00BACF6C )
{
if ( *ptr_is_TRIAL_BB2B7C == 1 )
{
TTimer_SetEnabled_5F9D74(*((_DWORD *)this + 0xFB), 0);
if ( *off_BB2698 == 1 )
{
gvar_00BACF70 = 1;
sub_9A611C((int)L"Activation", (int)&v49);
v23 = UStrToPWChar(v49);
sub_9A611C((int)L"Thank you!", (int)&v47);
v22 = v47;
sub_9A611C((int)L"Product successfully activated.", (int)&v46);
v17 = v46;
UStrCatN(&v48, 4);
v3 = (const WCHAR *)UStrToPWChar(v48);
TApplication_MessageBox(*Application, v3, v17, (UINT)L"\r");
if ( *off_BB2694[0] == 1 )
{
LOBYTE(v4) = 1;
TMenuItem_SetVisible(*(_DWORD *)(*gvar_00BB20D4 + 0x694), v4);
LOBYTE(v5) = 1;
TMenuItem_SetEnabled(*(_DWORD *)(*gvar_00BB20D4 + 0x694), v5);
if ( !*gvar_00BB1FC0 )
TMenuItem_SetChecked(*(_DWORD *)(*gvar_00BB20D4 + 0x694), 0);
}
TCustomForm_Close(this);
}
else if ( !*ptr_Activation_success_00BB1CBC
|| (*(unsigned __int8 (__fastcall **)(_DWORD))(**((_DWORD **)this + 0xFE) + 0x130))(*((_DWORD *)this + 0xFE)) )
{
if ( *ptr_Activation_success_00BB1CBC
&& (*(unsigned __int8 (__fastcall **)(_DWORD))(**((_DWORD **)this + 0xFE) + 0x130))(*((_DWORD *)this + 0xFE)) == 1 )
{
sub_9A611C((int)L"Activation", (int)&v32);
v23 = UStrToPWChar(v32);
sub_9A611C((int)aActivationFail, (int)&v30);
v22 = v30;
sub_9A611C((int)L"License key is invalid!", (int)&v29);
v19 = v29;
UStrCatN(&v31, 4);
v10 = (const WCHAR *)UStrToPWChar(v31);
TApplication_MessageBox(*Application, v10, v19, (UINT)L"\r");
}
else
{
sub_9A611C((int)L"Activation", (int)&v28);
v23 = UStrToPWChar(v28);
sub_9A611C((int)aActivationFail, (int)&v26);
v22 = v26;
sub_9A611C((int)L"License key is invalid!", (int)&v25);
v20 = v25;
UStrCatN(&v27, 4);
v11 = (const WCHAR *)UStrToPWChar(v27);
TApplication_MessageBox(*Application, v11, v20, (UINT)L"\r");
}
}
else if ( *ptr_RESPONSE_BB1E94 )
{
UStrEqual(*ptr_RESPONSE_BB1E94, L"INVALIDSERVERRESPONSE");
if ( v7 )
{
sub_9A611C((int)L"Activation", (int)&v41);
v23 = UStrToPWChar(v41);
sub_9A611C((int)aActivationFail, (int)&v39);
v22 = v39;
sub_9A611C((int)L"The server returned an invalid response.", (int)&v38);
v21 = v38;
sub_9A611C((int)L"Please try again later!", (int)&v37);
v16 = v37;
UStrCatN(&v40, 6);
v8 = (const WCHAR *)UStrToPWChar(v40);
TApplication_MessageBox(*Application, v8, v16, (UINT)L"\r");
}
else
{
sub_9A611C((int)L"Activation", (int)&v36);
v23 = UStrToPWChar(v36);
sub_9A611C((int)aActivationFail, (int)&v34);
v22 = v34;
v21 = L"\r";
sub_9A611C((int)L"Please check your internet connection!", (int)&v33);
v15 = *ptr_RESPONSE_BB1E94;
UStrCatN(&v35, 7);
v9 = (const WCHAR *)UStrToPWChar(v35);
TApplication_MessageBox(*Application, v9, v15, (UINT)L"\r");
}
}
else
{
sub_9A611C((int)L"Activation", (int)&v45);
v23 = UStrToPWChar(v45);
sub_9A611C((int)aActivationFail, (int)&v43);
v22 = v43;
sub_9A611C((int)L"Please check your internet connection!", (int)&v42);
v18 = v42;
UStrCatN(&v44, 4);
v6 = (const WCHAR *)UStrToPWChar(v44);
TApplication_MessageBox(*Application, v6, v18, (UINT)L"\r");
}
TControl_SetColor(*((_DWORD *)this + 0x10B), &byte_54B70C);
LOBYTE(v12) = 1;
(*(void (__fastcall **)(_DWORD, int))(**((_DWORD **)this + 0x10C) + 0x94))(*((_DWORD *)this + 0x10C), v12);
sub_67A55C(*Screen, 0, v13, v23, v22, L"\r", v21);
}
}
else
{
ischecker_created_over_00BACF6C = 1;
// call TThread.Create;TChecker.Create
v2 = TThread_Create(VMT_9A53C4_TChecker, 1);
// mov eax,dword ptr [ebx+3F8];TNagScreen.CheckBox1:TCheckBox
// …………
// call dword ptr [edx+130];TCheckBox.GetChecked
if ( (*(unsigned __int8 (__fastcall **)(_DWORD))(**((_DWORD **)this + 0xFE) + 0x130))(*((_DWORD *)this + 0xFE)) )
{
// 离线激活时
*(_BYTE *)(v2 + 0x31) = 1;
// active code
TControl_GetText(*((Controls::TControl **)this + 0x102), (int)&v50);
}
*(_BYTE *)(v2 + 0x31) = 0;
UStrClr(v2 + 0x34);
*(_BYTE *)(v2 + 0x30) = 1;
sub_48F8DC(v2, 1);
}
__writefsdword(0, v24[0]);
v24[2] = (unsigned int)&loc_9A4329;
UStrArrayClr(&v25, 0x19);
return UStrClr(&v50);
}
离线校验逻辑
TChecker 类
TChecker.Execute
_Unit180.TChecker.Execute
009A8BC4 mov byte ptr ds:[0BACF80],0;gvar_00BACF80
009A8BCB mov byte ptr ds:[0BACF81],0;gvar_00BACF81
009A8BD2 call 009A6AEC ;关键函数
009A8BD7 ret
check_9A6AEC
由于ida对Delphi 的异常处理未能正确分析,未能完整反编译(如mov fs:[eax], edx 设置SEH就给干傻了)
首先计算“VOVSOFT - Text Edit Plus” 的md5hex (C20297BE5DC4403AA4913F7587535516),作为注册表key
其相关配置将存到
\HKEY_CURRENT_USER\Software\Microsoft\VS\ServiceModules\C20297BE5DC4403AA4913F7587535516\Settings
009A6B5D | 33C0 | xor eax,eax |
009A6B5F | 55 | push ebp |
009A6B60 | 68 846B9A00 | push text.9A6B84 |
009A6B65 | 64:FF30 | push dword ptr fs:[eax] |
009A6B68 | 64:8920 | mov dword ptr fs:[eax],esp |
009A6B6B | 8D55 E0 | lea edx,dword ptr ss:[ebp-20] |
009A6B6E | A1 6C2ABB00 | mov eax,dword ptr ds:[BB2A6C] |
009A6B73 | 8B00 | mov eax,dword ptr ds:[eax] |
009A6B75 | E8 06EBFFFF | call <text.calc_md5hex> |
009A6B7A | 33C0 | xor eax,eax |
009A6B7C | 5A | pop edx |
009A6B7D | 59 | pop ecx |
009A6B7E | 59 | pop ecx |
009A6B7F | 64:8910 | mov dword ptr fs:[eax],edx |
009A6B82 | EB 1C | jmp text.9A6BA0 |
009A6B84 | E9 A349A6FF | jmp text.40B52C |
;SEH 异常处理
009A6B89 | 8D45 E0 | lea eax,dword ptr ss:[ebp-20] |
009A6B8C | E8 7357A6FF | call text.40C304 |
009A6B91 | B8 EC839A00 | mov eax,text.9A83EC | 9A83EC:L"Error: MD5 generate problem!"
009A6B96 | E8 25EAFFFF | call text.9A55C0 |
009A6B9B | E8 A84EA6FF | call text.40BA48 |
获取 MachineGuid
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
MachineGuid
009A6BA2 | 55 | push ebp |
009A6BA3 | 68 C06B9A00 | push text.9A6BC0 |
009A6BA8 | 64:FF30 | push dword ptr fs:[eax] |
009A6BAB | 64:8920 | mov dword ptr fs:[eax],esp |
009A6BAE | 8D45 E4 | lea eax,dword ptr ss:[ebp-1C] |
009A6BB1 | E8 FAFCFFFF | call <text.get__MachineGuid> |
009A6BB6 | 33C0 | xor eax,eax |
009A6BB8 | 5A | pop edx |
009A6BB9 | 59 | pop ecx |
009A6BBA | 59 | pop ecx |
009A6BBB | 64:8910 | mov dword ptr fs:[eax],edx |
009A6BBE | EB 1C | jmp text.9A6BDC |
009A6BC0 | E9 6749A6FF | jmp text.40B52C |
009A6BC5 | 8D45 E4 | lea eax,dword ptr ss:[ebp-1C] |
009A6BC8 | E8 3757A6FF | call text.40C304 |
009A6BCD | B8 34849A00 | mov eax,text.9A8434 | 9A8434:L"Error: GUID generate problem!"
009A6BD2 | E8 E9E9FFFF | call text.9A55C0 |
009A6BD7 | E8 6C4EA6FF | call text.40BA48 |
判断是否存在key.txt,存在时读取并保存到注册表\HKEY_CURRENT_USER\Software\Microsoft\VS\ServiceModules\C20297BE5DC4403AA4913F7587535516\Settings
LicenseKey
后面初始化某些配置
未联网、未激活时
联网校验过、未激活时有如下配置
该程序会进行网络校验,发送的相关字符:
网络请求失败时,校验Parity
009A80DE | 8B85 78FFFFFF | mov eax,dword ptr ss:[ebp-88] |
009A80E4 | 83E8 04 | sub eax,4 |
009A80E7 | 8B00 | mov eax,dword ptr ds:[eax] |
009A80E9 | 8985 78FFFFFF | mov dword ptr ss:[ebp-88],eax |
009A80EF | 8B85 78FFFFFF | mov eax,dword ptr ss:[ebp-88] |
009A80F5 | 85C0 | test eax,eax |
009A80F7 | 7E 16 | jle text.9A810F |
009A80F9 | BA 01000000 | mov edx,1 |
009A80FE | 8B0D A4CFBA00 | mov ecx,dword ptr ds:[<LicenseKey_BACFA4>] |
009A8104 | 0FB74C51 FE | movzx ecx,word ptr ds:[ecx+edx*2-2] |
009A8109 | 03D9 | add ebx,ecx |
009A810B | 42 | inc edx |
009A810C | 48 | dec eax |
009A810D | 75 EF | jne text.9A80FE |
009A810F | 33F6 | xor esi,esi |
009A8111 | 8B45 E4 | mov eax,dword ptr ss:[ebp-1C] |
009A8114 | 8985 74FFFFFF | mov dword ptr ss:[ebp-8C],eax |
009A811A | 83BD 74FFFFFF 00 | cmp dword ptr ss:[ebp-8C],0 |
009A8121 | 74 11 | je text.9A8134 |
009A8123 | 8B85 74FFFFFF | mov eax,dword ptr ss:[ebp-8C] |
009A8129 | 83E8 04 | sub eax,4 |
009A812C | 8B00 | mov eax,dword ptr ds:[eax] |
009A812E | 8985 74FFFFFF | mov dword ptr ss:[ebp-8C],eax |
009A8134 | 8B85 74FFFFFF | mov eax,dword ptr ss:[ebp-8C] |
009A813A | 85C0 | test eax,eax |
009A813C | 7E 13 | jle text.9A8151 |
009A813E | BA 01000000 | mov edx,1 | get key checksum
009A8143 | 8B4D E4 | mov ecx,dword ptr ss:[ebp-1C] |
009A8146 | 0FB74C51 FE | movzx ecx,word ptr ds:[ecx+edx*2-2] |
009A814B | 03F1 | add esi,ecx |
009A814D | 42 | inc edx |
009A814E | 48 | dec eax |
009A814F | 75 F2 | jne text.9A8143 |
009A8151 | 8B45 C4 | mov eax,dword ptr ss:[ebp-3C] | esi==> MachineGuid checksum
009A8154 | 83C0 34 | add eax,34 | eax+34h Activate code
009A8157 | B9 14000000 | mov ecx,14 |
009A815C | BA 01000000 | mov edx,1 |
009A8161 | E8 9255A6FF | call <text.@UStrDelete> | 删除长度14h
009A8166 | 8B45 C4 | mov eax,dword ptr ss:[ebp-3C] |
009A8169 | 8B40 34 | mov eax,dword ptr ds:[eax+34] |
009A816C | E8 3F5DA8FF | call <text.StrToInt> | 即激活码[20:] 为int_str
009A8171 | 2BF3 | sub esi,ebx |
009A8173 | 3BC6 | cmp eax,esi | int_str == MachineGuid_checksum - key_checksum
009A8175 | 0F85 CE000000 | jne text.9A8249 |
009A817B | 8B45 C4 | mov eax,dword ptr ss:[ebp-3C] | int_str 存储到 注册表Parity
009A817E | 8B40 34 | mov eax,dword ptr ds:[eax+34] |
009A8181 | 50 | push eax |
009A8182 | B9 CC869A00 | mov ecx,text.9A86CC | 9A86CC:L"Parity"
009A8187 | BA 5C859A00 | mov edx,text.9A855C | 9A855C:L"Settings"
009A818C | A1 20EBBC00 | mov eax,dword ptr ds:[BCEB20] |
009A8191 | E8 7AA5B9FF | call <text.reg_set_> |
009A8196 | B8 24EBBC00 | mov eax,<text.LicenseOwner> |
009A819B | BA B48B9A00 | mov edx,text.9A8BB4 | 9A8BB4:L"Offline"
009A81A0 | E8 3F45A6FF | call <text.@UStrAsg> |
009A81A5 | 8D85 5CFEFFFF | lea eax,dword ptr ss:[ebp-1A4] |
009A81AB | 8B15 24EBBC00 | mov edx,dword ptr ds:[<LicenseOwner>] |
009A81B1 | E8 CA51A6FF | call <text.@WStrFromUStr> |
009A81B6 | 8B85 5CFEFFFF | mov eax,dword ptr ss:[ebp-1A4] |
009A81BC | 8D8D 60FEFFFF | lea ecx,dword ptr ss:[ebp-1A0] |
009A81C2 | 66:BA BA00 | mov dx,BA |
009A81C6 | E8 45E4FFFF | call <text.xor_enc> |
009A81CB | 8B85 60FEFFFF | mov eax,dword ptr ss:[ebp-1A0] | 设置注册表LicenseOwner 值为Offline xor加密的hexstr
009A81D1 | 50 | push eax |
009A81D2 | B9 A4869A00 | mov ecx,text.9A86A4 | 9A86A4:L"LicenseOwner"
009A81D7 | BA 5C859A00 | mov edx,text.9A855C | 9A855C:L"Settings"
009A81DC | A1 20EBBC00 | mov eax,dword ptr ds:[BCEB20] |
009A81E1 | E8 2AA5B9FF | call <text.reg_set_> |
14.7 版本check函数的局部变量
## check函数的局部变量
[ebp-18h] string==> LastUpdateCheck
[ebp-4Ch] int==》 LastUpdateCheckCount
[ebp-0BCh] string==>InstalledVersion
[ebp-3ch] ==>obj
[+30h] 判断是否设置InstalledVersion
obj+34h==>Activate code
[ebp-0C0h] string==> CurrentVersion
[ebp-0C4h] string==>CurrentURL
BACF90:&L"http://vovsoft.com/software/text-edit-plus/"
BACF90:&L"6810A868ADD9651ABAB1AC6CD56621708492E4E0605911074FDF754F05F4B503A6DADFF038CCB31C72640C"
[ebp-0CCh] string ==>CurrentPrice
[ebp-0D4h] ==> license_key (原始)
[ebp-0D8h] string ==> LicenseKey (xor_enc_license_key)
[ebp-0DCh] ==》LicenseKey xor dec -->原始
[ebp-0E0h] string==> LicenseOwner
[ebp-8] string ==>Parity
[ebp-1Ch] machineGuid
other
某些配置项通过xor加密存储,如 CurrentURL、LicenseKey、LicenseOwner
xor_enc_9A6610
// bad sp value at call has been detected, the output may be wrong!
void __fastcall xor_enc_9A6610(int a1, __int16 a2, int a3)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v20 = 0;
v18 = 0;
v19 = a3;
v14 = &savedregs;
v13 = &loc_9A66D8;
ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)&ExceptionList);
UStrClr(a3);
UTF8Encode(a1, &v20, v5, v17, v16, v15, v14, v13, ExceptionList);
v6 = (int)v20;
if ( v20 )
v6 = *((_DWORD *)v20 + 0xFFFFFFFF);
if ( v6 - 1 >= 0 )
{
v7 = v6;
v8 = 0;
do
{
v20[v8] ^= HIBYTE(a2);
a2 = 0xD201 * ((unsigned __int8)v20[v8++] + a2) + 0x7F6A;
--v7;
}
while ( v7 );
}
v9 = (int)v20;
if ( v20 )
v9 = *((_DWORD *)v20 + 0xFFFFFFFF);
if ( v9 - 1 >= 0 )
{
v10 = v9;
v11 = 0;
do
{
IntToHex((unsigned __int8)v20[v11], 2, &v18);
UStrCat(v19, v18);
++v11;
--v10;
}
while ( v10 );
}
__writefsdword(0, v19);
savedregs = &dword_9A66DF;
UStrClr(&v18);
((void (__fastcall *)(char **))LStrClr)(&v20);
JUMPOUT(0x9A66DF);
}
xor_dec sub_9A66E8
// bad sp value at call has been detected, the output may be wrong!
int __usercall sub_9A66E8@<eax>(
int a1@<eax>,
__int16 value@<dx>,
int a3@<ecx>,
int a4@<ebx>,
int a5@<edi>,
int a6@<esi>)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
cchWideChar = 0;
v26 = 0;
v25 = 0;
temp = 0;
v22[1] = 0;
v22[0] = 0;
v21 = 0;
v20[5] = a4;
v20[4] = a6;
v20[3] = a5;
v24 = a3;
v20[2] = &savedregs;
v20[1] = System::__linkproc__ HandleFinally;
v20[0] = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)v20);
UpperCase(a1, &v26);
v7 = (int)v26;
if ( v26 )
v7 = *((_DWORD *)v26 + 0xFFFFFFFF);
LStrSetLength((int)&cchWideChar, v7 / 2);
v19 = &savedregs;
v18 = (int (__cdecl *)(int, int))&loc_9A67BC;
ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)&ExceptionList);
v9 = (int)v26;
if ( v26 )
v9 = *((_DWORD *)v26 + 0xFFFFFFFF);
if ( v9 > 1 )
UStrFromPWCharLen_3512(v22, *v26, v8, ExceptionList, &byte_9A68AC);
__writefsdword(0, (unsigned int)ExceptionList);
v10 = cchWideChar;
if ( cchWideChar )
v10 = (char *)*((_DWORD *)cchWideChar + 0xFFFFFFFF);
v11 = (int)(v10 + 0xFFFFFFFF);
if ( v11 >= 0 )
{
size = v11 + 1;
index = 0;
do
{
temp = (unsigned __int8)cchWideChar[index];
cchWideChar[index] ^= HIBYTE(value);
value = 0xD201 * (temp + value) + 0x7F6A;
++index;
--size;
}
while ( size );
}
v19 = &savedregs;
v18 = System::__linkproc__ HandleFinally;
ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)&ExceptionList);
UStrClr(&v25);
UTF8ToUnicodeString((int)cchWideChar);
UStrAsg(v24, v25, v14);
__writefsdword(0, (unsigned int)ExceptionList);
v19 = (int (__fastcall **)(_DWORD))&loc_9A685F;
UStrClr(&v25);
__writefsdword(0, (unsigned int)v26);
savedregs = sub_9A6896;
UStrArrayClr(&v21, 3);
UStrArrayClr(&v25, 2);
v15 = ((int (__fastcall *)(char **))LStrClr)(&cchWideChar);
return sub_9A6896(v15);
}
py
import random
import string
# xor_dec
def xor_dec_9A66E8(data:bytes,value:int=0xba):
out=bytearray(data)
for i in range(len(data)):
temp = data[i]
out[i] ^= (value >> 8) & 0xFF
value =0xD201 * (temp + value) + 0x7F6A
return out
# xor_enc
def xor_enc_9A6610(data:bytes,value:int=0xba):
out=bytearray(data)
for i in range(len(data)):
out[i] ^= (value >> 8) & 0xFF
value =0xD201 * (out[i] + value) + 0x7F6A
return out
def checksum32(data:bytes):
n=0
for x in data:
n+=x
return n&0xffffffff
def gen(machineGuid:bytes,key:bytes=b'AAAAA-AAAAA-AAAAA'):
if isinstance(machineGuid,str):
machineGuid=machineGuid.encode()
if isinstance(key,str):
key=key.encode()
machineGuid=machineGuid.lower()
key=key.upper()
licensekey_checksum=checksum32(key)
# print('licensekey_checksum:%08x'%licensekey_checksum)
mid_checksum=checksum32(machineGuid)
# print('mid_checksum:%08x'%mid_checksum)
Parity=mid_checksum-licensekey_checksum
print('Parity:',Parity)
stub=''.join(random.choices(string.ascii_uppercase,k=20))
code=stub+str(Parity)
print(f'Activate code:\n{code}')
return code
14.7、14.8 离线测试可用,程序联网便会进行网络校验,联网一定不通过!
如果想修改名字可手动修改注册表项:
如ikun 经过xor_enc_9A6610 加密后hexstr为 695DDF6E