anytxt searcher 1.3.2998 记录
anytxt searcher 1.3.2998 记录
文件信息
版本 1.3.2998
PE64
操作系统: Windows(Vista)[AMD64, 64 位, GUI]
链接程序: Microsoft Linker(14.16.27049)
编译器: Microsoft Visual C/C++(19.16.27049)[LTCG/C++]
语言: C++
库: Microsoft C/C++ Runtime[dynamic]
库: Qt(5.14.2.0)
工具: Visual Studio(2017, v15.9)
签名工具: Windows Authenticode(2.0)[PKCS #7]
附加: Binary[偏移=0x00f2a000,大小=0x59c8]
证书: WinAuth(2.0)[PKCS #7]
-
qt5 动态链接,
-
ollvm混淆
-
可通过zh_CHS.ini 文件中字符串id进行关键函数定位
-
日志文件目录C:\ProgramData\Anytxt\log
-
AI赋能,大部分工作由AI完成。
这里只记录许可解析流程,没有进行按钮事件分析,而是直接定位CLicence类,分析许可解析加载的过程。
扫码登陆应该是Protobuf gRPC
可用工具还原.proto marin-m/pbtk: A toolset for reverse engineering and fuzzing Protobuf-based apps
User.proto
感觉大有可为,嘿嘿,略;
syntax = "proto3";
package User;
service UserGreeter {
rpc LoginByWechat(WechatTokenRequest) returns (TokenResponse);
rpc LoginByGoogle(GoogleTokenRequest) returns (TokenResponse);
rpc LoginByMicrosoft(MicrosoftTokenRequest) returns (TokenResponse);
rpc LoginByPasswd(AccountTokenRequest) returns (TokenResponse);
rpc Logout(LogoutRequest) returns (BoolResponse);
rpc GetUserInfo(GetUserInfoRequest) returns (ValueResponse);
rpc CheckUserDevice(CheckUserDeviceRequest) returns (BoolResponse);
rpc SetUserInfo(SetUserInfoRequest) returns (BoolResponse);
rpc UserGetVipReward(GetVipRewardRequest) returns (BoolResponse);
rpc DeviceOnline(DeviceOnlineRequest) returns (BoolResponse);
rpc GetUtcTime(Empty) returns (UtcTimeResponse);
rpc GetRunTimes(GetRunTimesRequest) returns (RunTimesResponse);
rpc IsServerOK(IsServerOKRequest) returns (BoolResponse);
rpc GetOption(GetOptionRequest) returns (ValueResponse);
rpc OrderCreate(OrderCreateRequest) returns (OrderResponse);
rpc OrderCheck(OrderCheckRequest) returns (BoolResponse);
rpc OrderCancel(OrderCancelRequest) returns (BoolResponse);
rpc GetPlans(GetPlansRequest) returns (GetPlansResponse);
rpc GetBonusStatistics(GetBonusStatisticsRequest) returns (ValueResponse);
rpc ApplyForBonusExchange(ApplyForBonusExchangeRequest) returns (BoolResponse);
rpc GetApplicationInfo(GetApplicationInfoRequest) returns (ValueResponse);
rpc GetWechatQRcode(Empty) returns (GetWechatQRcodeResponse);
rpc CheckWechatQRcode(CheckWechatQRcodeRequest) returns (CheckWechatQRcodeResponse);
}
message WechatTokenRequest {
string wechat_id = 1;
int64 device_serial_number = 2;
}
message GoogleTokenRequest {
string google_id = 1;
int64 device_serial_number = 2;
}
message MicrosoftTokenRequest {
string microsoft_id = 1;
int64 device_serial_number = 2;
}
message AccountTokenRequest {
string username = 1;
string password = 2;
int64 device_serial_number = 3;
}
message LogoutRequest {
string user_token = 1;
int64 device_serial_number = 2;
}
message GetUserInfoRequest {
string user_token = 1;
int64 value_key = 2;
}
message SetUserInfoRequest {
string user_token = 1;
int64 value_key = 2;
string value_content = 3;
}
message CheckUserDeviceRequest {
string user_token = 1;
int64 device_serial_number = 2;
}
message GetOptionRequest {
string key = 1;
bool success = 2;
}
message TokenResponse {
string content = 1;
bool success = 2;
}
message ValueResponse {
string content = 1;
bool success = 2;
}
message BoolResponse {
bool success = 1;
}
message UtcTimeResponse {
int64 utc_time = 1;
}
message RunTimesResponse {
int64 run_times = 1;
}
message Empty {
}
message GetVipRewardRequest {
string user_token = 1;
}
message DeviceOnlineRequest {
int64 device_serial_number = 1;
int64 recommender_id = 2;
string location = 3;
string os_arch = 4;
string os_name = 5;
string os_version = 6;
int64 anytxt_version = 7;
}
message GetRunTimesRequest {
int64 device_serial_number = 1;
}
message IsServerOKRequest {
string version = 1;
}
message OrderCreateRequest {
string user_token = 1;
int64 plan_id = 2;
int64 volumes = 3;
int64 pay_way = 4;
double price = 5;
int32 plan_language = 6;
}
message OrderCheckRequest {
int64 order_id = 1;
string user_token = 2;
}
message OrderCancelRequest {
int64 order_id = 1;
string user_token = 2;
}
message OrderResponse {
int64 order_id = 1;
string pay_url = 2;
bool success = 3;
}
message GetPlansRequest {
int32 language = 1;
}
message GetPlansResponse {
bool success = 1;
string plans_json = 2;
}
message GetBonusStatisticsRequest {
string user_token = 1;
}
message ApplyForBonusExchangeRequest {
string user_token = 1;
}
message GetApplicationInfoRequest {
string user_token = 1;
int64 value_key = 2;
}
message GetWechatQRcodeResponse {
bool success = 1;
string json_value = 2;
}
message CheckWechatQRcodeRequest {
string ticket = 1;
}
message CheckWechatQRcodeResponse {
bool success = 1;
string json_value = 2;
}
CLicence
QSettings 存储许可信息
对应注册表:
HKEY_CURRENT_USER\Software\CBEWIN\Anytxt 字符串值License
HKEY_LOCAL_MACHINE
__int64 __fastcall CLicence_14026AA00(CLicence *CLicence)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v49 = 0xFFFFFFFFFFFFFFFEui64;
v50 = CLicence;
LOBYTE(CLicence->Offline_status_0) = 1;
QDate::QDate(&CLicence->QDate_startDate_18);
QDate::QDate(&CLicence->QDate_Expireddate_20);
QString::QString(&CLicence->qstr_licinfo_28);
CLicence->field_30 = 0;
QString::QString(&CLicence->qstr__lic_mem_anytxt_38);
QString::QString(&CLicence->qstr_lic_40);
QReadWriteLock::QReadWriteLock(&CLicence->qreadwritelock48, 0i64);
QString::QString(&CLicence->qstr_reg_CBEWIN_50);
QString::QString(&CLicence->qstr_reg_crent_user_CBEWIN_58);
QString::QString(&CLicence->qstr_reg_user_CBEWIN_60);
// __int64 __fastcall sub_14026B210(__int64 a1, __int64 a2)
// {
// __int64 result; // rax
// __int64 v3; // [rsp+0h] [rbp-48h] BYREF
// double v4; // [rsp+20h] [rbp-28h]
// __m128i si128; // [rsp+28h] [rbp-20h]
// unsigned __int64 v6; // [rsp+38h] [rbp-10h]
// v6 = &v3 ^ qword_140E70770;
// si128 = _mm_load_si128(&n_183_140CE5970);
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// *(a2 + 0xF) = 0x1FF;
// result = a2;
// *a2 = 0xAAE63FB7;
// *(a2 + 4) = 0x92A6FAA5;
// *(a2 + 8) = 0xB0E132B7;
// *(a2 + 0xC) = 0xEFFF;
// *(a2 + 0xE) = 0xB7;
// return result;
// }
v3 = sub_14026B210(v2, v52);
v4 = v3;
if ( v3[0x10] )
{
// .lic.mem.anytxt
*v3 ^= 0x99u;
*(v3 + 1) ^= 0x53u;
*(v3 + 2) ^= 0x8Fu;
*(v3 + 3) ^= 0xC9u;
*(v3 + 4) ^= 0x8Bu;
*(v3 + 5) ^= 0x97u;
*(v3 + 6) ^= 0xC3u;
*(v3 + 7) = ~v3[7];
*(v3 + 8) ^= 0x99u;
*(v3 + 9) ^= 0x53u;
*(v3 + 0xA) ^= 0x8Fu;
*(v3 + 0xB) ^= 0xC9u;
*(v3 + 0xC) ^= 0x8Bu;
*(v3 + 0xD) ^= 0x97u;
*(v3 + 0xE) ^= 0xC3u;
*(v3 + 0xF) = ~v3[0xF];
*(v3 + 0x10) = 0;
}
QString::QString(v39);
v5 = QString::QString(v44, v4);
QString::operator=(v39, v5);
QString::~QString(v44);
QString::operator=(&CLicence->qstr__lic_mem_anytxt_38, v39);
v6 = QString::begin(v39);
v7 = QString::end(v39);
v8 = 0i64;
v9 = (v7 - v6 + 1) >> 1;
if ( v6 > v7 )
v9 = 0i64;
if ( v9 )
{
while ( v9 )
{
*v6 = 0;
v6 = (v6 + 2);
--v9;
}
}
QString::~QString(v39);
for ( i = 0i64; i < 0x10; ++i )
v52[i] |= 0x91 - i;
// __int64 __fastcall sub_14026B3A0(__int64 a1, __int64 a2)
// {
// __int64 result; // rax
// *(a2 + 2) = 0x1AFE674;
// result = a2;
// *a2 = 0xE7C9;
// return result;
// }
v11 = sub_14026B3A0(i, v51);
v12 = v11;
if ( v11[5] )
{
// .lic
*v11 ^= 0xE7u;
*(v11 + 1) ^= 0x8Bu;
*(v11 + 2) ^= 0x1Du;
*(v11 + 3) ^= 0x85u;
*(v11 + 4) ^= 0xAFu;
*(v11 + 5) = 0;
}
QString::QString(v40);
v13 = QString::QString(v45, v12);
QString::operator=(v40, v13);
QString::~QString(v45);
QString::operator=(&CLicence->qstr_lic_40, v40);
v14 = QString::begin(v40);
v15 = QString::end(v40);
v16 = (v15 - v14 + 1) >> 1;
if ( v14 > v15 )
v16 = 0i64;
if ( v16 )
{
while ( v16 )
{
*v14 = 0;
v14 = (v14 + 2);
--v16;
}
}
QString::~QString(v40);
for ( j = 0i64; j < 5; ++j )
v51[j] |= 0x91 - j;
// unsigned __int64 __fastcall sub_14026B520(__int64 a1, _DWORD *a2)
// {
// // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
// v9 = &v3 ^ qword_140E70770;
// si128 = _mm_load_si128(&n_127_140CE5640);
// v7 = 0xA97E;
// v6 = _mm_load_si128(&n_121_140CE5290);
// v8 = 0x7F;
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// a2[8] = 0x17FA97E;
// result = a2;
// *a2 = 0x543AAC7F;
// a2[1] = 0xD4560D86;
// a2[2] = 0x4020AB76;
// a2[3] = 0xDE510298;
// a2[4] = 0x5E23A279;
// a2[5] = 0xC04D0796;
// a2[6] = 0x513AB576;
// a2[7] = 0xC05C039A;
// return result;
// }
v18 = sub_14026B520(j, &v54);
v19 = v18;
if ( v18[0x23] )
{
// HKEY_LOCAL_MACHINE\SOFTWARE\CBEWIN
*v18 ^= 0x37u;
*(v18 + 1) ^= 0xE7u;
*(v18 + 2) ^= 0x7Fu;
*(v18 + 3) ^= 0xDu;
*(v18 + 4) ^= 0xD9u;
*(v18 + 5) ^= 0x41u;
*(v18 + 6) ^= 0x19u;
*(v18 + 7) ^= 0x97u;
*(v18 + 8) ^= 0x37u;
*(v18 + 9) ^= 0xE7u;
*(v18 + 0xA) ^= 0x7Fu;
*(v18 + 0xB) ^= 0xDu;
*(v18 + 0xC) ^= 0xD9u;
*(v18 + 0xD) ^= 0x41u;
*(v18 + 0xE) ^= 0x19u;
*(v18 + 0xF) ^= 0x97u;
*(v18 + 0x10) ^= 0x37u;
*(v18 + 0x11) ^= 0xE7u;
*(v18 + 0x12) ^= 0x7Fu;
*(v18 + 0x13) ^= 0xDu;
*(v18 + 0x14) ^= 0xD9u;
*(v18 + 0x15) ^= 0x41u;
*(v18 + 0x16) ^= 0x19u;
*(v18 + 0x17) ^= 0x97u;
*(v18 + 0x18) ^= 0x37u;
*(v18 + 0x19) ^= 0xE7u;
*(v18 + 0x1A) ^= 0x7Fu;
*(v18 + 0x1B) ^= 0xDu;
*(v18 + 0x1C) ^= 0xD9u;
*(v18 + 0x1D) ^= 0x41u;
*(v18 + 0x1E) ^= 0x19u;
*(v18 + 0x1F) ^= 0x97u;
*(v18 + 0x20) ^= 0x37u;
*(v18 + 0x21) ^= 0xE7u;
*(v18 + 0x22) ^= 0x7Fu;
*(v18 + 0x23) = 0;
}
QString::QString(v41);
v20 = QString::QString(v46, v19);
QString::operator=(v41, v20);
QString::~QString(v46);
QString::operator=(&CLicence->qstr_reg_CBEWIN_50, v41);
v21 = QString::begin(v41);
v22 = QString::end(v41);
v23 = (v22 - v21 + 1) >> 1;
if ( v21 > v22 )
v23 = 0i64;
if ( v23 )
{
while ( v23 )
{
*v21 = 0;
v21 = (v21 + 2);
--v23;
}
}
QString::~QString(v41);
for ( k = 0i64; k < 0x23; ++k )
*(v55 + k + 0x18) |= 0x91 - k;
// __int64 __fastcall sub_14026B6F0(__int64 a1, __int64 a2)
// {
// // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
// v8 = &v3 ^ qword_140E70770;
// si128 = _mm_load_si128(&n_209_140CE4B00);
// v7 = 0x47D7;
// v6 = _mm_load_si128(&n_203_140CE4C50);
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// *(a2 + 0x21) = 0x147;
// result = a2;
// *a2 = 0x32E80CD1;
// *(a2 + 4) = 0x952A347C;
// *(a2 + 8) = 0x3FE302CB;
// *(a2 + 0xC) = 0x822C227C;
// *(a2 + 0x10) = 0x24FE1BCB;
// *(a2 + 0x14) = 0x86282365;
// *(a2 + 0x18) = 0x28F102CB;
// *(a2 + 0x1C) = 0x8E283261;
// *(a2 + 0x20) = 0xD7;
// return result;
// }
v25 = sub_14026B6F0(k, v53);
v26 = v25;
if ( v25[0x22] )
{
// HKEY_CURRENT_USER\SOFTWARE\CBEWIN
*v25 ^= 0x99u;
*(v25 + 1) ^= 0x47u;
*(v25 + 2) ^= 0xADu;
*(v25 + 3) ^= 0x6Bu;
*(v25 + 4) ^= 0x23u;
*(v25 + 5) ^= 0x77u;
*(v25 + 6) ^= 0x7Fu;
*(v25 + 7) ^= 0xC7u;
*(v25 + 8) ^= 0x99u;
*(v25 + 9) ^= 0x47u;
*(v25 + 0xA) ^= 0xADu;
*(v25 + 0xB) ^= 0x6Bu;
*(v25 + 0xC) ^= 0x23u;
*(v25 + 0xD) ^= 0x77u;
*(v25 + 0xE) ^= 0x7Fu;
*(v25 + 0xF) ^= 0xC7u;
*(v25 + 0x10) ^= 0x99u;
*(v25 + 0x11) ^= 0x47u;
*(v25 + 0x12) ^= 0xADu;
*(v25 + 0x13) ^= 0x6Bu;
*(v25 + 0x14) ^= 0x23u;
*(v25 + 0x15) ^= 0x77u;
*(v25 + 0x16) ^= 0x7Fu;
*(v25 + 0x17) ^= 0xC7u;
*(v25 + 0x18) ^= 0x99u;
*(v25 + 0x19) ^= 0x47u;
*(v25 + 0x1A) ^= 0xADu;
*(v25 + 0x1B) ^= 0x6Bu;
*(v25 + 0x1C) ^= 0x23u;
*(v25 + 0x1D) ^= 0x77u;
*(v25 + 0x1E) ^= 0x7Fu;
*(v25 + 0x1F) ^= 0xC7u;
*(v25 + 0x20) ^= 0x99u;
*(v25 + 0x21) ^= 0x47u;
*(v25 + 0x22) = 0;
}
QString::QString(v42);
v27 = QString::QString(v47, v26);
QString::operator=(v42, v27);
QString::~QString(v47);
QString::operator=(&CLicence->qstr_reg_crent_user_CBEWIN_58, v42);
v28 = QString::begin(v42);
v29 = QString::end(v42);
v30 = (v29 - v28 + 1) >> 1;
if ( v28 > v29 )
v30 = 0i64;
if ( v30 )
{
while ( v30 )
{
*v28 = 0;
v28 = (v28 + 2);
--v30;
}
}
QString::~QString(v42);
for ( m = 0i64; m < 0x22; ++m )
v53[m] |= 0x91 - m;
// __int64 __fastcall sub_14026B8C0(__int64 a1, __int64 a2)
// {
// // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
// v8 = &v3 ^ qword_140E70770;
// si128 = _mm_load_si128(&n_207_140CE4B60);
// v7 = 0xF9DF72D0;
// v6 = _mm_load_si128(&n_210_140CE4C10);
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// *(a2 + 0x23) = 0x1F9;
// result = a2;
// *a2 = 0xA0D470CF;
// *(a2 + 4) = 0x8C244E1A;
// *(a2 + 8) = 0xD7CD68D5;
// *(a2 + 0xC) = 0x88315E01;
// *(a2 + 0x10) = 0xA5C577D2;
// *(a2 + 0x14) = 0xBD117416;
// *(a2 + 0x18) = 0x9CE35AF0;
// *(a2 + 0x1C) = 0x8C355819;
// *(a2 + 0x20) = 0x72D0;
// *(a2 + 0x22) = 0xDF;
// return result;
// }
v32 = sub_14026B8C0(m, v55);
v33 = v32;
if ( v32[0x24] )
{
// HKEY_USERS\.DEFAULT\Software\CBEWIN
*v32 ^= 0x87u;
*(v32 + 1) ^= 0x3Bu;
*(v32 + 2) ^= 0x91u;
*(v32 + 3) ^= 0xF9u;
*(v32 + 4) ^= 0x45u;
*(v32 + 5) ^= 0x1Bu;
*(v32 + 6) ^= 0x77u;
*(v32 + 7) ^= 0xC9u;
*(v32 + 8) ^= 0x87u;
*(v32 + 9) ^= 0x3Bu;
*(v32 + 0xA) ^= 0x91u;
*(v32 + 0xB) ^= 0xF9u;
*(v32 + 0xC) ^= 0x45u;
*(v32 + 0xD) ^= 0x1Bu;
*(v32 + 0xE) ^= 0x77u;
*(v32 + 0xF) ^= 0xC9u;
*(v32 + 0x10) ^= 0x87u;
*(v32 + 0x11) ^= 0x3Bu;
*(v32 + 0x12) ^= 0x91u;
*(v32 + 0x13) ^= 0xF9u;
*(v32 + 0x14) ^= 0x45u;
*(v32 + 0x15) ^= 0x1Bu;
*(v32 + 0x16) ^= 0x77u;
*(v32 + 0x17) ^= 0xC9u;
*(v32 + 0x18) ^= 0x87u;
*(v32 + 0x19) ^= 0x3Bu;
*(v32 + 0x1A) ^= 0x91u;
*(v32 + 0x1B) ^= 0xF9u;
*(v32 + 0x1C) ^= 0x45u;
*(v32 + 0x1D) ^= 0x1Bu;
*(v32 + 0x1E) ^= 0x77u;
*(v32 + 0x1F) ^= 0xC9u;
*(v32 + 0x20) ^= 0x87u;
*(v32 + 0x21) ^= 0x3Bu;
*(v32 + 0x22) ^= 0x91u;
*(v32 + 0x23) ^= 0xF9u;
*(v32 + 0x24) = 0;
}
QString::QString(v43);
v34 = QString::QString(v48, v33);
QString::operator=(v43, v34);
QString::~QString(v48);
QString::operator=(&CLicence->qstr_reg_user_CBEWIN_60, v43);
v35 = QString::begin(v43);
v36 = QString::end(v43);
v37 = (v36 - v35 + 1) >> 1;
if ( v35 > v36 )
v37 = 0i64;
if ( v37 )
{
while ( v37 )
{
*v35 = 0;
v35 = (v35 + 2);
--v37;
}
}
QString::~QString(v43);
do
{
v55[v8] |= 0x91 - v8;
++v8;
}
while ( v8 < 0x24 );
GetHardwareID_14026C5D0(CLicence);
x_lic_1402745C0(CLicence);
return CLicence;
}
x_lic_1402745C0
__int64 __fastcall x_lic_1402745C0(CLicence *CLicence)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v8 = 0xFFFFFFFFFFFFFFFEui64;
ClearLicence_mem_temp_1402742B0((__int64)CLicence);
v2 = QString::QString((QString *)v6);
v10 = LoadAndUpdateLicence_140275EB0((__int64)CLicence, (__int64)v2) && LOBYTE(CLicence->Offline_status_0);
QString::~QString(v6);
if ( (int)((double)1 * (((double)7 - ((double)3 + (double)3)) * (double)(LOBYTE(CLicence->Offline_status_0) == 0))) )
{
ClearLicence_mem_temp_1402742B0((__int64)CLicence);
v3 = 0;
goto LABEL_18;
}
v7 = ((double)7 - ((double)3 + (double)3)) * (double)0;
if ( (int)((double)1 * v7) )
{
if ( (int)((double)1 * (((double)7 - ((double)3 + (double)3)) * (double)1)) )
{
v3 = v10;
goto LABEL_18;
}
}
else
{
CLicence_14026AA00(&CLicencea);
v4 = (unsigned __int8)sub_140275640(&CLicencea, 0i64) && (unsigned __int8)sub_14026CC00((__int64)&CLicencea);
if ( (int)((double)1 * (((double)7 - ((double)3 + (double)3)) * (double)v4)) )
sub_140275640(CLicence, 0i64);
QString::~QString(&CLicencea.qstr_reg_user_CBEWIN_60);
QString::~QString(&CLicencea.qstr_reg_crent_user_CBEWIN_58);
QString::~QString(&CLicencea.qstr_reg_CBEWIN_50);
QReadWriteLock::~QReadWriteLock((QReadWriteLock *)&CLicencea.qreadwritelock48);
QString::~QString(&CLicencea.qstr_lic_40);
QString::~QString(&CLicencea.qstr__lic_mem_anytxt_38);
QString::~QString(&CLicencea.qstr_licinfo_28);
}
v3 = v10;
LABEL_18:
result = 1i64;
if ( (int)((double)1 * (((double)7 - ((double)3 + (double)3)) * (double)1)) > 0 )
return v3;
return result;
}
许可加载解析流程
LoadAndUpdateLicence_140275EB0
// __int64 LoadAndUpdateLicence(CLicence *lic, const QString *defaultLic)
__int64 __fastcall LoadAndUpdateLicence_140275EB0(CLicence *CLicence, void *a2)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v77 = 0xFFFFFFFFFFFFFFFEui64;
STACK[0x598] = &v50 ^ qword_140E70770;
v4 = 0;
v59 = 0;
QString::QString(&hexInput);
v51 = (7 - (3 + 3)) * *(*a2 + 4i64);
if ( (1 * v51) )
{
QString::operator=(&hexInput, a2);
goto LABEL_52;
}
v51 = (7 - (3 + 3)) * 0;
if ( (1 * v51) )
{
v51 = (7 - (3 + 3)) * 1;
if ( !(1 * v51) )
goto LABEL_52;
v5 = (7 - (3 + 3)) * 5.0;
LABEL_14:
v51 = v5;
goto LABEL_52;
}
if ( !CLicence->field_30 || (v6 = 1, !*(CLicence->qstr_licinfo_28 + 4)) )
v6 = 0;
v51 = (7 - (3 + 3)) * v6;
if ( (1 * v51) )
{
QString::operator=(&hexInput, &CLicence->qstr_licinfo_28);
goto LABEL_52;
}
v51 = (7 - (3 + 3)) * 0;
if ( (1 * v51) )
{
v51 = (7 - (3 + 3)) * 1;
if ( !(1 * v51) )
goto LABEL_52;
v5 = (7 - (3 + 3)) * 10.0;
goto LABEL_14;
}
QReadLocker::QReadLocker(v68, &CLicence->qreadwritelock48);
sub_1402106A0(&v96);
v7 = QString::toStdString(&CLicence->qstr__lic_mem_anytxt_38, v98);
v59 = 1;
if ( *(v7 + 0x18) >= 0x10ui64 )
v7 = *v7;
if ( !getfilesize_14026A7D0(&v96, v7) || !v96 || !v97 || (v8 = 1, *(v97 + 8) <= 0) )
v8 = 0;
v51 = (7 - (3 + 3)) * v8;
v9 = (1 * v51);
v59 = 0;
std::string::~string(v98);
if ( v9 )
{
if ( v96 && v97 )
v10 = *v97;
else
v10 = 0i64;
v11 = QString::QString(v67, v10);
QString::operator=(&hexInput, v11);
QString::~QString(v67);
}
sub_140210A80(&v96);
QReadLocker::~QReadLocker(v68);
GetConfigFilePath_140049360(&lic_type[1], &CLicence->qstr_lic_40);
if ( *(hexInput + 4) || (v12 = QFileInfo::exists(&lic_type[1]), v13 = 1, !v12) )
v13 = 0;
v51 = (7 - (3 + 3)) * v13;
if ( (1 * v51) )
{
v54 = 0;
v14 = sub_1402793C0(&v54, v92);
sub_14027DE90(v14);
v15 = stdstring_140017B00(v99, v14);
if ( *(v15 + 0x18) >= 0x10ui64 )
v15 = *v15;
QString::QString(v61, v15);
v16 = QSettings::QSettings(&v80, &lic_type[1], 1i64);
v17 = QVariant::QVariant(&vars0);
v18 = QSettings::value(v16, v78, v61, v17);
v19 = QVariant::toString(v18, v69);
QString::operator=(&hexInput, v19);
QString::~QString(v69);
QVariant::~QVariant(v78);
QVariant::~QVariant(&vars0);
QSettings::~QSettings(&v80);
QString::~QString(v61);
free_stdstr_140017BF0(v99);
for ( i = 0i64; i < 0xF; ++i )
v92[i] |= 0x91 - i;
}
v51 = (7 - (3 + 3)) * (*(hexInput + 4) == 0);
if ( (1 * v51) )
{
v55 = 0;
v21 = sub_140279560(&v55, v93);
// Anytxt/License
sub_14027DE40(v21);
v22 = stdstring_140017B00(v100, v21);
if ( *(v22 + 0x18) >= 0x10ui64 )
v22 = *v22;
QString::QString(v62, v22);
v23 = QSettings::QSettings(v83, &CLicence->qstr_reg_CBEWIN_50, 0i64);
v24 = QVariant::QVariant(v82);
v25 = QSettings::value(v23, &v81, v62, v24);
v26 = QVariant::toString(v25, v70);
QString::operator=(&hexInput, v26);
QString::~QString(v70);
QVariant::~QVariant(&v81);
QVariant::~QVariant(v82);
QSettings::~QSettings(v83);
QString::~QString(v62);
free_stdstr_140017BF0(v100);
for ( j = 0i64; j < 0xF; ++j )
v93[j] |= 0x91 - j;
}
v51 = (7 - (3 + 3)) * (*(hexInput + 4) == 0);
if ( (1 * v51) )
{
v56 = 0;
// unsigned __int64 __fastcall sub_140279700(__int64 a1, _DWORD *a2)
// {
// unsigned __int64 result; // rax
// __int64 v3; // [rsp+0h] [rbp-48h] BYREF
// double v4; // [rsp+20h] [rbp-28h]
// int v5; // [rsp+28h] [rbp-20h]
// int v6; // [rsp+2Ch] [rbp-1Ch]
// int v7; // [rsp+30h] [rbp-18h]
// __int16 v8; // [rsp+34h] [rbp-14h]
// char v9; // [rsp+36h] [rbp-12h]
// unsigned __int64 v10; // [rsp+38h] [rbp-10h]
// v10 = &v3 ^ qword_140E70770;
// v5 = 0xCFAED364;
// v6 = 0xB760379D;
// v7 = 0xD5B2DE4C;
// v8 = 0x2696;
// v9 = 0x4F;
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// a2[3] = 0x14F2696;
// result = a2;
// *a2 = 0xCFAED364;
// a2[1] = 0xB760379D;
// a2[2] = 0xD5B2DE4C;
// return result;
// }
v28 = sub_140279700(&v56, v94);
// void __fastcall sub_14027DDF0(_BYTE *a1)
// {
// if ( a1[0xF] )
// {
// *a1 ^= 0x25u;
// a1[1] ^= 0xBDu;
// a1[2] ^= 0xD7u;
// a1[3] ^= 0xBBu;
// a1[4] ^= 0xE5u;
// a1[5] ^= 0x43u;
// a1[6] ^= 0x4Fu;
// a1[7] ^= 0xFBu;
// a1[8] ^= 0x25u;
// a1[9] ^= 0xBDu;
// a1[0xA] ^= 0xD7u;
// a1[0xB] ^= 0xBBu;
// a1[0xC] ^= 0xE5u;
// a1[0xD] ^= 0x43u;
// a1[0xE] ^= 0x4Fu;
// a1[0xF] = 0;
// }
// }
sub_14027DDF0(v28);
// Anytxt/License
v29 = stdstring_140017B00(v101, v28);
if ( *(v29 + 0x18) >= 0x10ui64 )
v29 = *v29;
QString::QString(v63, v29);
v30 = QSettings::QSettings(v86, &CLicence->qstr_reg_crent_user_CBEWIN_58, 0i64);
v31 = QVariant::QVariant(v85);
v32 = QSettings::value(v30, v84, v63, v31);
v33 = QVariant::toString(v32, v71);
QString::operator=(&hexInput, v33);
QString::~QString(v71);
QVariant::~QVariant(v84);
QVariant::~QVariant(v85);
QSettings::~QSettings(v86);
QString::~QString(v63);
free_stdstr_140017BF0(v101);
for ( k = 0i64; k < 0xF; ++k )
v94[k] |= 0x91 - k;
}
v51 = (7 - (3 + 3)) * (*(hexInput + 4) == 0);
if ( (1 * v51) )
{
v57[0] = 0;
// unsigned __int64 __fastcall sub_1402798A0(__int64 a1, _DWORD *a2)
// {
// unsigned __int64 result; // rax
// __int64 v3; // [rsp+0h] [rbp-48h] BYREF
// double v4; // [rsp+20h] [rbp-28h]
// int v5; // [rsp+28h] [rbp-20h]
// int v6; // [rsp+2Ch] [rbp-1Ch]
// int v7; // [rsp+30h] [rbp-18h]
// __int16 v8; // [rsp+34h] [rbp-14h]
// char v9; // [rsp+36h] [rbp-12h]
// unsigned __int64 v10; // [rsp+38h] [rbp-10h]
// v10 = &v3 ^ qword_140E70770;
// v5 = 0x8D8A61B8;
// v6 = 0x55425F9D;
// v7 = 0x97966C90;
// v8 = 0x4E96;
// v9 = 0x6D;
// v4 = (7 - (3 + 3)) * 1;
// result = (1 * v4);
// if ( result <= 0 )
// return result;
// a2[3] = 0x16D4E96;
// result = a2;
// *a2 = 0x8D8A61B8;
// a2[1] = 0x55425F9D;
// a2[2] = 0x97966C90;
// return result;
// }
v35 = sub_1402798A0(v57, v95);
// void __fastcall sub_14027DDA0(_BYTE *a1)
// {
// if ( a1[0xF] )
// {
// *a1 ^= 0xF9u;
// a1[1] ^= 0xFu;
// a1[2] ^= 0xF3u;
// a1[3] ^= 0xF9u;
// a1[4] ^= 0xE5u;
// a1[5] ^= 0x2Bu;
// a1[6] ^= 0x6Du;
// a1[7] ^= 0x19u;
// a1[8] ^= 0xF9u;
// a1[9] ^= 0xFu;
// a1[0xA] ^= 0xF3u;
// a1[0xB] ^= 0xF9u;
// a1[0xC] ^= 0xE5u;
// a1[0xD] ^= 0x2Bu;
// a1[0xE] ^= 0x6Du;
// a1[0xF] = 0;
// }
// }
sub_14027DDA0(v35);
v36 = stdstring_140017B00(&STACK[0x578], v35);
if ( *(v36 + 0x18) >= 0x10ui64 )
v36 = *v36;
QString::QString(v64, v36);
v37 = QSettings::QSettings(v89, &CLicence->qstr_reg_user_CBEWIN_60, 0i64);
v38 = QVariant::QVariant(v88);
v39 = QSettings::value(v37, v87, v64, v38);
v40 = QVariant::toString(v39, v72);
QString::operator=(&hexInput, v40);
QString::~QString(v72);
QVariant::~QVariant(v87);
QVariant::~QVariant(v88);
QSettings::~QSettings(v89);
QString::~QString(v64);
free_stdstr_140017BF0(&STACK[0x578]);
for ( m = 0i64; m < 0xF; ++m )
v95[m] |= 0x91 - m;
}
QString::~QString(&lic_type[1]);
LABEL_52:
v51 = (7 - (3 + 3)) * (*(hexInput + 4) == 0);
if ( (1 * v51) )
{
ClearLicence_mem_temp_1402742B0(CLicence);
goto LABEL_67;
}
v51 = (7 - (3 + 3)) * 0;
if ( (1 * v51) )
{
v51 = (7 - (3 + 3)) * 1;
if ( (1 * v51) )
v51 = (7 - (3 + 3)) * 4.0;
goto LABEL_67;
}
v51 = (7 - (3 + 3)) * (operator==(&hexInput, &CLicence->qstr_licinfo_28) == 0);
if ( (1 * v51) )
{
ClearLicence_mem_temp_1402742B0(CLicence);
QString::QString(&info);
lic_mid_14026BAF0 = get_lic_mid_14026BAF0(CLicence);
setkey_140206B60(v91, lic_mid_14026BAF0);
v43 = DecodeLicenseData_140207160(v91, v73, &hexInput);
QString::operator=(&info, v43);
QString::~QString(v73);
v51 = (7 - (3 + 3)) * (*(info + 4) == 0);
if ( (1 * v51) )
{
cpuid_1401E5910 = get_cpuid_1401E5910(v74);
v45 = QString::toLongLong(cpuid_1401E5910, 0i64, 0x10);
setkey_140206B60(v90, v45);
QString::~QString(v74);
v46 = DecodeLicenseData_140207160(v90, v75, &hexInput);
QString::operator=(&info, v46);
QString::~QString(v75);
v51 = (7 - (3 + 3)) * (*(info + 4) == 0);
if ( (1 * v51) )
{
v51 = (7 - (3 + 3)) * 1;
if ( (1 * v51) > 0 )
{
sub_140064350(v90);
sub_140064350(v91);
goto LABEL_65;
}
}
sub_140064350(v90);
}
sub_140064350(v91);
v52[0] = 0;
lic_type[0] = 0;
QDate::currentDate(&startDate);
QDate::currentDate(&endDate_1);
LOBYTE(v4) = LoadAndVerifyLicense_14027ADC0(CLicence, &info, lic_type, &startDate, &endDate_1, v52) == 0;
v51 = (7 - (3 + 3)) * v4;
if ( !(1 * v51) || (v51 = (7 - (3 + 3)) * 1, (1 * v51) <= 0) )
{
QWriteLocker::QWriteLocker(v76, &CLicence->qreadwritelock48);
v48 = lic_type[0];
CLicence->lic_type_4 = lic_type[0];
LOBYTE(CLicence->Offline_status_0) = v52[0];
CLicence->lictype_id_10 = sub_140273FC0(CLicence, v48);
CLicence->QDate_startDate_18 = startDate;
CLicence->QDate_Expireddate_20 = endDate_1;
QString::operator=(&CLicence->qstr_licinfo_28, &hexInput);
QWriteLocker::~QWriteLocker(v76);
QString::~QString(&info);
goto LABEL_67;
}
LABEL_65:
QString::~QString(&info);
v47 = 0;
goto LABEL_70;
}
LABEL_67:
v51 = (7 - (3 + 3)) * 1;
if ( (1 * v51) <= 0 )
{
QString::~QString(&hexInput);
return result;
}
v47 = *(CLicence->qstr_licinfo_28 + 4) > 0;
LABEL_70:
QString::~QString(&hexInput);
return v47;
}
关键流程
- 先尝试使用mid作为key解析license数据
- 解密失败后使用cpuid作为key进行解析
v51 = (7 - (3 + 3)) * (operator==(&hexInput, &CLicence->qstr_licinfo_28) == 0);
if ( (1 * v51) )
{
ClearLicence_mem_temp_1402742B0(CLicence);
QString::QString(&info);
lic_mid_14026BAF0 = get_lic_mid_14026BAF0(CLicence);
setkey_140206B60(v91, lic_mid_14026BAF0);
v43 = DecodeLicenseData_140207160(v91, v73, &hexInput);
QString::operator=(&info, v43);
QString::~QString(v73);
v51 = (7 - (3 + 3)) * (*(info + 4) == 0);
if ( (1 * v51) )
{
cpuid_1401E5910 = get_cpuid_1401E5910(v74);
v45 = QString::toLongLong(cpuid_1401E5910, 0i64, 0x10);
setkey_140206B60(v90, v45);
QString::~QString(v74);
v46 = DecodeLicenseData_140207160(v90, v75, &hexInput);
QString::operator=(&info, v46);
- 再次解密(两种方案)
- 解析解密后的许可信息,‘-’进行分隔,4/5组信息
QDate::currentDate(&startDate);
QDate::currentDate(&endDate_1);
LOBYTE(v4) = LoadAndVerifyLicense_14027ADC0(CLicence, &info, lic_type, &startDate, &endDate_1, v52) == 0;
v51 = (7 - (3 + 3)) * v4;
if ( !(1 * v51) || (v51 = (7 - (3 + 3)) * 1, (1 * v51) <= 0) )
{
QWriteLocker::QWriteLocker(v76, &CLicence->qreadwritelock48);
v48 = lic_type[0];
CLicence->lic_type_4 = lic_type[0];
LOBYTE(CLicence->Offline_status_0) = v52[0];
CLicence->lictype_id_10 = sub_140273FC0(CLicence, v48);
CLicence->QDate_startDate_18 = startDate;
CLicence->QDate_Expireddate_20 = endDate_1;
QString::operator=(&CLicence->qstr_licinfo_28, &hexInput);
QWriteLocker::~QWriteLocker(v76);
QString::~QString(&info);
goto LABEL_67;
}
解密所用key的相关函数
GetHardwareID_14026C5D0
(
记作mid, 日志文件ATGUI_2026xxxx.log 中存在
:[ 96 : ATGUI.cpp] Logic cores, xxxxxxxxxxxx
)
void __fastcall GetHardwareID_14026C5D0(CLicence *CLicence)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v22 = 0xFFFFFFFFFFFFFFFEui64;
v16 = CLicence;
get_cpuid_1401E5910(v14);
QString::QString(v13, "\\\\.\\C:");
v1 = 0i64;
FileW = CreateFileW(L"\\\\.\\C:", 0, 0, 0i64, 3u, 0, 0i64);
InBuffer[0] = 0i64;
memset(OutBuffer, 0, sizeof(OutBuffer));
BytesReturned = 0;
DeviceIoControl(FileW, 0x2D1400u, InBuffer, 0xCu, OutBuffer, 0x1000u, &BytesReturned, 0i64);
v3 = QByteArray::QByteArray(v18, OutBuffer + OutBuffer[5], 0x20);
v4 = sub_140204EA0(v3);
v5 = QVariant::QVariant(v23, v4);
v6 = QVariant::toString(v5, v17);
QString::operator=(v13, v6);
QString::~QString(v17);
QVariant::~QVariant(v23);
QByteArray::~QByteArray(v18);
CloseHandle(FileW);
CLicence_1 = v16;
QString::append(v14, v13);
v8 = QString::toUtf8(v14, v21);
v9 = QCryptographicHash::hash(v20, v8, 0i64);
v10 = QByteArray::toHex(v9, v19);
v11 = *(*v10 + 4i64);
v12 = QByteArray::data(v10);
if ( v12 && v11 )
v1 = ComputeHardwareHash_140043210(v12, v11);
CLicence_1->ComputeHardwareHash_8 = v1;
QByteArray::~QByteArray(v19);
QByteArray::~QByteArray(v20);
QByteArray::~QByteArray(v21);
QString::~QString(v13);
QString::~QString(v14);
}
get_cpuid_1401E5910
QString *__fastcall get_cpuid_1401E5910(QString *a1)
{
unsigned int RAX; // edi
__int64 v8; // rax
__int64 v9; // rax
__int64 v10; // rax
const struct QString *v11; // rdi
QString *v12; // rbx
__int64 v14; // [rsp+0h] [rbp-68h] BYREF
int v15; // [rsp+20h] [rbp-48h]
char v16[8]; // [rsp+28h] [rbp-40h] BYREF
char v17[8]; // [rsp+30h] [rbp-38h] BYREF
__int64 v18; // [rsp+38h] [rbp-30h]
QString *v19; // [rsp+40h] [rbp-28h]
_DWORD v20[2]; // [rsp+48h] [rbp-20h] BYREF
__int64 v21; // [rsp+50h] [rbp-18h]
unsigned __int64 v22; // [rsp+58h] [rbp-10h]
v18 = 0xFFFFFFFFFFFFFFFEui64;
v22 = &v14 ^ qword_140E70770;
v19 = a1;
v15 = 0;
QString::QString(a1, &byte_140A00602);
v15 = 1;
v20[0] = 0;
_RAX = 1i64;
__asm { cpuid }
RAX = _RAX;
v20[1] = _RBX;
v21 = _RCX;
v8 = QString::number(v17, _RDX, 0x10i64);
v9 = QString::toUpper(v8, v16);
QString::operator=(a1, v9);
QString::~QString(v16);
QString::~QString(v17);
v10 = QString::number(v20, RAX, 0x10i64);
v11 = QString::toUpper(v10, v17);
v12 = QString::QString(v16, a1);
v15 = 3;
QString::append(v16, v11);
QString::operator=(a1, v12);
QString::~QString(v16);
QString::~QString(v17);
QString::~QString(v20);
return a1;
}
DecodeLicenseData_140207160
// __int64 DecodeLicenseData(__int64 ctx, __int64 resultQStr, __int64 hexInput)
void *__fastcall DecodeLicenseData_140207160(PackContext *a1, __int64 resultQStr, __int64 hexInput)
{
__int64 v5; // rax
__int64 v6; // rdx
QByteArray *v7; // r8
__int64 v8; // rax
char v10[8]; // [rsp+20h] [rbp-28h] BYREF
char v11[8]; // [rsp+28h] [rbp-20h] BYREF
char v12[8]; // [rsp+30h] [rbp-18h] BYREF
__int64 v13; // [rsp+38h] [rbp-10h]
QArrayData *QArrayData; // [rsp+58h] [rbp+10h] BYREF
char v15; // [rsp+68h] [rbp+20h] BYREF
QArrayData = resultQStr;
v13 = 0xFFFFFFFFFFFFFFFEui64;
v5 = QString::toLower(hexInput, v11);
v6 = QString::toLatin1(v5, v10);
QByteArray::fromHex(&v15, v6);
QByteArray::~QByteArray(v10);
QString::~QString(v11);
v7 = QByteArray::QByteArray(v12, &v15);
DecodeDataStream_140207230(a1, &QArrayData, v7);
LODWORD(a1) = QArrayData->size;
v8 = QByteArray::operator char const *(&QArrayData);
QString::fromUtf8(resultQStr, v8, a1);
QByteArray::~QByteArray(&QArrayData);
QByteArray::~QByteArray(&v15);
return resultQStr;
}
DecodeDataStream_140207230
QByteArray *__fastcall DecodeDataStream_140207230(PackContext *a1, QByteArray *out, __int64 data)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v35 = data;
v34 = out;
v30 = 0xFFFFFFFFFFFFFFFEui64;
v3 = data;
v4 = out;
if ( a1->QArrayData_8->size )
{
QByteArray::QByteArray(&array, data);
if ( *(*v3 + 4i64) < 3 )
{
LABEL_6:
QByteArray::QByteArray(v4);
LABEL_22:
QByteArray::~QByteArray(&array);
goto LABEL_23;
}
if ( QByteArray::at(&array, 0) != 3 )
{
LODWORD(a1->error_code_18) = 2;
goto LABEL_6;
}
v6 = QByteArray::at(&array, 1);
v28 = v6;
v7 = QByteArray::mid(&array, &v33, 2i64);
QByteArray::operator=(&array, v7);
QByteArray::~QByteArray(&v33);
size = array->size;
v33 = 0;
if ( size > 0 )
{
v9 = v33;
v10 = size;
v11 = 0;
do
{
v12 = QByteArray::operator[](&array, v31, v9);
v13 = QByteRef::operator char(v12);
v14 = a1->QArrayData_8 + *a1->QArrayData_8->data + (v9 & 7);
v15 = v11 ^ *v14 ^ QByteArray::at(&array, v9);
v16 = QByteArray::operator[](&array, v32, v9);
QByteRef::operator=(v16, v15);
v11 = v13;
++v9;
}
while ( v9 < v10 );
v6 = v28;
v4 = v34;
v3 = v35;
}
v17 = QByteArray::mid(&array, &v33, 1i64);
QByteArray::operator=(&array, v17);
QByteArray::~QByteArray(&v33);
if ( (v6 & 2) != 0 )
{
if ( array->size < 2 )
{
ERROR_3:
LODWORD(a1->error_code_18) = 3;
QByteArray::QByteArray(v4);
goto LABEL_22;
}
QDataStream::QDataStream(v32, &array, 1i64);
QDataStream::operator>>(v32, &v33);
QDataStream::~QDataStream(v32);
v18 = QByteArray::mid(&array, &v36, 2i64);
QByteArray::operator=(&array, v18);
QByteArray::~QByteArray(&v36);
v19 = array->size;
v20 = QByteArray::constData(&array);
v21 = qChecksum(v20, v19);
v22 = v21 == v33;
}
else
{
if ( (v6 & 4) == 0 )
goto LABEL_19;
if ( array->size < 20 )
goto ERROR_3;
QByteArray::left(&array, &v36, 0x14i64);
v23 = QByteArray::mid(&array, &v28, 0x14i64);
QByteArray::operator=(&array, v23);
QByteArray::~QByteArray(&v28);
// Sha1
QCryptographicHash::QCryptographicHash(&v33, 2i64);
QCryptographicHash::addData(&v33, &array);
v24 = QCryptographicHash::result(&v33, &v28);
v22 = QByteArray_equals_140204E20(v24, &v36);
QByteArray::~QByteArray(&v28);
QCryptographicHash::~QCryptographicHash(&v33);
QByteArray::~QByteArray(&v36);
}
if ( !v22 )
goto ERROR_3;
LABEL_19:
if ( (v6 & 1) != 0 )
{
v25 = array->size;
v26 = QByteArray::constData(&array);
qUncompress(&v33, v26, v25);
QByteArray::operator=(&array, &v33);
QByteArray::~QByteArray(&v33);
}
LODWORD(a1->error_code_18) = 0;
QByteArray::QByteArray(v4, &array);
goto LABEL_22;
}
LODWORD(a1->error_code_18) = 1;
QByteArray::QByteArray(out);
LABEL_23:
QByteArray::~QByteArray(v3);
return v4;
}
LoadAndVerifyLicense_14027ADC0
// 返回 1:许可证有效(isValid == true)
//
// 返回 0:许可证无效或解析失败
// local variable allocation has failed, the output may be wrong!
__int64 __fastcall LoadAndVerifyLicense_14027ADC0(
__int64 a1,
__int64 licinfo,
_DWORD *lic_type,
_QWORD *startDate,
__int64 endDate_1,
void *Offline_status)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
a2[1] = 0xFFFFFFFFFFFFFFFEui64;
PackContext_.mid = 0xCFDD4A4CCB0F024i64;
PackContext_.QArrayData_8 = QArrayData::sharedNull();
LODWORD(PackContext_.qw_10) = 0;
*(&PackContext_.qw_10 + 4) = 1i64;
v11 = QDateTime::currentMSecsSinceEpoch(v10, v9);
qsrand(v11);
set_PackContext_140206BC0(&PackContext_);
v12 = DecodeLicenseData_140207160(&PackContext_, v24, licinfo);
QString::QString(&dec_licinfo);
QString::operator=(&dec_licinfo, v12);
QString::~QString(v12);
v25 = (7 - (3 + 3)) * dec_licinfo.d->size;
if ( (1 * v25) )
{
v25 = (7 - (3 + 3)) * 1;
if ( (1 * v25) > 0 )
{
v13 = ParseLicenseString_14027A1D0(1i64, &dec_licinfo, lic_type, startDate, endDate, isValid);
LABEL_19:
v20 = QString::begin(&dec_licinfo);
v21 = QString::end(&dec_licinfo);
v22 = (v21 - v20 + 1) >> 1;
if ( v20 > v21 )
v22 = 0i64;
if ( v22 )
{
while ( v22 )
{
*v20 = 0;
v20 = (v20 + 2);
--v22;
}
}
QString::~QString(&dec_licinfo);
if ( !PackContext_.QArrayData_8->ref
|| PackContext_.QArrayData_8->ref != 0xFFFFFFFF
&& _InterlockedExchangeAdd(&PackContext_.QArrayData_8->ref, 0xFFFFFFFF) == 1 )
{
QArrayData::deallocate(PackContext_.QArrayData_8, 1ui64, 8ui64);
}
return v13;
}
}
else
{
v25 = (7 - (3 + 3)) * 0;
if ( (1 * v25) )
{
v25 = (7 - (3 + 3)) * 1;
if ( (1 * v25) )
v25 = (7 - (3 + 3)) * 3.0;
}
else
{
v25 = (7 - (3 + 3)) * 1;
if ( (1 * v25) > 0 )
{
LicenceCode_14026BC30 = GenerateLicenceKey_14026BC30(obj, a2);
DecryptAndParseLicense_14027B750(endDate, v29, LicenceCode_14026BC30, v30, startDate, endDate, isValid);
v13 = v19;
QString::~QString(a2);
goto LABEL_19;
}
}
}
v14 = QString::begin(&dec_licinfo);
v15 = QString::end(&dec_licinfo);
v16 = (v15 - v14 + 1) >> 1;
if ( v14 > v15 )
v16 = 0i64;
if ( v16 )
{
while ( v16 )
{
*v14 = 0;
v14 = (v14 + 2);
--v16;
}
}
QString::~QString(&dec_licinfo);
result = PackContext_.QArrayData_8;
if ( !PackContext_.QArrayData_8->ref
|| PackContext_.QArrayData_8->ref != 0xFFFFFFFF
&& (result = PackContext_.QArrayData_8, _InterlockedExchangeAdd(&PackContext_.QArrayData_8->ref, 0xFFFFFFFF) == 1) )
{
QArrayData::deallocate(PackContext_.QArrayData_8, 1ui64, 8ui64);
}
return result;
}
GenerateLicenceKey_14026BC30
__int64 __fastcall GenerateLicenceKey_14026BC30(CLicence *obj, __int64 a2)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v23 = a2;
v21 = 0xFFFFFFFFFFFFFFFEui64;
v2 = QString::number(
v18,
((13 * obj->ComputeHardwareHash_8) >> 2) + (((13 * obj->ComputeHardwareHash_8) >> 0x20) >> 2),
0x10i64);
QString::toLower(v2, &v13);
QString::~QString(v18);
v3 = 0;
v4 = 0;
v14 = 0;
v15 = 2;
v16 = 0;
LODWORD(v25) = 7;
while ( 1 )
{
v17 = (7 - (3 + 3)) * 1;
if ( v4 >= (1 * v17) )
break;
v5 = 0;
if ( v13.d->size > 0 )
{
v6 = 7;
LODWORD(v17) = 7;
do
{
if ( (v6 + 9) / 8u != 1 )
{
if ( (1 * ((7 - (3 + 3)) * ((v5 & 1) == 0))) )
{
v3 += *QString::at(&v13, &v22, v5);
}
else if ( !(1 * ((7 - (3 + 3)) * 0)) )
{
v3 -= *QString::at(&v13, &v24, v5);
}
}
++v5;
v6 = LODWORD(v17);
}
while ( v5 < v13.d->size );
v4 = v14;
}
v14 = ++v4;
}
v7 = v3 % 0xFF;
v8 = v16 * v15;
v25 = (7 - (3 + 3)) * ((v8 + 7 + 8 * v8 + 9) / 8u - 1);
if ( (8 * v16 * v15 + 0x10) / 8u == 1 || (((2 * v8 + 0x10) / 8u - 1) * v25) > 0 )
{
v10 = QString::number(v20, v7, 0x10i64);
v11 = QString::rightJustified(v10, v19, 2i64);
v12 = QString::append(&v13, v11);
QString::toUpper(v12, v23);
QString::~QString(v19);
QString::~QString(v20);
QString::~QString(&v13);
return v23;
}
else
{
QString::~QString(&v13);
}
return result;
}
DecryptAndParseLicense_14027B750
// void DecryptAndParseLicense(const QString *encryptedHex, const QString *password, int *lictype, QDate *startDate, QDate *endDate, bool *isValid)
void __fastcall DecryptAndParseLicense_14027B750(
__int64 a1,
__int64 a2,
QString *a3,
_DWORD *a4,
_QWORD *arg_20,
_QWORD *a6,
bool *isOffline)
{
QString *v8; // rdi
struct QChar *v9; // rdi
struct QChar *v10; // rax
unsigned __int64 v11; // rcx
struct QChar *v12; // rdi
struct QChar *v13; // rax
unsigned __int64 v14; // rcx
char v15[8]; // [rsp+30h] [rbp-28h] BYREF
double v16; // [rsp+38h] [rbp-20h]
__int64 v17; // [rsp+40h] [rbp-18h]
__int64 dec_licinfo; // [rsp+60h] [rbp+8h] BYREF
dec_licinfo = a1;
v17 = 0xFFFFFFFFFFFFFFFEui64;
v8 = DecryptChaCha20_1402656B0(v15, a2, a3);
QString::QString(&dec_licinfo);
QString::operator=(&dec_licinfo, v8);
QString::~QString(v8);
v16 = (7 - (3 + 3)) * (*(dec_licinfo + 4) == 0);
if ( !(1 * v16) || (v16 = (7 - (3 + 3)) * 1, (1 * v16) <= 0) )
{
v16 = (7 - (3 + 3)) * 1;
if ( (1 * v16) <= 0 )
{
v9 = QString::begin(&dec_licinfo);
v10 = QString::end(&dec_licinfo);
v11 = (v10 - v9 + 1) >> 1;
if ( v9 > v10 )
v11 = 0i64;
if ( v11 )
{
while ( v11 )
{
*v9 = 0;
v9 = (v9 + 2);
--v11;
}
}
goto LABEL_16;
}
ParseLicenseString_14027A1D0(1i64, &dec_licinfo, a4, arg_20, a6, isOffline);
}
v12 = QString::begin(&dec_licinfo);
v13 = QString::end(&dec_licinfo);
v14 = (v13 - v12 + 1) >> 1;
if ( v12 > v13 )
v14 = 0i64;
if ( v14 )
{
while ( v14 )
{
*v12 = 0;
v12 = (v12 + 2);
--v14;
}
}
LABEL_16:
QString::~QString(&dec_licinfo);
}
ParseLicenseString_14027A1D0
bool __fastcall ParseLicenseString_14027A1D0(
__int64 a1,
__int64 dec_licinfo,
_DWORD *lic_type,
_QWORD *startDate,
_QWORD *endDate,
bool *isOfflineMode)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v26 = 0xFFFFFFFFFFFFFFFEui64;
v6 = 1;
QStringList_1 = QString::split(dec_licinfo, &QStringList, '-', 1i64, 1);
p = QStringList_1->p;
QStringList_1->p = *&QListData::shared_null;
if ( !QStringList.p->ref
|| QStringList.p->ref != 0xFFFFFFFF && _InterlockedExchangeAdd(&QStringList.p->ref, 0xFFFFFFFF) == 1 )
{
v8 = QStringList.p;
v9 = &QStringList.p->array[QStringList.p->begin];
for ( i = &QStringList.p->array[QStringList.p->end]; i != v9; QString::~QString(i) )
i += 0xFFFFFFFF;
QListData::dispose(v8);
}
v11 = 0;
p_begin = &p->begin;
v13 = p->end - p->begin;
if ( v13 >= 4 && v13 <= 5 )
v6 = 0;
if ( (1 * ((7 - (3 + 3)) * v6)) && (1 * ((7 - (3 + 3)) * 1)) > 0 )
goto LABEL_30;
p_begin = &p->begin;
*lic_type = QString::toShort(&p->array[p->begin], 0i64, 0xA);
v14 = QString::toInt(&p[1] + p->begin, 0i64, 0xA);
v15 = startDate;
*startDate = *QDate::fromJulianDay(v27, v14);
v16 = QString::toInt(&p[1].begin + p->begin, 0i64, 0xA);
*endDate = *QDate::fromJulianDay(v28, v16);
LOBYTE(v11) = p->end - p->begin > 4;
if ( (1 * ((7 - (3 + 3)) * v11)) )
{
*isOfflineMode = QString::toInt(&p[2] + *p_begin, 0i64, 0xA) != 0;
v17 = endDate;
goto LABEL_19;
}
if ( (1 * ((7 - (3 + 3)) * 0)) )
{
if ( (1 * ((7 - (3 + 3)) * 1)) )
{
v17 = endDate;
v15 = startDate;
goto LABEL_19;
}
}
else
{
*isOfflineMode = 1;
}
v17 = endDate;
v15 = startDate;
LABEL_19:
if ( (1 * ((7 - (3 + 3)) * 1)) <= 0 )
{
result = p;
if ( p->ref )
{
if ( p->ref == 0xFFFFFFFF )
return result;
result = p;
if ( _InterlockedExchangeAdd(&p->ref, 0xFFFFFFFF) != 1 )
return result;
}
v19 = &p->array[*p_begin];
for ( j = &p->array[p->end]; j != v19; QString::~QString(j) )
j += 0xFFFFFFFF;
QListData::dispose(p);
return result;
}
if ( (*v15 + 0xB69EEFF91Fi64) <= 0x16D3E147973i64 && (*v17 + 0xB69EEFF91Fi64) <= 0x16D3E147973i64 )
{
v21 = 1;
goto LABEL_31;
}
LABEL_30:
v21 = 0;
LABEL_31:
if ( p->ref && (p->ref == 0xFFFFFFFF || _InterlockedExchangeAdd(&p->ref, 0xFFFFFFFF) != 1) )
return v21;
v22 = &p->array[*p_begin];
for ( k = &p->array[p->end]; k != v22; QString::~QString(k) )
k += 0xFFFFFFFF;
QListData::dispose(p);
return v21;
}
get_lic_type_1400722A0
__int64 __fastcall get_lic_type_1400722A0(__int64 a1, int a2)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v33[1] = 0xFFFFFFFFFFFFFFFEui64;
v4 = 0i64;
v5 = qword_140EC1A50;
// 1117=免费版
QString::QString(&v22, "1117");
load_local_str_140136C90(v5, a1, &v22);
QString::~QString(&v22);
v28 = (7 - (3 + 3)) * a2;
switch ( (1 * v28) )
{
case 1:
v6 = qword_140EC1A50;
// 1323=家庭版
QString::QString(&v23, "1323");
v7 = load_local_str_140136C90(v6, &v29, &v23);
QString::operator=(a1, v7);
QString::~QString(&v29);
QString::~QString(&v23);
break;
case 2:
v8 = qword_140EC1A50;
// 1468=标准版
QString::QString(&v24, "1468");
v9 = load_local_str_140136C90(v8, &v30, &v24);
QString::operator=(a1, v9);
QString::~QString(&v30);
QString::~QString(&v24);
break;
case 3:
// 1324=专业版
v10 = qword_140EC1A50;
QString::QString(&v25, "1324");
v11 = load_local_str_140136C90(v10, &v31, &v25);
QString::operator=(a1, v11);
QString::~QString(&v31);
QString::~QString(&v25);
break;
case 4:
v12 = qword_140EC1A50;
// 1326=旗舰版
QString::QString(&v26, "1326");
v13 = load_local_str_140136C90(v12, &v32, &v26);
QString::operator=(a1, v13);
QString::~QString(&v32);
QString::~QString(&v26);
break;
case 5:
case 6:
v14 = qword_140EC1A50;
// 1325=服务器版
QString::QString(&v27, "1325");
v15 = load_local_str_140136C90(v14, v33, &v27);
QString::operator=(a1, v15);
QString::~QString(v33);
QString::~QString(&v27);
break;
default:
v16 = qword_140EC1A50;
// 1117=免费版
QString::QString(&v20, "1117");
v34 = v16 + 0x10;
if ( v16 != 0xFFFFFFFFFFFFFFF0ui64 )
{
QMutex::lock();
v34 |= 1ui64;
}
sub_1401316F0(v16 + 0x38);
d = *(*(v16 + 0x38) + 0x10i64);
if ( !d )
goto LABEL_16;
do
{
if ( operator<(&d[3], &v20) )
{
d = d[2].d;
}
else
{
v4 = d;
d = d[1].d;
}
}
while ( d );
if ( !v4 || operator<(&v20, &v4[3]) )
LABEL_16:
v4 = (*(v16 + 0x38) + 8i64);
sub_1401316F0(v16 + 0x38);
if ( v4 == (*(v16 + 0x38) + 8i64) )
{
v18 = sub_140131C20(v16 + 0x40, &v20);
QString::QString(v21, v18);
}
else
{
QString::QString(v21, v4 + 4);
}
QMutexLocker::~QMutexLocker(&v34);
QString::operator=(a1, v21);
QString::~QString(v21);
QString::~QString(&v20);
break;
}
result = (1 * ((7 - (3 + 3)) * 1));
if ( result > 0 )
return a1;
return result;
}
py
import struct
import zlib
import hashlib
import random
from datetime import date
from typing import Tuple, Optional
# ---------- CRC-16/X.25 (Qt qChecksum) ----------
def crc16_x25(data: bytes) -> int:
"""CRC-16/X.25: poly=0x1021, init=0xFFFF, xorout=0xFFFF, refin=True, refout=True"""
crc = 0xFFFF
for b in data:
crc ^= b & 0xFF
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0x8408 # 0x8408 是 0x1021 的逆序
else:
crc >>= 1
return crc ^ 0xFFFF
def q_checksum(data: bytes) -> int:
crc = 0xFFFF
for b in data:
crc ^= b
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0x8408
else:
crc >>= 1
return crc ^ 0xFFFF
def q_compress(data: bytes, level: int = 9) -> bytes:
compressed = zlib.compress(data, level)
return struct.pack('>I', len(data)) + compressed
def q_uncompress(data: bytes) -> Optional[bytes]:
if len(data) < 4:
return None
orig_len = struct.unpack('>I', data[:4])[0]
try:
decompressed = zlib.decompress(data[4:])
except zlib.error:
return None
if len(decompressed) != orig_len:
return None
return decompressed
def feedback_encrypt(plain: bytes, key: bytes) -> bytes:
if len(key) != 8:
raise ValueError("Key must be 8 bytes")
res = bytearray()
prev = 0
for i, b in enumerate(plain):
k = key[i % 8]
c = b ^ k ^ prev
res.append(c)
prev = c
return bytes(res)
def feedback_decrypt(cipher: bytes, key: bytes) -> bytes:
if len(key) != 8:
raise ValueError("Key must be 8 bytes")
res = bytearray()
prev = 0
for i, c in enumerate(cipher):
k = key[i % 8]
p = c ^ k ^ prev
res.append(p)
prev = c
return bytes(res)
def encode_data_stream(plain: bytes, key: bytes,
compress: bool = True,
use_checksum: bool = True,
use_hash: bool = False,random_byte = random.randint(0, 255)) -> bytes:
flags = 0
payload = plain
if compress:
compressed = q_compress(payload)
if compressed and len(compressed) < len(payload):
payload = compressed
flags |= 1
if use_hash:
h = hashlib.sha1(payload).digest()
payload = h + payload
flags |= 4
elif use_checksum:
crc = q_checksum(payload)
payload = struct.pack('>H', crc) + payload # 小端存储
flags |= 2
payload = bytes([random_byte]) + payload
encrypted = feedback_encrypt(payload, key)
return bytes([3, flags]) + encrypted
def decode_data_stream(packed: bytes, key: bytes) -> Tuple[Optional[bytes], int]:
if len(packed) < 3:
return (None, 1)
version = packed[0]
flags = packed[1]
if version != 3:
return (None, 2)
encrypted = packed[2:]
decrypted = feedback_decrypt(encrypted, key)
if len(decrypted) < 1:
return (None, 3)
payload = decrypted[1:]
if flags & 2:
if len(payload) < 2:
return (None, 3)
stored_crc = struct.unpack('>H', payload[:2])[0] # 小端读取
# print('stored_crc:',hex(stored_crc))
data = payload[2:]
if q_checksum(data) != stored_crc:
return (None, 3)
payload = data
elif flags & 4:
if len(payload) < 20:
return (None, 3)
stored_hash = payload[:20]
data = payload[20:]
if hashlib.sha1(data).digest() != stored_hash:
return (None, 3)
payload = data
if flags & 1:
decompressed = q_uncompress(payload)
if decompressed is None:
return (None, 3)
payload = decompressed
return (payload, 0)
def encode_license_data(plain_text: str, key: bytes) -> str:
utf8 = plain_text.encode('utf-8')
packed = encode_data_stream(utf8, key, compress=True, use_checksum=True, use_hash=False,random_byte=0)
return packed.hex().upper()
def decode_license_data(hex_str: str, key: bytes) -> Tuple[Optional[str], int]:
try:
packed = bytes.fromhex(hex_str)
except ValueError:
return (None, 1)
data, err = decode_data_stream(packed, key)
if err != 0:
return (None, err)
try:
plain = data.decode('utf-8')
except UnicodeDecodeError:
return (None, 3)
return (plain, 0)
def parse_license_string(lic_str: str):
'''
lic_type-start_jd-end_jd-{unknown}-{isOffline}
4或5组数据,
第4组数据未知
第5组默认1==》offline,
'''
parts = lic_str.strip().split('-')
if len(parts) not in (4, 5):
print('[!]parse_license_string error!')
return (None, None, None, None,False)
try:
lic_type = int(parts[0])
start_jd = int(parts[1])
end_jd = int(parts[2])
start_date = qt_julian_to_python_date(start_jd)
end_date = qt_julian_to_python_date(end_jd)
unknown = int(parts[3])
if len(parts)==5:
isOffline = (int(parts[4]) != 0)
else:
# 4
isOffline=True
return (lic_type, start_date, end_date, unknown,isOffline)
except:
return (None, None, None,None, False)
def load_and_verify_license(encrypted_hex: str):
mid = 0xCFDD4A4CCB0F024
key = mid.to_bytes(8, 'little')
plain, err = decode_license_data(encrypted_hex, key)
if err != 0:
return (False, None, None, None, None,False)
lic_type, s, e, unknown,offline = parse_license_string(plain)
if lic_type is None:
return (False, None, None, None, None,False)
# 简单日期有效性检查(可根据需要扩展)
if s < e:
return (True, lic_type, s, e, unknown,offline)
else:
return (False, lic_type, s, e, unknown,offline)
def python_date_to_qt_julian(d: date) -> int:
"""将 Python date 转换为 Qt QDate 的儒略日"""
return d.toordinal() + 1721425
def qt_julian_to_python_date(jd: int) -> date:
"""将 Qt 儒略日转换为 Python date"""
return date.fromordinal(jd - 1721425)
# offline==>Must be set to True
def generate_valid_license(lic_type: int, start_date: date, end_date: date, unknown:int,offline: bool = True) -> str:
mid = 0xCFDD4A4CCB0F024
key = mid.to_bytes(8, 'little')
start_jd = python_date_to_qt_julian(start_date)
end_jd = python_date_to_qt_julian(end_date)
# 必须生成4个字段,标志位为 1 或 0
flag = '1' if offline else '0'
# plain = f"{lic_type}-{start_jd}-{end_jd}-{flag}" #-{unknown}
plain = f"{lic_type}-{start_jd}-{end_jd}-{unknown}-{flag}"
print(f'[-]generate_valid_license plain:{plain},key:{key.hex()}')
return encode_license_data(plain, key)
# pip install cpuid
import cpuid
def get_cpuid_string() -> str:
"""
模拟 get_cpuid_1401E5910 函数,返回 CPUID 信息字符串。
执行 CPUID 指令 (EAX=1),拼接为十六进制字符串。
"""
# 执行 CPUID 功能 1
eax,ebx,ecx,edx = cpuid.cpuid(1)
# 格式化为 8 位十六进制大写字符串,按 EDX EAX 顺序拼接
result = f"{edx:X}{eax:X}"
return result
def test():
'''
这里采用cpuid作为第一层key
数据 压缩+crc16
第二次仍采用第一层的加密方式(xor;没有采用mid生成chacha20 key的方式)
'''
id=get_cpuid_string()
key=int(id,16).to_bytes(8,'little')
print('[+]cpuid_key:',key.hex())
start = date(2026, 1, 1)
end = date(2066, 6, 6)
#4==>旗舰版
lic_hex = generate_valid_license(4, start, end,666,True)
print(f"[-]Generated: {lic_hex}")
ok, ver, s, e, v,o = load_and_verify_license(lic_hex)
print(f"[-]Result: {ok}, ver={ver}, start={s}, end={e}, unknown={v},offline:{o}")
# 加密打包
hex_str = encode_license_data(lic_hex, key)
print("[=]reg Anytxt/License value:\n", hex_str,sep='')
pass
if __name__=='__main__':
test()
pass
ps


浙公网安备 33010602011771号