EasyUEFI 离线注册分析

news/发布时间2024/5/16 4:14:28

离线注册分析

仅做离线分析,文件版本5.3.0.2

目录
  • 离线注册分析
    • 一、注册码分析
      • register_CUpgradeDlg_21_id40_448DE0
      • check_rsa_pubk_dec_47D1D0
        • rsa_dec_47CEF0
      • 校验注册码信息
        • sub_47D430
    • 二、离线激活码分析
      • ok_440920
      • unline_check_450320
        • Init_490DD0
      • 校验激活码sub_491730
  • py

一、注册码分析

0、 通过字符信息、窗口事件、调用栈等信息定位到CUpgradeDlg

1、分析CUpgradeDlg metaClass 并根据虚表定位构造函数,

metaClass :

.text:00673220                             CUpgradeDlg_mate_673220 proc near       ; DATA XREF: .rdata:006759C4↓o
.text:00673220 000 6A 0C                                   push    0Ch
.text:00673222 004 6A 04                                   push    4
.text:00673224 008 68 10 96 81 00                          push    offset CUpgradeDlg_map_819610
.text:00673229 00C 68 74 86 8D 00                          push    offset parent_metaClass_8D8674
.text:0067322E 010 68 60 80 44 00                          push    offset CUpgradeDlg_manufacture_448060
.text:00673233 014 68 28 E8 87 00                          push    offset aCupgradedlg ; "CUpgradeDlg"
.text:00673238 018 B9 90 DA 8F 00                          mov     ecx, offset dword_8FDA90
.text:0067323D 018 E8 5C 28 F1 FF                          call    FX__FXMetaClass__metaClass_585A9E ; const FXchar* name,FXObject *(fac)(),const FXMetaClass* base,const void* ass,FXuint nass,FXuint assz
.text:00673242 000 68 C0 48 67 00                          push    offset sub_6748C0 ; void (__cdecl *)()
.text:00673247 004 E8 FC C4 F6 FF                          call    _atexit
.text:0067324C 004 59                                      pop     ecx
.text:0067324D 000 C3                                      retn
.text:0067324D                             CUpgradeDlg_mate_673220 endp

2、构造函数分析,获取控件id组成

image-20240421144126525

得到Register 注册按钮id为0x40

image-20240421143624807

3、进而分析CUpgradeDlg_map_819610 定位控件事件

image-20240421144404763

register_CUpgradeDlg_21_id40_448DE0

激活码格式XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXX (输入时自动‘-’拼接)

int __thiscall register_CUpgradeDlg_21_id40_448DE0(CUpgradeDlg *this, int a2, int a3, int a4)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v43 = a2;v44 = a4;email = (char *)this->email_98;memset(rsa_publick_dec, 0, sizeof(rsa_publick_dec));memset(appversion, 0, sizeof(appversion));ver2[0] = 0;ver1 = 0;sub_408680(email, (int)&s_email);             // support@hasleo.comv50 = 0;sub_408680((char *)this->CLicenseInputTextField_9C, (int)&s_license);LOBYTE(v50) = 1;memset(ws_email_1, 0, 0x100);memset(ws_license, 0, 0x6C);v7 = AppVersion_44FF00(appversion);v8 = v6;v40 = v6;if ( !(_WORD)v6 ){v9 = fxstring_580929((void **)&s_email);fxstring_5805EF((void **)&s_email, v9);if ( !*((_DWORD *)s_email + 0xFFFFFFFF) ){v10 = GetLastError() + 0xD001F000000000i64;v8 = HIDWORD(v10);v7 = v10;v35 = v10;v34 = 0xD1;LABEL_57:v40 = v8;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\UpgradeDlg.cpp", v34, v35);goto LABEL_58;}v11 = fxstring_580929((void **)&s_license);fxstring_5805EF((void **)&s_license, v11);if ( !*((_DWORD *)s_license + 0xFFFFFFFF) ){v12 = GetLastError() + 0xD701F100000000i64;v8 = HIDWORD(v12);v7 = v12;v35 = v12;v34 = 0xD8;goto LABEL_57;}if ( !s_email|| v37 == (_BYTE *)0xFFFFFF2C|| MultiByteToWideChar(0xFDE9u, 0, s_email, 0xFFFFFFFF, ws_email_1, 0x80) <= 0 ){v13 = GetLastError() + 0xDE000E00000000i64;v8 = HIDWORD(v13);v7 = v13;v35 = v13;v34 = 0xDF;goto LABEL_57;}if ( !s_license|| v37 == (_BYTE *)0xFFFFFF9C|| MultiByteToWideChar(0xFDE9u, 0, s_license, 0xFFFFFFFF, ws_license, 0x36) <= 0 ){v14 = GetLastError() + 0xE4000E00000000i64;v8 = HIDWORD(v14);v7 = v14;v35 = v14;v34 = 0xE5;goto LABEL_57;}license_format_455420((int)ws_license, ws_license);++this->field_A4;v7 = check_rsa_pubk_dec_47D1D0(ws_email_1, ws_license, rsa_publick_dec);v8 = v15;v40 = v15;if ( (_WORD)v15 ){log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\UpgradeDlg.cpp", 0xEE, v7, v15);goto LABEL_58;}v7 = sub_47D430(rsa_publick_dec, ver2, &ver1);v8 = v16;v40 = v16;if ( (_WORD)v16 ){log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\UpgradeDlg.cpp", 0xF4, v7, v16);goto LABEL_58;}if ( ver2[0] != 1 || rsa_publick_dec[1] != 1 ){v32 = GetLastError() + 0xF901F100000000i64;// Invalid license key.v8 = HIDWORD(v32);v7 = v32;v35 = v32;v34 = 0xFA;goto LABEL_57;}if ( (unsigned __int8)(ver1 - 1) > 5u || ver1 == 6 || ver1 == 5 ){v31 = GetLastError() + 0x10001F100000000i64;v8 = HIDWORD(v31);v7 = v31;v35 = v31;v34 = 0x101;goto LABEL_57;}if ( rsa_publick_dec[3] || (v17 = rsa_publick_dec[8] & 0xF, (rsa_publick_dec[8] & 0xF) != 0) && v17 != 1 && v17 != 2 ){v30 = GetLastError() + 0x10701F100000000i64;v8 = HIDWORD(v30);v7 = v30;v35 = v30;v34 = 0x108;goto LABEL_57;}// "5.3.0.2"if ( appversion[0] > (unsigned int)(unsigned __int8)rsa_publick_dec[2] && (ver1 == 4 || ver1 == 2) ){v18 = GetLastError() + 0x11001F100000000i64;v8 = HIDWORD(v18);v7 = v18;v35 = v18;v34 = 0x111;goto LABEL_57;}if ( (ver1 == 3 || ver1 == 1)&& v17 == 2&& rsa_publick_dec[0x11]&& _time64(0) >= *(_DWORD *)&rsa_publick_dec[4] + 2678400 * (unsigned int)(unsigned __int8)rsa_publick_dec[0x11] )// rsa_publick_dec[0x11] 月{v19 = GetLastError() + 0x11B01F100000000i64;v8 = HIDWORD(v19);v7 = v19;v35 = v19;v34 = 0x11C;goto LABEL_57;}unknowclass_4500E0 = get_unknowclass_4500E0();v21 = do_net_check_4502D0((int)ws_license, unknowclass_4500E0, 0) & 0xFFF;// net_checkif ( v21 <= 9 ){if ( v21 == 9 || !v21 )                   // 9 时离线{this->Active_status_B4 = v21;fxstring_5805EF((void **)&this->s_email_A8, (void **)&s_email);// [esp+20]:"support@hasleo.com"fxstring_5805EF((void **)&this->s_license_AC, (void **)&s_license);v36 = v44;this->ver1_B0 = (unsigned __int8)ver1;v22 = sub_585C8E(this, v43, a3, v36);LABEL_42:v23 = v22;LOBYTE(v50) = 0;FX::FXString::~FXString((void **)&s_license);v50 = 0xFFFFFFFF;FX::FXString::~FXString((void **)&s_email);return v23;}goto LABEL_51;}if ( v21 > 0xE ){if ( v21 == 0xF ){v29 = GetLastError() + 0x13D01F300000000i64;// Your license has expired, please renew it to continue using this software.v8 = HIDWORD(v29);v7 = v29;v35 = v29;v34 = 0x13E;goto LABEL_57;}if ( v21 != 0xFFF )goto LABEL_51;}else{if ( v21 == 0xE ){v26 = GetLastError() + 0x13701F500000000i64;// The license key has been disabled.v8 = HIDWORD(v26);v7 = v26;v35 = v26;v34 = 0x138;goto LABEL_57;}if ( v21 != 0xA ){if ( v21 == 0xD ){v25 = GetLastError() + 0x13101F400000000i64;// The license key has exceeded the number of activations allowed.v8 = HIDWORD(v25);v7 = v25;v35 = v25;v34 = 0x132;goto LABEL_57;}LABEL_51:v27 = GetLastError() + 0x14301F600000000i64;// Activation failed.v8 = HIDWORD(v27);v7 = v27;v35 = v27;v34 = 0x144;goto LABEL_57;}}v28 = GetLastError() + 0x12601F100000000i64;v8 = HIDWORD(v28);v7 = v28;v35 = v28;v34 = 0x127;goto LABEL_57;}log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\UpgradeDlg.cpp", 0xC9, v7, v6);LABEL_58:v46 = 0;v33 = (unsigned __int16)(((unsigned __int64)GetLastError() + 0x1F100000000i64) >> 0x20);if ( v46 || v33 != (unsigned __int16)v40 ){if ( (unsigned __int16)v40 | v46 )error_402CA0(this, this->FXApp_90, v7, v8, 0);}else{error_402CA0(this, this->FXApp_90, v7, v8, 0);if ( this->field_A4 >= 3u ){v22 = sub_585CAD(this, v43, a3, v44);goto LABEL_42;}}LOBYTE(v50) = 0;FX::FXString::~FXString((void **)&s_license);v50 = 0xFFFFFFFF;FX::FXString::~FXString((void **)&s_email);return 1;
}

check_rsa_pubk_dec_47D1D0

对注册码进行自定义base32解码,再进行RSA公钥解密

自定义字符表为ABCDEFGHJKLMNPQRSTUVWXYZ23456789

rsa解密后为0x1e字节,最后一位为crc8校验值

int __usercall check_rsa_pubk_dec_47D1D0@<eax>(const unsigned __int16 *ws_email_1@<edx>,const wchar_t *ws_license@<ecx>,char *rsa_enc)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]memset(str_license, 0, 0x31);v21 = 0;memset(dec, 0, sizeof(dec));v5 = wcslen(ws_email_1);if ( ws_license && wcslen(ws_license) == 48 && ws_email_1 && v5 ){str_email = (char *)malloc(v5 + 1);v7 = str_email;if ( str_email ){if ( v5 == wcstombs(str_email, ws_email_1, v5 + 1) ){_strupr(v7);if ( wcstombs(str_license, ws_license, 49u) == 48 ){_strupr(str_license);v8 = custom_base32_decode_47D0A0(dec, str_license);if ( (_WORD)v12 ){log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x2A0, v8, v12);}else{v8 = rsa_dec_47CEF0(dec, rsa_enc);if ( v13 ){log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", v18, 0x2A7, v8);}else{v14 = rsa_enc[0x1D];rsa_enc[0x1D] = 0;if ( v14 != (unsigned __int8)CRC8_47D7E0(0, (unsigned __int8 *)rsa_enc) ){v15 = GetLastError() + 0x2AF01F100000000i64;v8 = v15;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x2B0, v15);}v7 = *(char **)dec;}}}else{v11 = GetLastError() + 0x297000E00000000i64;v8 = v11;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x298, v11);}}else{v10 = GetLastError() + 0x28F000E00000000i64;v8 = v10;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x290, v10);}}else{v9 = GetLastError() + 0x289000300000000i64;v8 = v9;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x28A, v9);}if ( v7 )free(v7);}else{v17 = GetLastError() + 0x28101F100000000i64;v8 = v17;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x282, v17);}return v8;
}

rsa_dec_47CEF0

int __thiscall rsa_dec_47CEF0(char *data, char *out)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v2 = 0;memset(rsa_PUBLICkey, 0, 0x1000u);qmemcpy(rsa_PUBLICkey,"-----BEGIN RSA PUBLIC KEY-----\n""MCYCHwC9s2qhNcaeKtlin3VtwnU9Vv4x/j0wBPS43F/8eKMCAwEAAQ==\n""-----END RSA PUBLIC KEY-----\n",0x75u);v3 = BIO_new_mem_buf(rsa_PUBLICkey, 0x75);v4 = v3;if ( v3 ){bio_SSL_SESSION = PEM_read_bio_SSL_SESSION(v3, 0, 0, 0);v7 = bio_SSL_SESSION;if ( bio_SSL_SESSION ){// static int RSA_eay_public_encrypt(int flen, const unsigned char *from,//          unsigned char *to, RSA *rsa, int padding)if ( RSA_eay_public_decrypt_602D40(0x1E, (int)data, (int)out, (int)bio_SSL_SESSION, 3) < 0 ){v9 = GetLastError() + 0x13D000200000000i64;v2 = v9;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x13E, v9);}}else{v8 = GetLastError() + 0x135007200000000i64;v2 = v8;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x136, v8);}BIO_free_all(v4);if ( v7 )RSA_free(v7);}else{v5 = GetLastError() + 0x12D000300000000i64;v2 = v5;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x12E, v5);}CRYPTO_cleanup_all_ex_data();return v2;
}

校验注册码信息

/*
if (license_info[8]&0xf)!=0:if (license_info[8]&0xf)==1 or (license_info[8]&0xf)==2:ver2=license_info[0]ver1=license_info[0x10]else:error
else:ver2=license_info[0]&0x1fver1=license_info[0]>>5
*/ 
v7 = sub_47D430(rsa_publick_dec, ver2, &ver1);v8 = v16;v40 = v16;if ( (_WORD)v16 ){log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\UpgradeDlg.cpp", 0xF4, v7, v16);goto LABEL_58;}
//ver2==1  license_info[1]==1if ( ver2[0] != 1 || rsa_publick_dec[1] != 1 ){v32 = GetLastError() + 0xF901F100000000i64;// Invalid license key.v8 = HIDWORD(v32);v7 = v32;v35 = v32;v34 = 0xFA;goto LABEL_57;}
//ver1<5if ( (unsigned __int8)(ver1 - 1) > 5u || ver1 == 6 || ver1 == 5 ){v31 = GetLastError() + 0x10001F100000000i64;v8 = HIDWORD(v31);v7 = v31;v35 = v31;v34 = 0x101;goto LABEL_57;}
//license_info[3]==0
//(license_info[8] & 0xF)==0 or 1 or 2if ( rsa_publick_dec[3] || (v17 = rsa_publick_dec[8] & 0xF, (rsa_publick_dec[8] & 0xF) != 0) && v17 != 1 && v17 != 2 ){v30 = GetLastError() + 0x10701F100000000i64;v8 = HIDWORD(v30);v7 = v30;v35 = v30;v34 = 0x108;goto LABEL_57;}// "5.3.0.2"
//5<=license_info[2]
//ver1!=2  ver1!=4if ( appversion[0] > (unsigned int)(unsigned __int8)rsa_publick_dec[2] && (ver1 == 4 || ver1 == 2) ){v18 = GetLastError() + 0x11001F100000000i64;v8 = HIDWORD(v18);v7 = v18;v35 = v18;v34 = 0x111;goto LABEL_57;}
/*
(ver1!=1 and ver1!=3) || 
(license_info[8] & 0xF)!=2 ||
license_info[0x11]==0 || 
(time(2)>license_info[4] + 2678400 *license_info[0x11])
*/if ( (ver1 == 3 || ver1 == 1)&& v17 == 2&& rsa_publick_dec[0x11]&& _time64(0) >= *(_DWORD *)&rsa_publick_dec[4] + 2678400 * (unsigned int)(unsigned __int8)rsa_publick_dec[0x11] )// rsa_publick_dec[0x11] 月{v19 = GetLastError() + 0x11B01F100000000i64;v8 = HIDWORD(v19);v7 = v19;v35 = v19;v34 = 0x11C;goto LABEL_57;}unknowclass_4500E0 = get_unknowclass_4500E0();v21 = do_net_check_4502D0((int)ws_license, unknowclass_4500E0, 0) & 0xFFF;// net_checkif ( v21 <= 9 ){if ( v21 == 9 || !v21 )                   // 9 时离线{this->Active_status_B4 = v21;fxstring_5805EF((void **)&this->s_email_A8, (void **)&s_email);// [esp+20]:"support@hasleo.com"fxstring_5805EF((void **)&this->s_license_AC, (void **)&s_license);v36 = v44;this->ver1_B0 = (unsigned __int8)ver1;v22 = sub_585C8E(this, v43, a3, v36);LABEL_42:v23 = v22;LOBYTE(v50) = 0;FX::FXString::~FXString((void **)&s_license);v50 = 0xFFFFFFFF;FX::FXString::~FXString((void **)&s_email);return v23;}goto LABEL_51;}

sub_47D430

int __fastcall sub_47D430(char *rsa_publick_dec, char *ver2, char *ver1)
{int result; // eax__int64 v4; // kr00_8result = 0;if ( (*((_WORD *)rsa_publick_dec + 4) & 0xF) != 0 ){// +8  低4bit 不等于0时,值应为1或2if ( (*((_WORD *)rsa_publick_dec + 4) & 0xF) == 1 ){*ver2 = *rsa_publick_dec;*ver1 = rsa_publick_dec[0x10];}else if ( (*((_WORD *)rsa_publick_dec + 4) & 0xF) == 2 ){*ver2 = *rsa_publick_dec;*ver1 = rsa_publick_dec[0x10];}else{v4 = GetLastError() + 0x33301F100000000i64;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\License.cpp", 0x334, v4);return v4;}}else{// 取首字节 5bit*ver2 = *rsa_publick_dec & 0x1F;// (首字节>>5)*ver1 = (unsigned __int8)*rsa_publick_dec >> 5;}return result;
}

二、离线激活码分析

定位COfflineActiveDlg控件事件

image-20240421151153685

ok_440920

int __thiscall ok_440920(COfflineActiveDlg *this, int a2, int a3, int a4)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]License_Code_98 = (char *)this->License_Code_98;v30 = a2;v29 = a4;sub_408680(License_Code_98, (int)&License_Code);v34 = 0;sub_408680((char *)this->Machine_Code_A0, (int)Machine_Code);LOBYTE(v34) = 1;sub_408680((char *)this->FXTextField_Activation_Code_A8, (int)&Activation_Code);LOBYTE(v34) = 2;memset(ws_License_Code, 0, sizeof(ws_License_Code));memset(ws_Activation_Code, 0, 0x100);v6 = fxstring_580929((void **)&License_Code);fxstring_5805EF((void **)&License_Code, v6);if ( *((_DWORD *)License_Code + 0xFFFFFFFF) ){v10 = fxstring_580929(Machine_Code);fxstring_5805EF(Machine_Code, v10);if ( *((_DWORD *)Machine_Code[0] + 0xFFFFFFFF) ){v12 = fxstring_580929((void **)&Activation_Code);fxstring_5805EF((void **)&Activation_Code, v12);if ( *((_DWORD *)Activation_Code + 0xFFFFFFFF) ){if ( License_Code&& &v24 != (int *)0xFFFFFFCC&& MultiByteToWideChar(0xFDE9u, 0, License_Code, 0xFFFFFFFF, ws_License_Code, 0x80) > 0 ){if ( tows_43F490(Activation_Code, ws_Activation_Code) > 0 ){++this->field_B4;unknowclass_4500E0 = get_unknowclass_4500E0();if ( (unline_check_450320(ws_License_Code, ws_Activation_Code, unknowclass_4500E0) & 0xFFF) == 0 ){v19 = sub_585C8E((CUpgradeDlg *)this, a2, a3, v29);goto LABEL_23;}v17 = GetLastError() + 0x11A01F700000000i64;// "Activation code is incorrect."v7 = HIDWORD(v17);v8 = v17;v23 = v17;v22 = 0x11B;}else{v15 = GetLastError() + 0x111000E00000000i64;// "The specified string is invalid."v7 = HIDWORD(v15);v8 = v15;v23 = v15;v22 = 0x112;}}else{v14 = GetLastError() + 0x10A000E00000000i64;v7 = HIDWORD(v14);v8 = v14;v23 = v14;v22 = 0x10B;}}else{v13 = GetLastError() + 0x103000D00000000i64;// "The specified string is an empty string."v7 = HIDWORD(v13);v8 = v13;v23 = v13;v22 = 0x104;}}else{v11 = GetLastError() + 0xFC000D00000000i64;v7 = HIDWORD(v11);v8 = v11;v23 = v11;v22 = 0xFD;}}else{v9 = GetLastError() + 0xF5000D00000000i64;v7 = HIDWORD(v9);v8 = v9;v23 = v9;v22 = 0xF6;}v28 = v7;log_450470((int)L"%S %d nRet=0x%016llX\n", ".\\OfflineActiveDlg.cpp", v22, v23);v31 = 0;v18 = (unsigned __int16)(((unsigned __int64)GetLastError() + 0x1F700000000i64) >> 0x20);if ( v31 || v18 != (unsigned __int16)v7 ){if ( (unsigned __int16)v28 | v31 )error_402CA0(this, this->FXApp_90, v8, v7, 0);goto LABEL_21;}error_402CA0(this, this->FXApp_90, v8, v7, 0);if ( this->field_B4 < 3u ){
LABEL_21:LOBYTE(v34) = 1;FX::FXString::~FXString((void **)&Activation_Code);LOBYTE(v34) = 0;FX::FXString::~FXString(Machine_Code);v34 = 0xFFFFFFFF;FX::FXString::~FXString((void **)&License_Code);return 1;}v19 = sub_585CAD(this, v30, a3, v29);LABEL_23:v21 = v19;LOBYTE(v34) = 1;FX::FXString::~FXString((void **)&Activation_Code);LOBYTE(v34) = 0;FX::FXString::~FXString(Machine_Code);v34 = 0xFFFFFFFF;FX::FXString::~FXString((void **)&License_Code);return v21;
}

unline_check_450320

// ws_License_Code, ws_Activation_Code
int __usercall unline_check_450320@<eax>(wchar_t *ws_License_Code@<edx>,         // 注册码wchar_t *ws_Activation_Code@<ecx>,      // 激活码UnknowClass *a3@<esi>)
{int result; // eaxint v5; // ediresult = 0x7601001;if ( !a3->CActiveOnline_obj_8FDCF4 || !ws_License_Code || !ws_Activation_Code )return result;result = a3->CActiveOnline_obj_8FDCF4->vftable_0->Init_490DD0(// CActiveOnline_vft+0xc(int)a3->CActiveOnline_obj_8FDCF4,L"EasyUEFI",ws_License_Code,1);if ( (result & 0xFFF) != 0 )return result;v5 = a3->CActiveOnline_obj_8FDCF4->vftable_0->sub_491730((_DWORD *)a3->CActiveOnline_obj_8FDCF4,ws_Activation_Code,wcslen(ws_Activation_Code));a3->CActiveOnline_obj_8FDCF4->vftable_0->sub_490EE0((_DWORD *)a3->CActiveOnline_obj_8FDCF4);return v5;
}

Init_490DD0

int __thiscall Init_490DD0(CActiveOnline *this, const wchar_t *productname, const wchar_t *ws_License_Code, int a4)
{int v5; // esiconst wchar_t *v6; // eaxDWORD LastError; // eaxif ( this->dword8 ){v5 = 0x3901004;}else{v6 = productname;if ( productname ){while ( *v6++ );if ( v6 - (productname + 1) ){if ( ws_License_Code ){if ( wcslen(ws_License_Code) >= 48 ){this->gapC = a4;sub_490D20(this);v5 = transform_498770(&this->vec_char_Activation_Code_table_50);if ( (v5 & 0xFFF) == 0 ){std::wstring::operator+=((std::wstring *)&this->productname_E8, productname);std::wstring::operator+=((std::wstring *)&this->ws_License_Code_104, ws_License_Code);remove_bar_4994B0((std::wstring *)&this->ws_License_Code_104);this->dword8 = 1;}}else{v5 = 0x3D01002;}}else{v5 = 0x3C01002;}}else{v5 = 0x3B01002;}}else{v5 = 0x3A01002;}}if ( (v5 & 0xFFF) != 0 ){LastError = GetLastError();flog_496C40(L"[A] Init failed! uReturn = %x SysErr = %d", v5, LastError);}else{flog_496C40(L"[A] Init success.");}return v5;
}

校验激活码sub_491730

1、激活码根据字母表进行替换

2、根据‘|’进行分隔成4部分

3、

第1部分hex字符串为“8000”或“8001"

第2部分为license_md5[8:8+8]

第3部分为machine_code_md5[8:8+8]

第4部分为machine_code机器码

// local variable allocation has failed, the output may be wrong!
CActiveOnline *__thiscall sub_491730(CActiveOnline *this, void *Activation_Code, int Activation_Code_size)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v27 = this;tf_active_code._Myres = 7;tf_active_code._Mysize = 0;tf_active_code.u._Buf[0] = 0;v61 = 6;part1._Myres = 7;part1._Mysize = 0;part1.u._Buf[0] = 0;part2._Myres = 7;part2._Mysize = 0;part2.u._Buf[0] = 0;part3._Myres = 7;part3._Mysize = 0;part3.u._Buf[0] = 0;part4._Myres = 7;part4._Mysize = 0;part4.u._Buf[0] = 0;memset(plicense, 0, sizeof(plicense));v45 = 0;*(_DWORD *)v46 = 0;v47 = 0;v53 = 0;*(_DWORD *)_Ptr = 0;v55 = 0;v56 = 0;*(_DWORD *)v57 = 0;v58 = 0;v59 = 0;v49 = 0;*(_DWORD *)v50 = 0;v51 = 0;p2 = 0;pmachine_code = 0;p3 = 0;v42 = 0xF;v41 = 0;LOBYTE(v40) = 0;v37 = 0xF;v36 = 0;LOBYTE(v35) = 0;v28 = operator new(1u);LOBYTE(v61) = 7;if ( this->dword8 ){if ( Activation_Code ){if ( Activation_Code_size ){wstring_43D4C0(&tf_active_code, Activation_Code, wcslen((const unsigned __int16 *)Activation_Code));//激活码根据字母表进行替换v26 = (CActiveOnline *)vec_498A40(&this->vec_char_Activation_Code_table_50,(int)&tf_active_code,(int)&tf_active_code);if ( ((unsigned __int16)v26 & 0xFFF) == 0 ){p_part3 = &part3;v26 = (CActiveOnline *)&v24;std::wstring::wstring((std_wstring_d *)&v24, (const std::wstring *)&tf_active_code);//根据‘|’进行分隔成4部分v26 = (CActiveOnline *)split_492500(&part4, &part2, &part1, (std_wstring_d)v24, p_part3);if ( ((unsigned __int16)v26 & 0xFFF) == 0 ){BUF = (union std_wstring_union *)part1.u._Ptr;if ( part1._Myres < 8 )BUF = &part1.u;//第一部分hex字符串为8000h或8001hv5 = wcstol(BUF->_Buf, 0, 0x10) - 0x8000;if ( v5 > 17 )v26 = (CActiveOnline *)0x2E401001;elsev26 = (CActiveOnline *)sub_4926A0(v5);//    case 0:case 1: result = 0;if ( ((unsigned __int16)v26 & 0xFFF) == 0 ){v6 = v27;p_wstring_debug_machine_code_120 = &v27->wstring_debug_machine_code_120;//第4部分为机器码if ( compare_495110(&v27->wstring_debug_machine_code_120, &part4) ){if ( part2._Mysize == 8 || part3._Mysize == 8 ){Ptr = (union std_wstring_union *)part2.u._Ptr;if ( part2._Myres < 8 )Ptr = &part2.u;WideCharToMultiByte(0, 0, Ptr->_Buf, 0xFFFFFFFF, &p2, 0xA, 0, 0);p_u = (union std_wstring_union *)part3.u._Ptr;if ( part3._Myres < 8 )p_u = &part3.u;WideCharToMultiByte(0, 0, p_u->_Buf, 0xFFFFFFFF, &p3, 0xA, 0, 0);if ( v6->ws_License_Code_104._Myres < 8 )v10 = v6->ws_License_Code_104.u._Buf;elsev10 = v6->ws_License_Code_104.u._Ptr;WideCharToMultiByte(0, 0, v10, 0xFFFFFFFF, plicense, 0x40, 0, 0);if ( p_wstring_debug_machine_code_120->_Myres < 8 )v11 = p_wstring_debug_machine_code_120->u._Buf;elsev11 = p_wstring_debug_machine_code_120->u._Ptr;WideCharToMultiByte(0, 0, v11, 0xFFFFFFFF, &pmachine_code, 0x18, 0, 0);temp_str = (int)&v24.u._Ptr;std::string::string((std::string *)&v24.u, plicense);v12 = (const std::string *)md5_4986F0(&twstr, *(std_string_d *)v24.u._Buf);LOBYTE(v61) = 8;std::string::assign((std::string *)lic_md5, v12, 0, 0xFFFFFFFF);LOBYTE(v61) = 7;std::string::~string((int)&twstr);temp_str = (int)&v24.u._Ptr;std::string::string((std::string *)&v24.u, &pmachine_code);v13 = (const std::string *)md5_4986F0(&twstr, *(std_string_d *)v24.u._Buf);LOBYTE(v61) = 9;std::string::assign((std::string *)v34, v13, 0, 0xFFFFFFFF);LOBYTE(v61) = 7;std::string::~string((int)&twstr);v14 = (std_wstring_d *)std::string::substr((std::basic_string<char,std::char_traits<char>,glitch::core::SAllocator<char,0> > *)lic_md5,(std::basic_string<char,std::char_traits<char>,glitch::core::SAllocator<char,0> > *)&twstr,8u,8u);if ( v14->_Myres < 0x10 )v15 = &v14->u;elsev15 = (union std_wstring_union *)v14->u._Ptr;v16 = strcmp((const char *)v15, &p2);// 第2部分为license_md5[8:8+8]std::string::~string((int)&twstr);if ( v16 ){v26 = (CActiveOnline *)0x14B01003;}else{v20 = (std_wstring_d *)std::string::substr((std::basic_string<char,std::char_traits<char>,glitch::core::SAllocator<char,0> > *)v34,(std::basic_string<char,std::char_traits<char>,glitch::core::SAllocator<char,0> > *)&twstr,8u,8u);if ( v20->_Myres < 0x10 )v21 = &v20->u;elsev21 = (union std_wstring_union *)v20->u._Ptr;v22 = strcmp((const char *)v21, &p3);// 第3部分为machine_code_md5[8:8+8]std::string::~string((int)&twstr);if ( v22 )v26 = (CActiveOnline *)0x14C01003;}}else{v26 = (CActiveOnline *)0x14401003;}}else{v26 = (CActiveOnline *)0x1420100B;}}}}}else{v26 = (CActiveOnline *)0x12801002;}}else{v26 = (CActiveOnline *)0x12701002;}}else{v26 = (CActiveOnline *)0x12501004;}sub_48F3B0((CActiveOnline *)&v27->wstring_www_com_6C);v17 = v26;v18 = (union std_wstring_union *)part1.u._Ptr;if ( ((unsigned __int16)v26 & 0xFFF) != 0 ){if ( part1._Myres < 8 )v18 = &part1.u;p_part3 = (std_wstring_d *)v18;LastError = GetLastError();flog_496C40(L"[A] AutoActive failed! uReturn = %x SysErr = %d wsStatus = %s", v17, LastError);}else{if ( part1._Myres < 8 )v18 = &part1.u;flog_496C40(L"[A] AutoActive success. wsStatus = %s", v18);}operator delete(v28);if ( v37 >= 0x10 )operator delete(v35);v37 = 0xF;v36 = 0;LOBYTE(v35) = 0;if ( v42 >= 0x10 )operator delete(v40);v42 = 0xF;v41 = 0;LOBYTE(v40) = 0;if ( part4._Myres >= 8 )operator delete(part4.u._Ptr);part4._Myres = 7;part4._Mysize = 0;part4.u._Buf[0] = 0;if ( part3._Myres >= 8 )operator delete(part3.u._Ptr);part3._Myres = 7;part3._Mysize = 0;part3.u._Buf[0] = 0;if ( part2._Myres >= 8 )operator delete(part2.u._Ptr);part2._Myres = 7;part2._Mysize = 0;part2.u._Buf[0] = 0;if ( part1._Myres >= 8 )operator delete(part1.u._Ptr);part1._Myres = 7;part1._Mysize = 0;part1.u._Buf[0] = 0;if ( tf_active_code._Myres >= 8 )operator delete(tf_active_code.u._Ptr);return v26;
}

py

'''
pip install pycryptodome
'''
import base64
import ctypes
import io
import os
import random
from typing import Union
from Crypto.PublicKey import RSA
from Crypto.Util.number import inverseimport hashlib
import time
from datetime import datetimedef convert_to_time64(time_str):# 解析时间字符串为 datetime 对象dt_obj = datetime.strptime(time_str, r"%Y-%m-%d %H:%M:%S")# 将 datetime 对象转换为时间戳timestamp = dt_obj.timestamp()# # 将时间戳转换为 _time64 格式# time64 = int(timestamp * 1e7)  # 1e7 是将秒转换为 100 纳秒的单位time64 = int(timestamp)return time64def convert_to_time_string(time64):# 将 _time64 格式的时间戳转换为秒数# timestamp = time64 / 1e7  # 将 100 纳秒转换为秒# 使用 fromtimestamp 将秒数转换为 datetime 对象dt_obj = datetime.fromtimestamp(time64)# 使用 strftime 方法将 datetime 对象格式化为时间字符串time_str = dt_obj.strftime("%Y-%m-%d %H:%M:%S")return time_strpubk = "-----BEGIN RSA PUBLIC KEY-----\n"\"MCYCHwC9s2qhNcaeKtlin3VtwnU9Vv4x/j0wBPS43F/8eKMCAwEAAQ==\n"\"-----END RSA PUBLIC KEY-----\n"def rsa_pk_enc(data: bytes) -> bytes:# http://factordb.com/index.php?query=1309267119417726280330942057320079958095363483536018220587938405183944867# e=65537p = 1138829745998159918316484590691394789q = 1149660099780921729474053823339894503n = p*q# phi = (p - 1) * (q - 1)# d = inverse(e, phi)# print(d)d = 461760535243012729352417637561931856791126802617053449862506727428818545t = int.from_bytes(data, 'big')x = pow(t, d, n)bs = i2bs(x)# print(x)# print(bs,bs.hex())return bs# from rsa import PublicKey, common, transform, core
# def rsa_pubkey_dec(cipher:bytes, PUBLIC_KEY:bytes=pubk.encode()):
#         public_key = PublicKey.load_pkcs1(PUBLIC_KEY)
#         encrypted = transform.bytes2int(cipher)
#         print('e:',public_key.e)
#         print('n:',public_key.n)
#         decrypted = core.decrypt_int(encrypted, public_key.e, public_key.n)
#         print('rsa_pubkey_dec result:',decrypted)
#         text = transform.int2bytes(decrypted)
#         return texttable = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,0x6B, 0x79, 0x6E, 0x6A, 0x41, 0x34, 0x45, 0x48, 0x78, 0x36, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,0x40, 0x63, 0x4E, 0x57, 0x32, 0x7A, 0x6C, 0x53, 0x58, 0x4C, 0x59, 0x30, 0x64, 0x75, 0x77, 0x44,0x6F, 0x51, 0x70, 0x56, 0x46, 0x7C, 0x61, 0x37, 0x38, 0x5A, 0x62, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,0x60, 0x39, 0x67, 0x65, 0x43, 0x74, 0x69, 0x73, 0x50, 0x6D, 0x68, 0x72, 0x66, 0x4F, 0x31, 0x33,0x55, 0x4B, 0x42, 0x35, 0x4D, 0x49, 0x54, 0x76, 0x71, 0x47, 0x4A, 0x7B, 0x52, 0x7D, 0x7E, 0x7F]def s_transform(s: str):ret = ''for x in s:ret += chr(table[ord(x)])return retdef re_transfrom(s: str):ret = ''for x in s:ret += chr(table.index(ord(x)))return retdef i2bs(m: int, byteorder='big'):hex_m = m.to_bytes((m.bit_length() + 7) // 8, byteorder=byteorder)return hex_mdef rsa_pub_dec(decoded_data: bytes, PUBLIC_KEY: bytes = pubk.encode()) -> bytes:public_key = RSA.import_key(PUBLIC_KEY)# 获取模数和公钥指数n = public_key.ne = public_key.e# 打印结果print("Modulus (n):", n)# bs_n=n.to_bytes(128,'big')# print(bs_n,bs_n.hex())print("Exponent (e):", e)c = int.from_bytes(decoded_data, 'big')m = pow(c, e, n)print('pow:', m)hex_m = i2bs(m)return hex_mclass CustomBase32Codec:def __init__(self, custom_alphabet='ABCDEFGHJKLMNPQRSTUVWXYZ23456789'):if len(custom_alphabet) != 32:raise ValueError("Custom alphabet must contain 32 characters.")# Standard Base32 alphabetstandard_alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'# Create translation tablesself.encode_trans = bytes.maketrans(standard_alphabet, custom_alphabet.encode())self.decode_trans = bytes.maketrans(custom_alphabet.encode(), standard_alphabet)def encode(self, data):if isinstance(data, str):data = data.encode('utf-8')# Use the standard base64 library to encode and then translate to custom alphabetencoded = base64.b32encode(data)return encoded.translate(self.encode_trans)def decode(self, data):if isinstance(data, str):data = data.encode('utf-8')# Translate from custom alphabet to standard and then decode using standard base64 librarystandard_encoded = data.translate(self.decode_trans)return base64.b32decode(standard_encoded)def reflect_data(x, width):# See: https://stackoverflow.com/a/20918545if width == 8:x = ((x & 0x55) << 1) | ((x & 0xAA) >> 1)x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2)x = ((x & 0x0F) << 4) | ((x & 0xF0) >> 4)elif width == 16:x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1)x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2)x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4)x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)elif width == 32:x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1)x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2)x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4)x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8)x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16)else:raise ValueError('Unsupported width')return xdef crc_poly(data, n, poly, crc=0, ref_in=False, ref_out=False, xor_out=0):g = 1 << n | poly  # Generator polynomial# Loop over the datafor d in data:# Reverse the input byte if the flag is trueif ref_in:d = reflect_data(d, 8)# XOR the top byte in the CRC with the input bytecrc ^= d << (n - 8)# Loop over all the bits in the bytefor _ in range(8):# Start by shifting the CRC, so we can check for the top bitcrc <<= 1# XOR the CRC if the top bit is 1if crc & (1 << n):crc ^= g# Reverse the output if the flag is trueif ref_out:crc = reflect_data(crc, n)# Return the CRC valuereturn crc ^ xor_outdef CRC8_MAXIM(data: bytes):crc8 = crc_poly(data, n=8, poly=0x31, ref_in=True, ref_out=True, xor_out=0)return crc8def convert_bytes_to_structure(st: object, byte: bytes):assert ctypes.sizeof(st) == len(byte), 'size error! need:%d,give:%d' % (ctypes.sizeof(st), len(byte))# ctypes.memmove(ctypes.pointer(st), byte, ctypes.sizeof(st))ctypes.memmove(ctypes.addressof(st), byte, ctypes.sizeof(st))class TYPE_BASE(ctypes.LittleEndianStructure):_pack_: int = 1def __init__(self, data: Union[bytes, list, tuple, set]) -> None:if isinstance(data, bytes):convert_bytes_to_structure(self, data)elif isinstance(data, (list, tuple, set)):convert_bytes_to_structure(self, bytes(data))elif isinstance(data, io.IOBase):data.readinto(self)'''
struct LicenseInfo{char var0;char var1;char major_version2;char var3;int expiration4;char var8;char unknow9[7];char var10;char var11;char unknow12[11];char crc1d;};
'''class LicenseInfo(TYPE_BASE):# _pack_: int = 1_fields_: list = [("var0", ctypes.c_ubyte),("var1", ctypes.c_ubyte),("major_version2", ctypes.c_ubyte),("var3", ctypes.c_ubyte),("expiration4", ctypes.c_uint32),("var8", ctypes.c_ubyte),("unknow9", ctypes.c_byte*7),("var10", ctypes.c_ubyte),("var11", ctypes.c_ubyte),("unknow12", ctypes.c_byte*11),("crc1d", ctypes.c_ubyte),]def __init__(self, data: Union[bytes, list, tuple, set]) -> None:super().__init__(data)self.get_var()def get_var(self):if (self.var8 & 0xf) != 0:if (self.var8 & 0xf) == 1 or (self.var8 & 0xf) == 2:self.ver2 = self.var0self.ver1 = self.var10else:self.ver2 = self.var0 & 0x1fself.ver1 = self.var0 >> 5def __str__(self) -> str:info = ''info += 'ver1:%02x\n' % self.ver1info += 'ver2:%02x\n' % self.ver2info += 'major_version2:%02x\n' % self.major_version2info += 'var3:%02x\n' % self.var3info += 'expiration4:%s\n' % convert_to_time_string(self.expiration4)info += 'var8:%02x\n' % self.var8info += 'unknow9:%s\n' % bytes(self.unknow9)info += 'var10:%02x\n' % self.var10info += 'var11:%02x\n' % self.var11info += 'unknow12:%s\n' % bytes(self.unknow12)info += 'crc1d:%02x\n' % self.crc1dreturn infodef parse_license(data: bytes):custom_b32 = CustomBase32Codec()decoded_data = custom_b32.decode(data)print("Custom Base32 Decoded:", decoded_data)print('hex:', decoded_data.hex())# enc=custom_b32.encode(b'SUPPORT@HASLEO.COM')# print('enc:',enc)# text=rsa_pubkey_dec(decoded_data)text = rsa_pub_dec(decoded_data)print('rsa_pubkey_dec:', text)print('rsa_pubkey_dec hex:', text.hex())enc = rsa_pk_enc(text)print('test enc:', enc, enc.hex())rsa_dec = text[:-1]+b'\x00'# CRC-8/MAXIMcrc8 = CRC8_MAXIM(rsa_dec)print('crc8/MAXIM :', crc8, hex(crc8))obj = LicenseInfo(text)print(str(obj))def GenActivationCode(license, machine_code) -> str:lic_md5 = hashlib.md5(license).hexdigest()# print('lic_md5:',lic_md5)mc_md5 = hashlib.md5(machine_code).hexdigest()# print('mc_md5:',mc_md5)s = '8000|%s|%s|%s' % (lic_md5[8:16], mc_md5[8:16], machine_code.decode())# print(s)re_s = re_transfrom(s)# print(re_s)return re_sdef GenLicense() -> bytes:lic = b''ver2 = 1ver1 = 1  # random.randint(1,4)lic += (ver2 | (ver1 << 5)).to_bytes(1, 'little')  # this way var8  must 0lic += b'\x01'  # var1lic += b'\xff'  # major_version2lic += b'\x00'  # var3expiration4 = convert_to_time64('2077-01-01 12:00:00')t = convert_to_time_string(expiration4)# print(t)lic += expiration4.to_bytes(4, 'little')var8 = b'\x00'lic += var8lic += os.urandom(7)  # unknow9[7]lic += b'\x00'  # var10lic += b'\xff'  # var11  monthlic += os.urandom(11)  # unknow12[11]crc8 = CRC8_MAXIM(lic+b'\x00')lic += crc8.to_bytes(1, 'little')# print('lic:',lic,lic.hex())# print(str(LicenseInfo(lic)))enc = rsa_pk_enc(lic)license = CustomBase32Codec().encode(enc)return licenseif __name__ == "__main__":license = GenLicense()print('License:', license.decode())print('Please input MachineCode:')mc = input().encode()ac = GenActivationCode(license, mc)print('ActivationCode', ac)

image-20240421153019573

image-20240421153045919

activate.log 日志中显示激活成功

image-20240421153142570

image-20240421152912426

ps

网络检验

int __userpurge do_net_check_4502D0@<eax>(int license@<edx>, UnknowClass *a2@<esi>, int a3)
{int result; // eaxint v4; // ediresult = 0x5401001;if ( !a2->CActiveOnline_obj_8FDCF4 || !license )return result;result = a2->CActiveOnline_obj_8FDCF4->vftable_0->Init_490DD0((int)a2->CActiveOnline_obj_8FDCF4,L"EasyUEFI",(const wchar_t *)license,1);if ( (result & 0xFFF) != 0 )return result;// net_check_490F80v4 = a2->CActiveOnline_obj_8FDCF4->vftable_0->sub_490F80((int)a2->CActiveOnline_obj_8FDCF4, a3);a2->CActiveOnline_obj_8FDCF4->vftable_0->sub_490EE0((_DWORD *)a2->CActiveOnline_obj_8FDCF4);return v4;
}

main中还用一个DistributeLicense,不跟了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/28413125.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

springboot启动原理

启动类上的注解,会扫描路径下的类进容器进行实例化。这样访问时springmvc的dispa就可以访问到这个类了。 new DispatcherServlet(webapplication) springmvc需要一个web容器。这个容器参数,在startTomcat(applicationContext)方法里面传入。

第一次Blog

前言 第一次题目集是对类的设计,类与对象的使用和类与数组关联类的考察。第二次题目集是类与对象之间的创建以及运用的考察。第三次题目集是对类的封装性以及Java自带时间包的运用的考察。总而言之,三次题目集的题目量并不算大,题目集的难度也是比较中等。设计与分析这是答题…

记录Windows failed fast startup with error status 0xC00000D4.

1、电脑经常性卡死,查看event viewer 发现启动时一些error 不知道啥原因 看到https://answers.microsoft.com/en-us/windows/forum/windows8_1-performance/faststartup-issues-kernel-power-boot-and/69cc4b65-f847-4f4b-a0a0-b73f469a1ddf 这里说删除%windir%/prefetch文件夹…

通用数据湖仓一体架构正当时

这篇博文中提出的建议并不新鲜。事实上许多组织已经投入了数年时间和昂贵的数据工程团队的工作,以慢慢构建这种架构的某个版本。我知道这一点,因为我以前在Uber和LinkedIn做过这样的工程师。我还与数百个组织合作,在开源社区中构建它并朝着类似的目标迈进。 早在 2011 年 Li…

[转帖]Oracle 败了、谷歌赢了:Java API 版权案最终裁决

https://zhuanlan.zhihu.com/p/362496136 周一,最高法院在Oracle围绕移动操作系统Android中所用软件的一起旷日持久的版权诉讼中判谷歌胜诉。 法院的判决为6比2。大法官Amy Coney Barrett没有参与此案。 该案涉及谷歌用于构建Android的12000行代码,这些代码是从Sun Microsyst…

Java面试题:请谈谈对ThreadLocal的理解?

ThreadLocal是一种特殊的变量存储机制,它提供了一种方式,可以在每个线程中保存数据,而不会受到其他线程的影响。这种机制在多线程编程中非常有用,因为它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰,以空间换时间。 在Java中,ThreadLocal的实现主…