sublime_text 记录
目录
- sublime_text 记录
- 1、定位注册对话框
- license_window_1400A25D2
- 定位按钮事件lambda
- 2、注册函数on_ok_clicked_license_window_1400A3F60
- check_lic_1400A19BC(to patch)
- parse_lic_1405B0E48
- verify_rsa_signature_1405B1B69
- check_lic_1400A19BC(to patch)
- 3、网络校验
- net_check_license_1400A30E3(to patch)
- 4、other
- License.sublime_license解析&签名验证脚本
- 1、定位注册对话框
sublime_text 4169 版本4.1.6.9
1、定位注册对话框
搜索"Enter License",
函数交叉引用,定位到license_window
license_window_1400A25D2
_QWORD *__fastcall license_window_1400A25D2(_QWORD *a1, __int64 a2, int a3, __int64 a4)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v42 = 0xFFFFFFFFFFFFFFFEui64;sub_140005412();*a1 = &license_window::`vftable';a1[1] = &license_window::`vftable';a1[0x4D] = a4;v40 = a1;v35 = a1 + 0x52;sub_140032268(a1 + 0x52, a2);sub_1401642B0(v40, "dialog window");v8 = operator new(0x220ui64);v34 = 0i64;button_control = v8;sub_1401861A0(v8, &v34);v9 = button_control;v40[0x4E] = button_control;v29 = &unk_14075F4E1;v30 = "";(*(void (__fastcall **)(void *))(*(_QWORD *)v9 + 0x1E8i64))(v9);button_control = operator new(0x260ui64);v10 = &v25;string_140001FD0(&v25, "https://www.sublimehq.com/store/text");if ( v27 >= 0x10 )v10 = (__int128 *)v25;v36[0] = (__int64)v10;v36[1] = (__int64)v10 + (_QWORD)v26;v11 = button_control;sub_1401861A0(button_control, v36);*v11 = &link_label_control::`vftable';v11[1] = &link_label_control::`vftable';v11[0x4B] = 0i64;str_clear_140004410(&v25);*(_QWORD *)&v25 = ___7___Func_impl_no_alloc_V_lambda_2___0___0license_window__QEAA_AEBV__function___A6AXXZ_std__PEAVtext_control_environment__PEAUlicense_info___Z_X__V_std__6B_;*((_QWORD *)&v25 + 1) = v11;v28 = &v25;sub_1400328D4(&v25, v11 + 0x44);sub_140005A2A((__int64)&v25, v12);sub_1401642B0(v11, "label_control link_label");v38 = operator new(0x2B8ui64);sub_1400A2D10(v38, 1i64);v13 = v38;sub_14018881A(v38, v40[0x4E], 0i64);sub_14018881A(v13, v11, 1i64);button_control = operator new(0x368ui64);button_control_14015314C((__int64)button_control);v14 = button_control;v40[0x51] = button_control;*(_QWORD *)v31.u._Buf = "Use License";*(_QWORD *)&v31.u._Buf[8] = "";sub_140153C02((__int64)v14, (__int128 *)v31.u._Buf);v15 = v40[0x51];*(_QWORD *)&v25 = ___7___Func_impl_no_alloc_V_lambda_3___0___0license_window__QEAA_AEBV__function___A6AXXZ_std__PEAVtext_control_environment__PEAUlicense_info___Z_X__V_std__6B_;*((_QWORD *)&v25 + 1) = v40;v28 = &v25;sub_140153214(v15, &v25);sub_140005A2A((__int64)&v25, v16);button_control = operator new(0x3B8ui64);LOBYTE(v17) = 1;sub_14047E4F4((_DWORD)button_control, a3, v17, 0, 1);v18 = button_control;v40[0x4F] = button_control;v18[0x71] = "license:input";v39 = operator new(0x318ui64);sub_1400FDEDA(v39, v18, v18 + 0x22);v40[0x50] = v39;button_control = operator new(0x1B0ui64);sub_14017BDF0(button_control, 3i64, 1i64);v19 = button_control;(*(void (__fastcall **)(void *))(*(_QWORD *)button_control + 0x1F0i64))(button_control);(*(void (__fastcall **)(_QWORD *))(*v19 + 0x1E8i64))(v19);*(_DWORD *)(v19[0x26] + 4i64) = 0x3F800000;*(_DWORD *)v19[0x29] = 0x3F800000;sub_14017BF3E((_DWORD)v19, (_DWORD)v13, 0, 0, 0);sub_14017BF3E((_DWORD)v19, v40[0x50], 1, 0, 0);sub_14017BF3E((_DWORD)v19, v40[0x51], 2, 0, 0);sub_140162720(v40, v19);*(_QWORD *)&v25 = 0i64;*((_QWORD *)&v25 + 1) = 0x200i64;v26 = &v27;v20 = v36;sub_1400A134D(v36);if ( v37 >= 0x10 )v20 = (__int64 *)v36[0];v21 = sub_140122FEA(v20, &v25, 0x40000000i64);str_clear_140004410(v36);if ( v21 ){v22 = *(_QWORD *)(*(_QWORD *)(v40[0x4F] + 0x128i64) + 0x848i64);v32 = v26;v33 = (__int64)v26 + v25;v23 = v36;sub_140385275(v36);if ( v37 >= 4 )v23 = (__int64 *)v36[0];v31._Mysize = (size_t)v23;v31._Myres = (size_t)v23 + 4 * v36[2];sub_1403F3CEE(v22, 0, (unsigned int)&v31._Mysize, 0, 1);sub_140019D58(v36);}sub_1401309D8(&v25);return v40;
}
定位按钮事件lambda
2、注册函数on_ok_clicked_license_window_1400A3F60
void __fastcall on_ok_clicked_license_window_1400A3F60(__int64 a1)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v23 = 0xFFFFFFFFFFFFFFFEui64;v1 = *(_QWORD *)(a1 + 8);gettext_14047A122(*(_QWORD *)(v1 + 0x278), (__int64)&v13[56]);memset(xor_str, 0, sizeof(xor_str));v18 = 0xFi64;v20 = 0i64;v19 = 0i64;v21 = 0xFi64;sub_1400A154A(*(_OWORD **)(v1 + 0x268), xor_str);sub_1400A0FC0(xor_str);if ( *(_QWORD *)&v13[72] ){// need ret 0v2 = check_lic_1400A19BC(&v14,(_QWORD *)(*(_QWORD *)(v1 + 0x268) + 0x10i64),*(_DWORD **)(v1 + 0x268),(unsigned int *)&v22,(int *)(*(_QWORD *)(v1 + 0x268) + 0xCi64),(_BYTE *)(*(_QWORD *)(v1 + 0x268) + 4i64));v3 = *(_QWORD *)(v1 + 0x268);*(_BYTE *)(v3 + 5) = v2 == 0;if ( v2 ){switch ( v2 ){case 1:// 这似乎是 Sublime Merge 许可证密钥,而不是 Sublime Text 密钥callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2EAF, 0i64);break;case 2:// 该许可证密钥似乎无效。callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2EBD, 0i64);break;case 3:// 许可证密钥已失效callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2ECB, 0i64);break;case 4:// 该许可证密钥因被共享而失效callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2ED9, 0i64);break;case 5:// 由于您的订阅已结束或已取消,许可证密钥已失效。callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2EE7, 0i64);break;default:break;}}else{vec_pop_14000233C((_QWORD *)(v3 + 0x30), &v14);string_140003006(&v15, &v14);v16 = v22;*(_QWORD *)xor_str = ___7___Func_impl_no_alloc_V_lambda_4___0__on_ok_clicked_license_window__QEAAXXZ_X__V_std__6B_;*(std_string *)&xor_str[8] = v15;v15._Mysize = 0i64;v15._Myres = 0xFi64;v15.u._Buf[0] = 0;LODWORD(v18) = v22;*((_QWORD *)&v19 + 1) = xor_str;sub_14020C932(xor_str, 0x1D4C0i64);sub_140005A2A((__int64)xor_str, v5);str_clear_140004410(&v15);// MachineGuid md5gen_lic_xor_data_1400A0FEE((__int64)xor_str);lic_data = &v14;// xor liclicense_file_xor_1400A1307(*(std_string **)xor_str, &v14);sub_14000439A((std_vector_str *)xor_str);Ptr = v14.u._Ptr;lic_data_sz = v14._Mysize;Myres = v14._Myres;v10 = xor_str;save_lic_1400A134D((__int64)xor_str);if ( Myres >= 0x10 )lic_data = (std_string *)Ptr;if ( *(_QWORD *)&xor_str[0x18] >= 0x10ui64 )v10 = *(char **)xor_str;// 保存lic文件到// C:\Users\xxx\AppData\Roaming\Sublime Text\Local\License.sublime_licensev11 = write_lic_1401230FC(v10, lic_data, lic_data_sz, 1);str_clear_140004410((std_string *)xor_str);if ( !v11 )callback_work_14013685C((__int64)&unk_1408E8998, (__int64)sub_1400A2D84, 0i64);v12 = thread_1401329DC(net_license_notification_1400A1583, (LPVOID)v22);CloseHandle(v12);if ( *(_BYTE *)(*(_QWORD *)(v1 + 0x268) + 4i64) )callback_work_14013685C((__int64)&unk_1408E8998, (__int64)purchasing_cb_1400A2E2E, 0i64);elsecallback_work_14013685C((__int64)&unk_1408E8998, (__int64)purchasing_cb_1400A2EA1, 0i64);}}else{v4 = xor_str;save_lic_1400A134D((__int64)xor_str);if ( *(_QWORD *)&xor_str[0x18] >= 0x10ui64 )v4 = *(_BYTE **)xor_str;sub_140123489(v4);str_clear_140004410((std_string *)xor_str);}if ( *(_QWORD *)(v1 + 0x2C8) )sub_140005A7E(v1 + 0x290);(*(void (__fastcall **)(_QWORD))(**(_QWORD **)(v1 + 0x28) + 0x18i64))(*(_QWORD *)(v1 + 0x28));str_clear_140004410(&v14);
}
check_lic_1400A19BC(to patch)
patch点 修改此函数返回0
该函数需返回0
parse_lic_1405B0E48
解析lic格式,并进行签名校验
// 需返回1
__int64 __fastcall parse_lic_1405B0E48(std_string *input_lic,std_string *emb,std_string *out_username,int *lic_type,std_string *prefix,std_string *random,std_string *unknow)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v16 = -2ui64;*(_OWORD *)&lic_verify_data[96] = 0i64;*(_QWORD *)&lic_verify_data[112] = 0i64;*(_QWORD *)&lic_verify_data[120] = 0xFi64;if ( (unsigned __int8)split_1405B0F77(input_lic,out_username,lic_type,prefix,random,unknow,(std_string *)&lic_verify_data[96]) ){// ret==>// Mifeng User// Single User License// EA7E-1184812User_License_1405B13B8(&v14, out_username, *lic_type, prefix, random, unknow);// ibtomcrypt中rsa_verify_hash// pkcs1_15 签名验证,sha1LOBYTE(v10) = verify_rsa_signature_1405B1B69(&v14, &data, emb);v11 = v10;str_clear_140004410(&v14);}else{v11 = 0;}str_clear_140004410(&data);return v11;
}
verify_rsa_signature_1405B1B69
bool __fastcall verify_rsa_signature_1405B1B69(std_string *userinfo, std_string *data, std_string *embed)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]// LibTomMathmemmove(&qword_1408F3A20, &off_1406DE250, 0x1A0ui64);sub_1404E87B8(&off_1406DE0A0);stat = sub_1404E8754("sha1");sha1hash_sz = 0x80;Mysize = userinfo->_Mysize;if ( userinfo->_Myres >= 0x10 )userinfo = (std_string *)userinfo->u._Ptr;if ( (unsigned int)calc_sha1_1404E504C(stat, (__int64)userinfo, Mysize, (__int64)sha1hash, &sha1hash_sz) )return 0;v8 = SLODWORD(embed->_Mysize) / 2;if ( embed->_Myres >= 0x10 )embed = (std_string *)embed->u._Ptr;hexstr2bytes_1405B1B24((__int64)embed, (__int64)v16, v8);// hexstr??to bytesif ( (unsigned int)rsa_import_1404ED7E8((__int64)v16, v8, v13) )return 0;sigdata_sz = LODWORD(data->_Mysize) >> 1;if ( data->_Myres >= 0x10 )data = (std_string *)data->u._Ptr;hexstr2bytes_1405B1B24((__int64)data, (__int64)sigdata, sigdata_sz);pub_key_ = 0;// sig: 签名的二进制数据。// siglen: 签名的长度。// hash: 要验证的哈希值。// hashlen: 哈希值的长度。// padding: 填充方案(如LTC_PKCS_1_V1_5)。// hash_idx: 哈希算法的索引(如find_hash("sha256"))。// stat: 返回的验证状态(0表示验证失败,1表示验证成功)。// key: 公钥结构体。if ( (unsigned int)rsa_verify_hash_1404EE0D8((__int64)sigdata,sigdata_sz,(__int64)sha1hash,sha1hash_sz,1,stat,0,&pub_key_,(__int64)v13) )return 0;sub_1404ED778(v13);return pub_key_ == 1;
}
3、网络校验
patch 线程函数直接ret
1、net_check_license_1400A30E3
2、net_license_notification_1400A1583(可选,在check_lic_1400A19BC patch后可以忽略)
net_check_license_1400A30E3(to patch)
BOOL __fastcall clicked_license_net_check_1400A3752(_QWORD *a1, int a2)
{void *v4; // rax_DWORD *Block; // [rsp+20h] [rbp-10h]Block = operator new(0x28ui64);string_140003006(Block, a1);Block[8] = a2;v4 = (void *)thread_1401329DC(net_check_license_1400A30E3, Block);return CloseHandle(v4);
}
net_check_license_1400A30E3
4、other
由于该n 未被分解factordb.com;
因此需进行patch
License.sublime_license解析&签名验证脚本
import binascii
import hashlib
from Crypto.PublicKey import RSA
from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA1import winregEMBEDDED_XOR_DATA = bytes([0x87, 0x36, 0x2A, 0x87, 0xBA, 0xB1, 0xBE, 0x9D, 0x31, 0xFF,0x31, 0x40, 0xBA, 0xB6, 0xB6, 0xB6, 0xB2, 0xB7, 0xB4, 0x36,0x3C, 0xB7, 0x87, 0x36, 0x30, 0xB5, 0x36, 0x36, 0xB7, 0x6F,0xCC, 0x15, 0xF2, 0xD5, 0x40, 0x72, 0x66, 0xFD, 0xBB, 0x4C,0xA5, 0x0E, 0xC3, 0xBB, 0xAE, 0xEB, 0xDC, 0x6B, 0xC9, 0xDA,0xD9, 0x7E, 0x9C, 0x1B, 0xB9, 0x05, 0x2A, 0xEE, 0x56, 0x6E,0x19, 0xD0, 0x3E, 0xBB, 0x9C, 0x3F, 0x74, 0x1C, 0x6B, 0x18,0x49, 0xCA, 0xFD, 0x84, 0x6B, 0x76, 0x08, 0x09, 0xE4, 0xAD,0x92, 0xAB, 0x58, 0xBB, 0x25, 0x88, 0xB1, 0x09, 0xCE, 0x05,0x85, 0x32, 0xEE, 0x1B, 0x49, 0x5E, 0x31, 0x62, 0x56, 0xE9,0xFA, 0xA0, 0xD1, 0x5D, 0xE1, 0x73, 0x56, 0xB1, 0xE0, 0x4D,0xC3, 0x6C, 0xBE, 0xC0, 0x74, 0x4C, 0xC2, 0x35, 0x00, 0x3B,0x63, 0xCC, 0x05, 0x70, 0x4E, 0x05, 0xE5, 0x03, 0x1E, 0xF1,0x8A, 0xA2, 0x41, 0x19, 0xD9, 0x5E, 0x94, 0xCA, 0xE3, 0x72,0xFF, 0xAC, 0x44, 0x57, 0x07, 0x2E, 0x97, 0xAE, 0xBC, 0x78,0x04, 0xA9, 0xEC, 0x52, 0xBE, 0x74, 0x8C, 0xB5, 0xB6, 0xA6])def get_machine_guid():try:registry_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Cryptography", 0, winreg.KEY_READ)value, regtype = winreg.QueryValueEx(registry_key, "MachineGuid")winreg.CloseKey(registry_key)return valueexcept FileNotFoundError:return Nonedef int_to_bytes(n: int, order='little') -> bytes:# 获取整数的位长度bit_length = n.bit_length()# 计算所需的最小字节数byte_length = (bit_length + 7) // 8# 转换为字节序列,使用大端字节序byte_array = n.to_bytes(byte_length, byteorder=order)return byte_arraydef import_rsa_der_pubkey(binary_data):try:# 从二进制数据中导入RSA密钥rsa_key = RSA.import_key(binary_data)print("RSA密钥导入成功!")print('e:', rsa_key.e)print('n:', rsa_key.n)return rsa_keyexcept ValueError as e:print(f"导入RSA密钥失败: {e}")def verify_rsa_signature(public_key, signature, message):try:# 导入公钥# public_key = RSA.import_key(public_key_pem)# 计算消息的哈希值(使用SHA-1)h = SHA1.new(message)# 验证签名pkcs1_15.new(public_key).verify(h, signature)print("签名验证成功!")return Trueexcept (ValueError, TypeError) as e:print(e)print("签名验证失败!")return Falsedef get_embedded_pubkey() -> str:ret = b''for i in range(0xa0):x = (EMBEDDED_XOR_DATA[i] ^ 0xb7) & 0xffret += x.to_bytes(1, 'little')ret = ret.hex().upper()return retEMBEDDED_PUBKEY_STR = get_embedded_pubkey()'''
#失效的lic,只为检查签名验证
—– BEGIN LICENSE —–
Mifeng User
Single User License
EA7E-1184812
C0DAA9CD 6BE825B5 FF935692 1750523A
EDF59D3F A3BD6C96 F8D33866 3F1CCCEA
1C25BE4D 25B1C4CC 5110C20E 5246CC42
D232C83B C99CCC42 0E32890C B6CBF018
B1D4C178 2F9DDB16 ABAA74E5 95304BEF
9D0CCFA9 8AF8F8E2 1E0A955E 4771A576
50737C65 325B6C32 817DCB83 A7394DFA
27B7E747 736A1198 B3865734 0B434AA5
—— END LICENSE ——'''def test():print('embedded_pubkey:', EMBEDDED_PUBKEY_STR)x = hashlib.sha256(EMBEDDED_PUBKEY_STR.encode()).digest()print('sha256 embedded key:', x.hex())'''sha256[1] ^ 0x34 | sha256[0xD] ^ 0xD7 | sha256[0x1E] ^ 0x56'''if (x[1] ^ 0x34 | x[0xD] ^ 0xD7 | x[0x1E] ^ 0x56) != 0:print('embedded_pubkey check sha256 error!')else:print('check embedded_pubkey sha256 success!')'''
Mifeng User
Single User License
EA7E-1184812'''userinfo = binascii.a2b_hex('4D6966656E6720557365720A53696E676C652055736572204C6963656E73650A454137452D31313834383132')msg_sha1 = hashlib.sha1(userinfo).digest()print('[#]msg_sha1:', msg_sha1.hex())rsa_key = import_rsa_der_pubkey(binascii.a2b_hex(EMBEDDED_PUBKEY_STR))user_data = binascii.a2b_hex('C0DAA9CD6BE825B5FF9356921750523AEDF59D3FA3BD6C96F8D338663F1CCCEA1C25BE4D25B1C4CC5110C20E5246CC42D232C83BC99CCC420E32890CB6CBF018B1D4C1782F9DDB16ABAA74E595304BEF9D0CCFA98AF8F8E21E0A955E4771A57650737C65325B6C32817DCB83A7394DFA27B7E747736A1198B38657340B434AA5')print('\n###############################[manual verify]###############################')i_data = bytes_to_long(user_data)data = pow(i_data, rsa_key.e, rsa_key.n)# print('rsa dec:',int_to_bytes(data).hex())# 解析解密后的数据# 对于PKCS#1 v1.5 签名,结构是:# 00 01 ff ... ff 00 [ASN.1编码的哈希算法ID和哈希值]# 查找ASN.1编码的起始位置(0x00之后)data = long_to_bytes(data)start_idx = data.index(b'\x00', 2) + 1asn1_encoded = data[start_idx:]dec_msg = asn1_encoded[-20:]print('[#]dec_msg:', dec_msg.hex())print('msg_sha1==dec_msg', msg_sha1 == dec_msg)print('###############################[manual verify end]###############################\n\n')print('pkcs1_15 verify:')verify_rsa_signature(rsa_key, user_data, userinfo)def calc_lic_xor_table() -> bytes:# MachineGuid=b'692a3bbc-1b8b-44c2-b95f-8a18dc8b5664'MachineGuid = get_machine_guid().encode()hs = hashlib.md5(MachineGuid).digest()return hsXOR_TABLE = calc_lic_xor_table()def lic_file_parse(path: str):with open(path, 'rb') as f:data = bytearray(f.read())for i in range(len(data)):data[i] ^= XOR_TABLE[i & 0xf]print("License.sublime_license dec:")print(data.decode(encoding='utf-8'))if __name__ == "__main__":# path=r'C:\Users\xxxx\AppData\Roaming\Sublime Text\Local\License.sublime_license'# lic_file_parse(path)test()pass