ida 9.0.24.807 许可校验
ida 9.0.24.807 ida64.dll 许可校验
搜索license可以找到大量信息
并且有几个license相关的导出函数

跟踪get_license_manager
定位许可校验函数
license_manager虚表信息
.rdata:00000001003CC298 license_manager_vft dq offset vtbl_license_manager_vft_func_0
.rdata:00000001003CC298 ; DATA XREF: vtbl_license_manager_vft_func_0+19↑o
.rdata:00000001003CC298 ; new_license_manager+2E↑o
.rdata:00000001003CC2A0 dq offset vtbl_license_manager_vft_func_1
.rdata:00000001003CC2A8 dq offset vtbl_license_manager_vft_func_2
.rdata:00000001003CC2B0 dq offset vtbl_license_manager_vft_func_3
.rdata:00000001003CC2B8 dq offset vtbl_license_manager_vft_func_4
.rdata:00000001003CC2C0 dq offset vtbl_license_manager_vft_func_5
.rdata:00000001003CC2C8 dq offset vtbl_license_manager_vft_func_6
.rdata:00000001003CC2D0 dq offset vtbl_license_manager_vft_func_7
.rdata:00000001003CC2D8 dq offset vtbl_license_manager_vft_func_8
.rdata:00000001003CC2E0 dq offset vtbl_license_manager_vft_func_9
.rdata:00000001003CC2E8 dq offset vtbl_license_manager_vft_func_10
.rdata:00000001003CC2F0 dq offset vtbl_license_manager_vft_func_11
.rdata:00000001003CC2F8 dq offset vtbl_license_manager_vft_func_12
在get_license_manager 函数中发现license校验函数
// 读取 keyfile 并进行验证
if ( ((unsigned int (__fastcall *)(LicenseManager *, char *, int *))license_manager_obj_100451FD8->vft_0->vtbl_license_manager_vft_func_3)(
license_manager_obj_100451FD8,
v2,
&v45) )
{
if ( v40 )
v4 = (const char *)v39;
debug_100022C40("Could not acquire license: %s\n", v4);
}
vtbl_license_manager_vft_func_3_3415C0
v52 = check_license_file_100344500(
(char **)&obj->field_70,
(__int64)&obj->field_88,
(__int64)&obj->field_148,
hexlic_fpath,
a4,
a5);
if ( !v52 && (a4 & 0x10) != 0 )
{
qmutex_198 = 0i64;
v74 = 0i64;
v75 = 0i64;
if ( !((unsigned __int8 (__fastcall *)(LicenseManager *, void **, _QWORD, _QWORD))obj->vft_0->vtbl_license_manager_vft_func_6)(
obj,
&qmutex_198,
*(unsigned int *)(a3 + 8),
0i64) )
{
if ( v54 )
local_file = (const char *)v53;
q_sprintf_100003F80(
a5,
"Failed to list licenses for product %s in the local file \"%s\".",
product_1004505B0[*(int *)(a3 + 8)],
local_file);
v43 = (char *)qmutex_198;
check_license_file_100344500
__int64 __fastcall check_license_file_100344500(char **a1, __int64 a2, __int64 a3, const char *a4, int a5, __int64 a6)
{
unsigned int v10; // ebx
void *v11; // r9
__int64 v12; // r8
__int64 v13; // rdx
void *lictext; // [rsp+30h] [rbp-28h] BYREF
__int64 v16; // [rsp+38h] [rbp-20h]
__int64 v17; // [rsp+40h] [rbp-18h]
lictext = 0i64;
v16 = 0i64;
v17 = 0i64;
if ( load_file_100344970(&lictext, a4, a6) )//读取许可
{
v10 = check_100342660(a1, a2, (__int64)&lictext, a5, a6);//校验
if ( a3 )
{
v11 = *(void **)a3;
v12 = *(_QWORD *)(a3 + 8);
v13 = *(_QWORD *)(a3 + 0x10);
*(_QWORD *)a3 = lictext;
*(_QWORD *)(a3 + 8) = v16;
*(_QWORD *)(a3 + 0x10) = v17;
lictext = v11;
v16 = v12;
v17 = v13;
}
if ( v10 && *(_QWORD *)(a6 + 8) <= 1ui64 )
q_sprintf_100003F80(a6, "The file \"%s\" doesn't appear to be a valid license file", a4);
}
else
{
v10 = 2;
}
qfree(lictext);
return v10;
}
check_100342660
__int64 __fastcall check_100342660(char **a1, __int64 a2, __int64 lictext, char a4, __int64 a5)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
Block = 0i64;
v13 = 0i64;
v14 = 0i64;
if ( (unsigned __int8)parse_and_check_1003438C0((__int64 *)&Block, lictext, a4, (void **)a5) )
v7 = check_json_field_100343DC0(a1, a2, (__int64 *)&Block, 0, (void **)a5);
else
v7 = 2;
v8 = Block;
if ( !Block )
return v7;
v9 = v13;
if ( v13 )
{
v10 = (void **)Block;
do
{
jvalue_t_clear(v10 + 3);
qfree(*v10);
v10 += 5;
--v9;
}
while ( v9 );
}
qfree(v8);
return v7;
}
parse_and_check_1003438C0
__int64 __fastcall parse_and_check_1003438C0(__int64 *a1, __int64 a2, char lictext, void **a4)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v7 = 0i64;
v18 = 0;
v19 = 0i64;
v8 = *(_QWORD *)(a2 + 8);
v9 = *(const void **)a2;
Block = 0i64;
v10 = 0i64;
v21 = 0i64;
v22 = 0i64;
if ( v8 )
{
if ( v8 != 0xFFFFFFFFFFFFFFFFui64 )
{
v7 = qvector_reserve((__int64)&Block, 0i64, v8 + 1, 1ui64);
Block = v7;
}
v21 = v8 + 1;
memmove(v7, v9, v8);
*((_BYTE *)Block + v8) = 0;
v10 = v21;
v7 = Block;
}
v11 = &Src;
if ( v10 )
v11 = (const char *)v7;
if ( (unsigned int)parse_json_string((__int64)&v18, (__int64)v11)
|| v18 != 3
|| (unsigned int)check_signature_100343A20(v19, lictext, a4) )
{
v16 = 0;
}
else
{
if ( a1 )
{
if ( v18 != 3 )
{
if ( under_debugger )
__debugbreak();
interr(0x502i64);
}
v12 = *a1;
v13 = a1[1];
v14 = a1[2];
v15 = v19;
*a1 = *v19;
a1[1] = v15[1];
a1[2] = v15[2];
*v15 = v12;
v15[1] = v13;
v15[2] = v14;
}
v16 = 1;
}
qfree(Block);
jvalue_t_clear(&v18);
return v16;
}
signature校验==》check_signature_100343A20
__int64 __fastcall check_signature_100343A20(__int64 *lic_json, char a2, void **a3)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
if ( (a2 & 2) != 0 )
return 0i64;
v6 = 0i64;
v7 = lic_json[1];
if ( !v7 )
goto LABEL_9;
v8 = *lic_json;
v9 = *lic_json;
while ( 1 )
{
v10 = &Src;
if ( *(_QWORD *)(v9 + 8) )
v10 = *(const char **)v9;
if ( !strcmp(v10, "signature") )
break;
++v6;
v9 += 0x28i64;
if ( v6 >= v7 )
goto LABEL_9;
}
v11 = v8 + 8 * (5 * v6 + 3);
if ( *(_DWORD *)v11 != 2 || !v11 )
{
LABEL_9:
sub_100002B00(a3, "Missing \"signature\" key", 0x17ui64);
return 9i64;
}
// 计算payload json_str 的sha256
calc_json_sha256_100344600((__int64)&v39, lic_json);
signature_hex = 0i64;
data = 0i64;
v13 = 0i64;
v34 = 0i64;
v35 = 0i64;
if ( *(_DWORD *)v11 != 2 )
{
if ( under_debugger )
__debugbreak();
interr(0x657i64);
}
v14 = *(__int64 **)(v11 + 8);
v15 = v14[1];
v16 = v15 - 1;
if ( !v15 )
v16 = 0i64;
v17 = v16 >> 1;
if ( v17 )
{
data = (void *)qvector_reserve(&data, 0i64, v17, 1i64);
memset((char *)data + v34, 0, v17 - v34);
v13 = v17;
v34 = v17;
signature_hex = data;
}
else
{
v17 = 0i64;
}
v18 = *v14;
v19 = &signature_hex[v17];
if ( signature_hex != v19 )
{
do
{
v29 = 0;
if ( (unsigned int)qsscanf(v18, "%02X", &v29) != 1 )
break;
if ( v29 > 0xFF )
break;
*signature_hex = v29;
v18 += 2i64;
++signature_hex;
}
while ( signature_hex != v19 );
v13 = v34;
signature_hex = data;
}
v20 = v14[1];
v21 = *v14 + v20 - 1;
if ( !v20 )
v21 = *v14;
if ( v18 == v21 )
{
Signature_offset_20h = 0i64;
v36 = 0i64;
v37 = 0i64;
v38 = 0i64;
if ( v13 != 0x80 )
{
if ( under_debugger )
__debugbreak();
interr(0xC49i64);
}
//rsa 解密
v24 = Signature_decryption_100344E30(
signature_dec,
0xA0ui64,
signature_hex,
0x80ui64,
(__int64 *)&exponent_1003CCC30,
(char *)pub_modulus_1003CCB90);
if ( v24 >= 0 )
{
v25 = 0x40i64;
if ( (unsigned __int64)v24 <= 0x40 )
{
LABEL_32:
Block = 0i64;
v31 = 0i64;
v32 = 0i64;
Block = (_BYTE *)qvector_reserve(&Block, 0i64, 0x20i64, 1i64);
memset(&Block[v31], 0, 0x20 - v31);
v31 = 0x20i64;
v26 = Block;
// 复制signature rsa 解密后的数据 [0x20:0x40]
*(_OWORD *)Block = *(_OWORD *)&signature_dec[0x20];
v26[1] = *(_OWORD *)&signature_dec[0x30];
Signature_offset_20h = Block;
v36 = Block;
Block = 0i64;
v27 = v31;
v37 = v31;
v31 = 0i64;
v38 = v32;
v32 = 0i64;
qfree(0i64);
if ( v40 == v27 ) // 0x20
{
if ( !v40 )
{
LABEL_42:
v22 = 0;
goto LABEL_36;
}
v28 = v39;
// 与前面计算的sha256的值进行比较
while ( *v28 == v28[Signature_offset_20h - (_BYTE *)v39] )
{
if ( ++v28 - (_BYTE *)v39 >= v40 )
goto LABEL_42;
}
}
v22 = 0xA;
LABEL_36:
qfree(Signature_offset_20h);
signature_hex = data;
goto LABEL_37;
}
while ( !signature_dec[v25] )
{
if ( ++v25 >= (unsigned __int64)v24 )
goto LABEL_32;
}
v24 = 0xFFFFFFFE;
}
q_sprintf_100003F80((__int64)a3, "Signature decryption failed with code: %d", (unsigned int)v24);
v22 = 0xA;
goto LABEL_36;
}
v22 = 9;
LABEL_37:
qfree(signature_hex);
qfree(v39);
return v22;
}
许可字段校验(略)
todo
总结
简而言之,sha256+rsa
取许可中的payload,json对象序列化字符串,计算该字符串的sha256,
取许可中的signature的值,hexstr转bytes,rsa解密后取[0x20:0x40] 与上面的哈希值进行比较
e=0x13
n_bytes_le='EDFD425CF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF930000000000000000000000000000000000000000000000000000000000000000'
n=103708259528020238281968231491212855083623649579000552826541271154713103521021202133558709859463813691153402829135224007858959801854118729056356465578692294425903276554814675228955441044359462414007297799626945860003884709392298205606490444008955270902786809983042022666144385344717700223903132058765651803629
.rdata:00000001003CCB90 pub_modulus_1003CCB90 db 0EDh, 0FDh, 42h, 5Ch, 0F9h, 78h, 54h, 6Eh, 89h, 11h
.rdata:00000001003CCB90 ; DATA XREF: check_signature_100343A20+1F1↑o
.rdata:00000001003CCB90 db 22h, 58h, 84h, 43h, 6Ch, 57h, 14h, 5, 25h, 65h, 0Bh
.rdata:00000001003CCB90 db 0CFh, 6Eh, 0BFh, 0E8h, 0Eh, 0DBh, 0C5h, 0FBh, 1Dh, 0E6h
.rdata:00000001003CCB90 db 8Fh, 4Ch, 66h, 0C2h, 9Ch, 0B2h, 2Eh, 0B6h, 68h, 78h
.rdata:00000001003CCB90 db 8Ah, 0FCh, 0B0h, 0ABh, 0BBh, 71h, 80h, 44h, 58h, 4Bh
.rdata:00000001003CCB90 db 81h, 0Fh, 89h, 70h, 0CDh, 0DFh, 22h, 73h, 85h, 0F7h
.rdata:00000001003CCB90 db 2 dup(5Dh), 0DDh, 0D9h, 1Dh, 4Fh, 18h, 93h, 7Ah, 8
.rdata:00000001003CCB90 db 0AAh, 83h, 0B2h, 8Ch, 49h, 0D1h, 2Dh, 0C9h, 2Eh, 75h
.rdata:00000001003CCB90 db 5, 0BBh, 38h, 80h, 9Eh, 91h, 0BDh, 0Fh, 0BDh, 2Fh, 2Eh
.rdata:00000001003CCB90 db 6Ah, 0B1h, 0D2h, 0E3h, 3Ch, 0Ch, 55h, 0D5h, 0BDh, 0DDh
.rdata:00000001003CCB90 db 47h, 8Eh, 0E8h, 0BFh, 84h, 5Fh, 0CEh, 0F3h, 0C8h, 2Bh
.rdata:00000001003CCB90 db 9Dh, 2 dup(29h), 0ECh, 0B7h, 1Fh, 4Dh, 1Bh, 3Dh, 0B9h
.rdata:00000001003CCB90 db 6Eh, 3Ah, 8Eh, 7Ah, 0AFh, 93h, 20h dup(0)

浙公网安备 33010602011771号