010Editor漏洞分析
Windows
此应用程序未加密,可以直接使用idapro或x64dbg进行调试。可以以一些常量字符串作为标志位,检查相关字符串引用的位置,并添加断点进行调试。经过一些调试可以找到下面的代码,这些代码是通过idapro反汇编出来的。
其中第一个if的位置调用了一个函数,这个函数其实就是检查授权的代码位置。
__int64 __fastcall sub_14036EDC0(__int64 a1, unsigned int a2) { int v5; // eax int v6; // eax int v7; // eax unsigned int v8; // ecx int v9; // eax unsigned int v10; // ecx int v11; // eax unsigned int v12; // ecx if ( *(_DWORD *)(a1 + 60) ) // make this function always return 219 (0xdb) return 275i64; v5 = sub_1400060D2(); switch ( v5 ) { case 45: return 219i64; // single license case 78: v11 = sub_1400091F1(a1, a2); v12 = 524; if ( v11 != 23 ) return 237; return v12; case 231: return 375i64; default: v6 = sub_1400091F1(a1, a2); if ( v6 == 23 ) return 113i64; if ( v6 != 42 ) { if ( v6 == 312 ) { v7 = sub_140005AB5(a1); v8 = 47; if ( v7 == 419 ) return 249; return v8; } return 375i64; } v9 = sub_140005AB5(a1); v10 = 375; if ( v9 == 419 ) return 249; return v10; } }
再结合下面这个代码:
void *__fastcall sub_14036F180(__int64 a1, void *a2, int a3, int *a4, int a5, int a6) { const char *v10; // rdx __int64 v11; // rdx int v12; // eax bool v13; // cf const struct QString *v14; // rax const struct QString *v15; // rbx const struct QString *v16; // rax int v17; // eax __int64 v18; // rdx const struct QString *v19; // rax const struct QString *v20; // rbx const struct QString *v21; // rax const char *v22; // rdx int v23; // r14d const struct QString *v24; // rax const struct QString *v25; // rbx const struct QString *v26; // rax char v28[8]; // [rsp+28h] [rbp-18h] BYREF char v29[8]; // [rsp+30h] [rbp-10h] BYREF char v30[8]; // [rsp+38h] [rbp-8h] BYREF QString::QString(a2); if ( a3 != 219 ) // previous function change a3 to 219, so next segment { if ( a3 == 47 ) { QString::operator=(a2, "Evaluation Version\n"); QString::operator+=(a2, "Clock Error"); v17 = 30; goto LABEL_34; } if ( a3 == 113 ) { v22 = "Evaluation Version\n"; } else { if ( a3 != 524 ) { if ( a3 == 249 ) { QString::operator=(a2, "Evaluation Version\n"); v18 = *(unsigned int *)(qword_140D64950 + 52); if ( (_DWORD)v18 == 1 ) { QString::operator+=(a2, "1 Use Left"); } else { v19 = (const struct QString *)QString::number(v29, v18, 10i64); v20 = QString::QString((QString *)v28, v19); v21 = (const struct QString *)QString::fromUtf8(v30, " Uses Left", 0xFFFFFFFFi64); QString::append((QString *)v28, v21); QString::~QString(v30); QString::append((QString *)a2, v20); QString::~QString(v28); QString::~QString(v29); } *a4 = 29; return a2; } if ( a3 == 237 ) { QString::operator=(a2, "Upgrade Required\n"); QString::operator+=(a2, "Evaluation Version Expired"); } else { QString::operator=(a2, "Evaluation Version\n"); QString::operator+=(a2, "Expired"); } v17 = 30; LABEL_34: *a4 = v17; return a2; } v22 = "Upgrade Required\n"; } QString::operator=(a2, v22); v23 = *(_DWORD *)(qword_140D64950 + 40) - *(_DWORD *)(qword_140D64950 + 36); if ( v23 == 1 ) { QString::operator+=(a2, "1 Day Left"); } else { v24 = (const struct QString *)QString::number(v29, (unsigned int)v23, 10i64); v25 = QString::QString((QString *)v28, v24); v26 = (const struct QString *)QString::fromUtf8(v30, " Days Left", 0xFFFFFFFFi64); QString::append((QString *)v28, v26); QString::~QString(v30); QString::append((QString *)a2, v25); QString::~QString(v28); QString::~QString(v29); if ( v23 >= 30 ) return a2; } v17 = 30 - v23; goto LABEL_34; } if ( a5 ) QString::operator=(a2, "Licensed to:\n"); QString::QString((QString *)v28, (const struct QString *)(qword_140D64950 + 8)); QString::append((QString *)a2, (const struct QString *)v28); QString::~QString(v28); v10 = " - "; if ( !a6 ) v10 = "\n"; QString::operator+=(a2, v10); if ( *(_DWORD *)(a1 + 48) == 1 ) // change this code, make it always ++ (a2, "Single User License").... { QString::operator+=(a2, "Single User License"); *a4 = 0; } else { v11 = *(unsigned int *)(qword_140D64950 + 48); v12 = 0; if ( *(_DWORD *)(qword_140D64950 + 44) == 1 ) v13 = (unsigned int)v11 < 0x32; else v13 = (unsigned int)v11 < 0x3E8; LOBYTE(v12) = !v13; if ( v12 ) { QString::operator+=(a2, "Site License"); } else { v14 = (const struct QString *)QString::number(v30, v11, 10i64); v15 = QString::QString((QString *)v28, v14); v16 = (const struct QString *)QString::fromUtf8(v29, " User License", 0xFFFFFFFFi64); QString::append((QString *)v28, v16); QString::~QString(v29); QString::append((QString *)a2, v15); QString::~QString(v28); QString::~QString(v30); } *a4 = 0; } return a2; }
因此直接将这个函数改成总是返回0xdb(219)就可以啦。
原版安装包下载地址:
链接: https://pan.baidu.com/s/1nM1p4YhYUHXVSsYx65NX2w?pwd=g58s 提取码: g58s
MacOS
macos下可以用hopper disassembler打开。根据windows的经验,可以直接搜索这个代码:
mov eax, 113 (B8 13 01 00 00)
这个代码改成始终返回0xDB(219),这个id代表"Single User License"。
查找字符串"Single User License",可以找到有两处引用它的地方,类似:
if ( *(_DWORD *)(a1 + 48) == 1 ) { QString::operator+=(a2, "Single User License"); *a4 = 0; }
直接把这个改成if(true)。保存之后会破坏数字签名,建议直接把数字签名数据去除。
mac原版下载:
链接: https://pan.baidu.com/s/14UidVR4hoMGGy3Wv_XlGiQ?pwd=b126 提取码: b126