Created
November 4, 2021 06:43
-
-
Save opastorello/05f02f902339ebc27ea7f20c1838b066 to your computer and use it in GitHub Desktop.
Cracking Sublime Text Build (4121)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Cracking Sublime Text ( Build 4121 ) Tutorial Analysis | |
--- | |
Two main changes to be made for best experience. This can be done with script. | |
### License Key | |
While it is possible to deduce the format of the license key, there is available ones online to show. Analyse and see that it is still that same format. The main part is the verification of the hash values from the license key that we want to always be "correct". This is also the key that this tutorial will use. | |
``` | |
----- BEGIN LICENSE ----- | |
username_here | |
Unlimited User License | |
EA7E-00000000 | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
----- END LICENSE ----- | |
``` | |
#### 1. Return the RSA verification to always be True | |
Responsible for RSA verification starts from this function. | |
```c | |
__int64 __fastcall sub_7FF79C10868E(__int64 a1) | |
{ | |
unsigned int i; // esi | |
__int64 v4; // [rsp+0h] [rbp-80h] BYREF | |
char v5[32]; // [rsp+38h] [rbp-48h] BYREF | |
char v6[32]; // [rsp+58h] [rbp-28h] BYREF | |
_OWORD v7[2]; // [rsp+78h] [rbp-8h] BYREF | |
char v8[32]; // [rsp+98h] [rbp+18h] BYREF | |
_OWORD v9[2]; // [rsp+B8h] [rbp+38h] BYREF | |
char v10[32]; // [rsp+D8h] [rbp+58h] BYREF | |
_OWORD v11[2]; // [rsp+F8h] [rbp+78h] BYREF | |
_OWORD v12[2]; // [rsp+118h] [rbp+98h] BYREF | |
char v13[32]; // [rsp+138h] [rbp+B8h] BYREF | |
__int64 v14; // [rsp+158h] [rbp+D8h] | |
v14 = -2i64; | |
sub_7FF79C102DBE(&v4 + 7, "7E-1000\n"); | |
sub_7FF79C102DBE(v7, "EA"); | |
sub_7FF79C102DBE(v9, "User License\n"); | |
sub_7FF79C102DBE(v11, "Unlimited "); | |
sub_7FF79C102DBE(v12, "Name\n"); | |
sub_7FF79C10B5D7(v10, v12, v11); | |
sub_7FF79C10B5D7(v8, v10, v9); | |
sub_7FF79C10B5D7(v6, v8, v7); | |
sub_7FF79C10B5D7(v13, v6, v5); | |
sub_7FF79C10277C(v6); | |
sub_7FF79C10277C(v8); | |
sub_7FF79C10277C(v10); | |
sub_7FF79C10277C(v12); | |
sub_7FF79C10277C(v11); | |
sub_7FF79C10277C(v9); | |
sub_7FF79C10277C(v7); | |
sub_7FF79C10277C(v5); | |
for ( i = 0; i < 9; ++i ) | |
sub_7FF79C10395C(v13, "00000000000000000000000000000000\n"); | |
// If result is 0, | |
if ( !root_license_check_sub_7FF6A2C1751C(v13, 0i64, 0i64, 0i64, 0i64, 0i64) ) | |
sub_7FF79C309B74(sub_7FF79C10B632, a1, 480000i64); | |
return sub_7FF79C10277C(v13); | |
} | |
``` | |
Which checks license. | |
```c | |
__int64 __fastcall root_license_check_sub_7FF6A2C1751C(__int64 a1, __int64 a2, _DWORD *a3, unsigned int *a4, int *a5, _BYTE *a6) | |
{ | |
... | |
... | |
LOBYTE(v31[0]) = 0; | |
v10 = v33; | |
v34 = xmmword_7FF79C737950; | |
LOBYTE(v33[0]) = 0; | |
v11 = &qword_7FF79C9D3ED8; | |
hash_verified = verify_hash_please(v8, (__int64)&qword_7FF79C9D3ED8, (int)v24, &v38, (int)v35, v31, v33); | |
if ( *((_QWORD *)&v34 + 1) > 0xFui64 ) | |
v10 = (__int64 *)v33[0]; | |
v13 = sub_7FF79C6D8BB0((__int64)v10); | |
if ( hash_verified ) | |
v14 = (unsigned __int8)Current_set_0(v35, "E52D"); | |
else | |
v14 = 2; | |
if ( (unsigned __int64)qword_7FF79C9D3EF0 > 0xF ) | |
v11 = (__int64 *)qword_7FF79C9D3ED8; | |
sub_7FF79C234E63((__int128 *)v27, (__int64)v11, qword_7FF79C9D3EE8); | |
if ( v28 ^ 0xEA | v27[14] ^ 0xA5 | v29 ^ 0x56 ) | |
v14 = 2; | |
... | |
... | |
``` | |
This calls the verify_hash_please function (renamned) | |
```c | |
__int64 __fastcall verify_hash_please(int a1, __int64 a2, _QWORD *a3, _DWORD *a4, _QWORD *a5, void *a6, void *a7) | |
{ | |
unsigned int v10; // eax | |
unsigned int v11; // esi | |
_BYTE v13[32]; // [rsp+0h] [rbp-80h] BYREF | |
__int64 v14[4]; // [rsp+38h] [rbp-48h] BYREF | |
__int64 v15[11]; // [rsp+58h] [rbp-28h] BYREF | |
v15[4] = -2i64; | |
*(_OWORD *)&v13[72] = xmmword_7FF79C737950; | |
v13[56] = 0; | |
if ( (unsigned __int8)sub_7FF79C6A1C9F(a1, (int)a3, (int)a4, (int)a5, a6, a7, (__int64)&v13[56]) ) | |
{ | |
sub_7FF79C6A20B2((__int64)v15, a3, *a4, a5, a6, (__int64)a7); | |
LOBYTE(v10) = check_license_hash_sub_7FF79C6A2881(v15, v14, (__int64 *)a2); | |
v11 = v10; | |
sub_7FF79C10277C(v15); | |
} | |
else | |
{ | |
v11 = 0; | |
} | |
sub_7FF79C10277C(v14); | |
return v11; | |
} | |
``` | |
Invokes to check the RSA hash | |
```c | |
/* We just have to return 1 as value !*/ | |
bool __fastcall check_license_hash_sub_7FF79C6A2881(__int64 *a1, __int64 *a2, __int64 *a3) | |
{ | |
_QWORD rbx1; // rbx | |
_QWORD r14_1; // r14 | |
_QWORD rsi1; // rsi | |
_DWORD edi1; // edi | |
_DWORD er8_1; // er8 | |
_DWORD ebp4; // ebp | |
_DWORD ebx7; // ebx | |
bool result; // al | |
int var2108; // [rsp+50h] [rbp-2108h] | |
int result_1; // [rsp+54h] [rbp-2104h] | |
_QWORD var2100[9]; // [rsp+58h] [rbp-2100h] | |
char var20B8[128]; // [rsp+A0h] [rbp-20B8h] | |
char var2038[4096]; // [rsp+120h] [rbp-2038h] | |
char var1038[4152]; // [rsp+1120h] [rbp-1038h] | |
memmove(&qword_7FF79C9DF810, &off_7FF79C7D8820, 0x1A0ui64); | |
sub_7FF79C5E80CC(&off_7FF79C7D8670); | |
edi1 = sub_7FF79C5E8068("sha1"); | |
var2108 = 128; | |
er8_1 = *((_DWORD *)a2 + 4); | |
if ( (unsigned __int64)a2[3] > 0xF ) | |
a2 = (__int64 *)*a2; | |
if ( (unsigned int)sub_7FF79C5E49E8(edi1, (_DWORD)a2, er8_1, (unsigned int)var20B8, (__int64)&var2108) ) | |
return 0; | |
ebp4 = *((_DWORD *)a3 + 4) / 2; | |
if ( (unsigned __int64)a3[3] > 0xF ) | |
a3 = (__int64 *)*a3; | |
sub_7FF79C6A283C(a3, var1038, ebp4); | |
if ( (unsigned int)sub_7FF79C5ECF3C(var1038, ebp4, var2100) ) | |
return 0; | |
ebx7 = *((_DWORD *)a1 + 4) >> 1; | |
if ( (unsigned __int64)a1[3] > 0xF ) | |
a1 = (__int64 *)*a1; | |
sub_7FF79C6A283C(a1, var2038, ebx7); | |
result_1 = 0; | |
if ( (unsigned int)verify_RSA_hash_sub_7FF79C5ED870(var2038, ebx7, var20B8, var2108, 1, edi1, 0, &result_1, var2100) ) | |
return 0; | |
sub_7FF79C5ECECC(var2100); | |
return result_1 == 1; | |
} | |
``` | |
As we need to get the result to 1, patch to always return 1. | |
When cracking this, check that this 1 helps. I use 010editor (cracked also) to patch out the bytes. | |
This are the current bytes see in ida. | |
``` | |
; want to change to mov rax, 1 | |
; ret | |
.text:00007FF79C6A2881 41 57 push r15 | |
.text:00007FF79C6A2883 41 56 push r14 | |
.text:00007FF79C6A2885 56 push rsi | |
.text:00007FF79C6A2886 57 push rdi | |
.text:00007FF79C6A2887 55 push rbp | |
.text:00007FF79C6A2888 53 push rbx | |
.text:00007FF79C6A2889 B8 28 21 00 00 mov eax, 2128h | |
.text:00007FF79C6A288E E8 5D 62 05 00 call _alloca_probe | |
.text:00007FF79C6A2893 48 29 C4 sub rsp, rax | |
.text:00007FF79C6A2896 4C 89 C3 mov rbx, r8 | |
.text:00007FF79C6A2899 49 89 D6 mov r14, rdx | |
.text:00007FF79C6A289C 48 89 CE mov rsi, rcx | |
.text:00007FF79C6A289F 48 8D 0D 6A CF 33 00 lea rcx, qword_7FF79C9DF810 ; void * | |
.text:00007FF79C6A28A6 48 8D 15 73 5F 13 00 lea rdx, off_7FF79C7D8820 ; Src | |
.text:00007FF79C6A28AD 41 B8 A0 01 00 00 mov r8d, 1A0h ; Size | |
.text:00007FF79C6A28B3 E8 F8 9E 04 00 call memmove | |
.text:00007FF79C6A28B8 48 8D 0D B1 5D 13 00 lea rcx, off_7FF79C7D8670 ; Buf2 | |
.text:00007FF79C6A28BF E8 08 58 F4 FF call sub_7FF79C5E80CC | |
.text:00007FF79C6A28C4 48 8D 0D 23 2E 1B 00 lea rcx, aSha1 ; "sha1" | |
.text:00007FF79C6A28CB E8 98 57 F4 FF call sub_7FF79C5E8068 | |
``` | |
Change `41 57 41 56 56 57 55 53 b8 28 21 00 00 e8 5d` to `b8 01 00 00 00 c3 55 53 b8 28 21 00 00 e8 5d`. | |
In the debugger, after changing, should see this. | |
```asm | |
00007FF747152881 | B8 01000000 | mov eax,1 | | |
00007FF747152886 | C3 | ret | | |
00007FF747152887 | 55 | push rbp | | |
00007FF747152888 | 53 | push rbx | rbx:"81044230" | |
00007FF747152889 | B8 28210000 | mov eax,2128 | | |
00007FF74715288E | E8 5D620500 | call sublime_text.7FF7471A8AF0 | | |
00007FF747152893 | 48:29C4 | sub rsp,rax | | |
00007FF747152896 | 4C:89C3 | mov rbx,r8 | rbx:"81044230", r8:&"30819D300D06092A864886F70D010101050003818B0030818702818100D87BA24562F7C5D14A0CFB12B9740C195C6BDC7E6D6EC92BAC0EB29D59E1D9AE67890C2B88C3ABDCAFFE7D4A33DCC1BFBE531A251CEF0C923F06BE79B2328559ACFEE986D5E15E4D1766EA56C4E10657FA74DB0977C3FB7582B78CD47BB2C7F9B252B4A9463D15F6AE6EE9237D54C5481BF3E0B09920190BCFB31E5BE509C33B020111" | |
00007FF747152899 | 49:89D6 | mov r14,rdx | r14:&"30819D300D06092A864886F70D010101050003818B0030818702818100D87BA24562F7C5D14A0CFB12B9740C195C6BDC7E6D6EC92BAC0EB29D59E1D9AE67890C2B88C3ABDCAFFE7D4A33DCC1BFBE531A251CEF0C923F06BE79B2328559ACFEE986D5E15E4D1766EA56C4E10657FA74DB0977C3FB7582B78CD47BB2C7F9B252B4A9463D15F6AE6EE9237D54C5481BF3E0B09920190BCFB31E5BE509C33B020111", rdx:&"0C0CD4A8CAA317D9CCABD1AC434C984C7E4A0B1377893C3EDD0A5BA1B2EB721C4BAAB4C49B96437D14EB743E7DB55D9C7CA26EE267C3B4EC29B2C65A88D90C59CB6CCBA57DE6177BC02C28268C9A21B06AB1A5B620B09EA | |
00007FF74715289C | 48:89CE | mov rsi,rcx | rcx:&"TESTING\nUnlimited User License\nEA7E-81044230" | |
00007FF74715289F | 48:8D0D 6ACF3300 | lea rcx,qword ptr ds:[7FF74748F810] | rcx:&"TESTING\nUnlimited User License\nEA7E-81044230", 00007FF74748F810:&"LibTomMath" | |
00007FF7471528A6 | 48:8D15 735F1300 | lea rdx,qword ptr ds:[7FF747288820] | rdx:&"0C0CD4A8CAA317D9CCABD1AC434C984C7E4A0B1377893C3EDD0A5BA1B2EB721C4BAAB4C49B96437D14EB743E7DB55D9C7CA26EE267C3B4EC29B2C65A88D90C59CB6CCBA57DE6177BC02C28268C9A21B06AB1A5B620B09EA201C979BD29670B1992DC6D906E3658494AB847395B4C3EA1048CC1D09748ED54CAC9D58590CAD815", 00007FF747288820:&"LibTomMath" | |
00007FF7471528AD | 41:B8 A0010000 | mov r8d,1A0 | | |
00007FF7471528B3 | E8 F89E0400 | call sublime_text.7FF74719C7B0 | | |
00007FF7471528B8 | 48:8D0D B15D1300 | lea rcx,qword ptr ds:[7FF747288670] | rcx:&"TESTING\nUnlimited User License\nEA7E-81044230", 00007FF747288670:&"sha1" | |
00007FF7471528BF | E8 0858F4FF | call sublime_text.7FF7470980CC | | |
00007FF7471528C4 | 48:8D0D 232E1B00 | lea rcx,qword ptr ds:[7FF7473056EE] | rcx:&"TESTING\nUnlimited User License\nEA7E-81044230", 00007FF7473056EE:"sha1" | |
00007FF7471528CB | E8 9857F4FF | call sublime_text.7FF747098068 | | |
``` | |
--- | |
### 2. Patch so not connect to sublimetext site for license check | |
Sometime while running with debugger, there is exception. RPC_S_Server_Unavailable is message of exception. See [this](`https://docs.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/not-log-on-error-rpc-server-unavailable`). It appears to be DNS failure for connection. This step is not very important but it seems to be better to just do it anyways. | |
``` | |
#### After submitting the license | |
INT3 breakpoint at sublime_text.00007FF747152881 (00007FF747152881)! | |
Thread 66A8 created, Entry: sublime_text.00007FF746C57117 | |
SetThreadName(66A8, "license_notification") | |
EXCEPTION_DEBUG_INFO: | |
dwFirstChance: 1 | |
ExceptionCode: 406D1388 (MS_VC_EXCEPTION) | |
ExceptionFlags: 00000000 | |
ExceptionAddress: 00007FFA5D874F99 kernelbase.00007FFA5D874F99 | |
NumberParameters: 6 | |
ExceptionInformation[00]: 0000000000001000 | |
ExceptionInformation[01]: 00007FF7472F465F sublime_text.00007FF7472F465F | |
ExceptionInformation[02]: 00000000000066A8 | |
ExceptionInformation[03]: 0000000004D4A306 | |
ExceptionInformation[04]: 0000000000000000 | |
ExceptionInformation[05]: 000000819FEFFBB0 | |
First chance exception on 00007FFA5D874F99 (406D1388, MS_VC_EXCEPTION)! | |
###### After attempting to close | |
Thread 275C created, Entry: sublime_text.00007FF746C58A22 | |
SetThreadName(275C, "license_check") | |
EXCEPTION_DEBUG_INFO: | |
dwFirstChance: 1 | |
ExceptionCode: 406D1388 (MS_VC_EXCEPTION) | |
ExceptionFlags: 00000000 | |
ExceptionAddress: 00007FFA5D874F99 kernelbase.00007FFA5D874F99 | |
NumberParameters: 6 | |
ExceptionInformation[00]: 0000000000001000 | |
ExceptionInformation[01]: 00007FF7472F63AD sublime_text.00007FF7472F63AD | |
ExceptionInformation[02]: 000000000000275C | |
ExceptionInformation[03]: 0000000000000000 | |
ExceptionInformation[04]: 0000000000000000 | |
ExceptionInformation[05]: 000000819FEFF5C0 | |
First chance exception on 00007FFA5D874F99 (406D1388, MS_VC_EXCEPTION)! | |
###### After attempting to save the new file | |
DLL Loaded: 00007FFA56870000 C:\Windows\System32\cscapi.dll | |
EXCEPTION_DEBUG_INFO: | |
dwFirstChance: 1 | |
ExceptionCode: 000006BA (RPC_S_SERVER_UNAVAILABLE) | |
ExceptionFlags: 00000001 | |
ExceptionAddress: 00007FFA5D874F99 kernelbase.00007FFA5D874F99 | |
NumberParameters: 0 | |
First chance exception on 00007FFA5D874F99 (000006BA, RPC_S_SERVER_UNAVAILABLE)! | |
``` | |
For this case, we do not need the connection to their server. We can find this server address hardcoded in the binary. Patch `license.sublimehq.com` to `127.0.0.1` | |
``` | |
CHANGE FROM | |
00007FF7472F4D4E 6C 69 63 65 6E 73 65 2E 73 75 62 6C 69 6D 65 68 license.sublimeh | |
00007FF7472F4D5E 71 2E 63 6F 6D 00 71 77 65 72 74 79 75 69 6F 70 q.com.qwertyuiop | |
TO | |
00007FF7472F4D4E 31 32 37 2e 30 2e 30 2e 31 00 00 00 00 00 00 00 127.0.0.1....... | |
00007FF7472F4D5E 00 00 00 00 00 00 71 77 65 72 74 79 75 69 6F 70 ......qwertyuiop | |
``` | |
This is because sublime text will create a thread with the function for license notification. | |
```c | |
v2 = root_license_check_sub_7FF6A2C1751C( | |
v20, | |
*(v1 + 616) + 16i64, | |
*(v1 + 616), | |
&v23, | |
(*(v1 + 616) + 12i64), | |
(*(v1 + 616) + 4i64)); | |
... | |
... | |
sub_7FF746BB277C(&v15); | |
if ( !v10 ) | |
warning_message_box_sub_7FF79C23B528(&unk_7FF747485958, sub_7FF746C58716, 0i64); | |
v11 = CreateThread_sub_7FF746CE7C5C(license_notification_sub_7FF746C57117, v23); | |
CloseHandle(v11); | |
... | |
... | |
``` | |
In the license notification thread, a request is made and requested to domain `www.sublimetext.com` to check for sublime version checking. For instance, `/license_notification?n=0&b=4121&m=FRnBZEeWU-l-fp1689XdMA`. | |
license_check thread is also created which query to license.sublimehq.com also for `sublime-license-check` with parameters looking like `/check/29f27acf86591ee7be8691fd97ebcb6d3faf05d1f06431b73603d400fddc724c?n=0&b=4121&m=FRnBZEeWU-l-fp1689XdMA` | |
```c | |
__int64 __fastcall license_check_thread_sub_7FF746C58A22(void *Block) | |
{ | |
... | |
... | |
sub_7FF746CE7CB8("license_check"); | |
v2 = v35; | |
check_license_sub_1405A2221(v35, Block); | |
v3 = *(Block + 8); | |
if ( Block ) | |
sub_7FF746BB277C(Block); | |
j_free_0(Block); | |
if ( v35[3] > 0xFui64 ) | |
v2 = v35[0]; | |
sub_7FF746CE5017(v2, v35[2], Str); | |
sub_7FF746BEC654(v32, 32i64, "%d", v3); | |
v4 = v36; | |
sub_7FF746DCDFFF(v36); | |
if ( v36[3] > 0xFui64 ) | |
v4 = v36[0]; | |
sub_7FF746CDD6B1(v4, v36[2], v33); | |
v8 = xmmword_7FF7471E7940; | |
v9 = v10; | |
*&v22 = "/check/"; | |
*(&v22 + 1) = ""; | |
sub_7FF746BB5E62(&v8, &v22); | |
*&v23 = Str; | |
*(&v23 + 1) = &v10[strlen(Str) + 520]; | |
sub_7FF746BB5E62(&v8, &v23); | |
*&v24 = "?n="; | |
*(&v24 + 1) = ""; | |
sub_7FF746BB5E62(&v8, &v24); | |
*&v25 = v32; | |
*(&v25 + 1) = &v32[strlen(v32)]; | |
sub_7FF746BB5E62(&v8, &v25); | |
*&v26 = "&b="; | |
*(&v26 + 1) = ""; | |
sub_7FF746BB5E62(&v8, &v26); | |
*&v27 = "4121"; | |
*(&v27 + 1) = ""; | |
sub_7FF746BB5E62(&v8, &v27); | |
*&v28 = "&m="; | |
*(&v28 + 1) = ""; | |
sub_7FF746BB5E62(&v8, &v28); | |
*&v29 = v33; | |
*(&v29 + 1) = &v33[strlen(v33)]; | |
sub_7FF746BB5E62(&v8, &v29); | |
v14 = xmmword_7FF7471E7950; | |
v13[0] = 0; | |
v16 = xmmword_7FF7471E7950; | |
v15[0] = 0; | |
v18 = xmmword_7FF7471E7950; | |
v17[0] = 0; | |
v19 = 0; | |
v20 = 0i64; | |
v21 = 0i64; | |
v12 = 1i64; | |
strcpy_(v13, "license.sublimehq.com"); | |
sub_7FF746CE5A02(&v8, Src); | |
sub_7FF746BBB46E(v15, Src); | |
sub_7FF746BB277C(Src); | |
strcpy_(v17, "sublime-license-check/3.0"); | |
v5 = v37; | |
v38 = xmmword_7FF7471E7950; | |
LOBYTE(v37[0]) = 0; | |
v30 = &string_http_connection_handler::`vftable'; | |
... | |
... | |
} | |
``` | |
--- | |
#### Python Script | |
Change `41 57 41 56 56 57 55 53 b8 28 21 00 00 e8 5d` to `b8 01 00 00 00 c3 55 53 b8 28 21 00 00 e8 5d`. | |
``` | |
CHANGE FROM | |
00007FF7472F4D4E 6C 69 63 65 6E 73 65 2E 73 75 62 6C 69 6D 65 68 license.sublimeh | |
00007FF7472F4D5E 71 2E 63 6F 6D 00 71 77 65 72 74 79 75 69 6F 70 q.com.qwertyuiop | |
TO | |
00007FF7472F4D4E 31 32 37 2e 30 2e 30 2e 31 00 00 00 00 00 00 00 127.0.0.1....... | |
00007FF7472F4D5E 00 00 00 00 00 00 71 77 65 72 74 79 75 69 6F 70 ......qwertyuiop | |
``` | |
Instructions: | |
- Go to sublimetext folder and extract the sublimetext.exe to Desktop | |
- Run the python script | |
```python | |
# Use Python 3 | |
f = open("./sublime_text.exe","rb") | |
data = f.read() | |
f.close | |
f = open("./sublime_text.exe.back","wb") | |
f.write(data) | |
f.close() | |
f = open("./sublime_text.exe","wb") | |
data = data.replace(b"\x41\x57\x41\x56\x56\x57\x55\x53\xb8\x28\x21\x00\x00\xe8\x5d",b"\xb8\x01\x00\x00\x00\xc3\x55\x53\xb8\x28\x21\x00\x00\xe8\x5d") | |
data = data.replace(b"\x6C\x69\x63\x65\x6E\x73\x65\x2E\x73\x75\x62\x6C\x69\x6D\x65\x68\x71\x2E\x63\x6F\x6D\x00\x71\x77\x65\x72\x74\x79\x75\x69\x6F\x70",b"\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x71\x77\x65\x72\x74\x79\x75\x69\x6F\x70") | |
f.write(data) | |
f.close() | |
``` | |
- Put sublimetext.exe back into the original folder. | |
- Go to Help -> Enter License | |
``` | |
----- BEGIN LICENSE ----- | |
username_here | |
Unlimited User License | |
EA7E-00000000 | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
feedbeef feedbeef feedbeef feedbeef | |
----- END LICENSE ----- | |
``` | |
--- |
@opastorello I learn and apply the IDA you mentioned and I think maybe I have located the hash checking logic in Sublime Text 4 Build x4126 for linux :
Pseudo code:
if ( var0 )
var1 = need_to_do();
Assembly code:
.text:000000000058674A test bl, bl ; Logical Compare
.text:000000000058674C jz short loc_586763 ; Jump if Zero (ZF=1)
In order to get checking okay result always, need to ensure var0=1. Could you please teach me how to do that? I tried to use "test $1, $1" but it's a syntax error...
Thanks a lot!
I find a tricky way, replace jz with jnz instruction and it works. LOL
Can anyone help me on how to use this trick, I 'm pretty confused..
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Bro, thanks for detailed guidance! I tried similar way for newset Sublime Text 4 Build x4126 for windows, and it works!
When I tried to do the same modification on Sublime Text 4 Build x4126 for linux (https://download.sublimetext.com/sublime_text_build_4126_x64.tar.xz), I do locate the server IP logic part in hexadecimal mode, but failed to locate where checking result logic is. Could you please share the way how to locate where checking result logic is? Thanks!