mirror of
https://github.com/DoubleLabyrinth/navicat-keygen.git
synced 2019-12-02 05:10:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1f5900770 | ||
|
|
a15d77bfc9 | ||
|
|
93f355e604 | ||
|
|
8f0986e00e |
@@ -22,6 +22,92 @@
|
||||
|
||||
If you have the corresponding private key, please tell me. I would be very appreciated for your generous.
|
||||
|
||||
__NOTICE:__
|
||||
|
||||
Start from __Navicat Premium 12.0.25__, Navicat do not load this public key from resource in `navicat.exe`. Actually the public key is stored in `libcc.dll` and encrypted. And to avoid being replaced easily, the public key is split into 5 parts:
|
||||
|
||||
The content below is discovered from `libcc.dll` of Navicat Premium x64 12.0.25 Simplified Chinese version. SHA256 value is `607e0a84c75966b00f3d12fa833e91d159e4f51ac51b6ba66f98d0c3cbefdce0`. I do not guaranteed that __offset__ value is absolutely correct in other versions. But __char string__ and __immediate values__ is highly possible to be found.
|
||||
|
||||
1. At file offset `+ 0x1A12090` in `libcc.dll`, stored as __char string__:
|
||||
|
||||
> "D75125B70767B94145B47C1CB3C0755E
|
||||
> 7CCB8825C5DCE0C58ACF944E08280140
|
||||
> 9A02472FAFFD1CD77864BB821AE36766
|
||||
> FEEDE6A24F12662954168BFA314BD950
|
||||
> 32B9D82445355ED7BC0B880887D650F5"
|
||||
|
||||
2. At file offset `+ 0x59D799` in `libcc.dll`, stored as __immediate value__ in a instruction:
|
||||
|
||||
> 0xFE 0xEA 0xBC 0x01
|
||||
|
||||
In decimal: `29158142`
|
||||
|
||||
3. At file offset `+ 0x1A11DA0` in `libcc.dll`, stored as __char string__:
|
||||
|
||||
> "E1CED09B9C2186BF71A70C0FE2F1E0AE
|
||||
> F3BD6B75277AAB20DFAF3D110F75912B
|
||||
> FB63AC50EC4C48689D1502715243A79F
|
||||
> 39FF2DE2BF15CE438FF885745ED54573
|
||||
> 850E8A9F40EE2FF505EB7476F95ADB78
|
||||
> 3B28CA374FAC4632892AB82FB3BF4715
|
||||
> FCFE6E82D03731FC3762B6AAC3DF1C3B
|
||||
> C646FE9CD3C62663A97EE72DB932A301
|
||||
> 312B4A7633100C8CC357262C39A2B3A6
|
||||
> 4B224F5276D5EDBDF0804DC3AC4B8351
|
||||
> 62BB1969EAEBADC43D2511D6E0239287
|
||||
> 81B167A48273B953378D3D2080CC0677
|
||||
> 7E8A2364F0234B81064C5C739A8DA28D
|
||||
> C5889072BF37685CBC94C2D31D0179AD
|
||||
> 86D8E3AA8090D4F0B281BE37E0143746
|
||||
> E6049CCC06899401264FA471C016A96C
|
||||
> 79815B55BBC26B43052609D9D175FBCD
|
||||
> E455392F10E51EC162F51CF732E6BB39
|
||||
> 1F56BBFD8D957DF3D4C55B71CEFD54B1
|
||||
> 9C16D458757373E698D7E693A8FC3981
|
||||
> 5A8BF03BA05EA8C8778D38F9873D62B4
|
||||
> 460F41ACF997C30E7C3AF025FA171B5F
|
||||
> 5AD4D6B15E95C27F6B35AD61875E5505
|
||||
> 449B4E"
|
||||
|
||||
4. At file offset `+ 0x59D77F` in `libcc.dll`, stored as __immediate value__ in a instruction:
|
||||
|
||||
> 0x59 0x08 0x01 0x00 (in decimal )
|
||||
|
||||
In decimal: `67673`
|
||||
|
||||
5. At file offset `+ 0x1A11D8C` in `libcc.dll`, stored as __char string__:
|
||||
|
||||
> "92933"
|
||||
|
||||
Then output encrypted public key with format `"%s%d%s%d%s"`, the order is the same as it list:
|
||||
|
||||
> D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933
|
||||
|
||||
This encrypted public key can be decrypted by my another repo: [how-does-navicat-encrypt-password](https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password), while the key used is `b'23970790'`
|
||||
|
||||
Example:
|
||||
|
||||
```cmd
|
||||
E:\GitHub>git clone https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password.git
|
||||
...
|
||||
E:\GitHub>cd how-does-navicat-encrypt-password\python3
|
||||
E:\GitHub\how-does-navicat-encrypt-password\python3>python
|
||||
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> from NavicatCrypto import *
|
||||
>>> cipher = Navicat11Crypto(b'23970790')
|
||||
>>> print(cipher.DecryptString('D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933'))
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
|
||||
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
|
||||
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
|
||||
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
|
||||
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
|
||||
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
|
||||
awIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
```
|
||||
|
||||
* __Request Code__
|
||||
|
||||
It is a Base64 string that represents 256-bytes-long data, while the 256-bytes-long data is the cipher text of the __offline activation information__ encrypted by __Navicat Activation Public Key__.
|
||||
@@ -166,20 +252,35 @@
|
||||
5. Input __Activation Code__, then offline activation is done.
|
||||
|
||||
## 4. How to use
|
||||
1. Build patcher and keygen.
|
||||
1. Build patcher and keygen in Release configuration or download the latest release.
|
||||
|
||||
2. Replace __Navicat Activation Public Key__ in `navicat.exe`.
|
||||
2. Replace __Navicat Activation Public Key__ in `navicat.exe` or `libcc.dll`.
|
||||
Example:
|
||||
|
||||
```bash
|
||||
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12\navicat.exe"
|
||||
D:\Program Files\PremiumSoft\Navicat Premium 12\navicat.exe has been backed up.
|
||||
Public key has been replaced.
|
||||
Success!
|
||||
* For Navicat Premium version < 12.0.25
|
||||
```bash
|
||||
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12"
|
||||
D:\Program Files\PremiumSoft\Navicat Premium 12\navicat.exe has been backed up.
|
||||
Public key has been replaced.
|
||||
Success!
|
||||
```
|
||||
|
||||
```
|
||||
* For Navicat Premium version >= 12.0.25
|
||||
```bash
|
||||
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12"
|
||||
D:\Program Files\PremiumSoft\Navicat Premium 12\libcc.dll has been backed up.
|
||||
Public key has been replaced.
|
||||
Success!
|
||||
```
|
||||
You may wait for a few seconds or even longer, because patcher is search for a appropriate RSA key. Finally you will get `RegPrivateKey.pem` file at current directory.
|
||||
|
||||
You will get `RegPrivateKey.pem` file at current directory.
|
||||
If you do not want to search, use `RegPrivateKey.pem` in my latest release, then:
|
||||
```bash
|
||||
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12" RegPrivateKey.pem
|
||||
D:\Program Files\PremiumSoft\Navicat Premium 12\libcc.dll has been backed up.
|
||||
Public key has been replaced.
|
||||
Success!
|
||||
```
|
||||
|
||||
3. Then in console:
|
||||
|
||||
|
||||
+154
-56
@@ -1,4 +1,4 @@
|
||||
#include <tchar.h>
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
@@ -26,9 +26,22 @@
|
||||
#pragma comment(lib, "Crypt32.lib") // some symbol are used in OpenSSL lib
|
||||
|
||||
#define NAVICAT_12
|
||||
#define NAVICAT_CHS
|
||||
|
||||
void GenerateSnKey(char(&SnKey)[16]) {
|
||||
enum NavicatLanguage {
|
||||
English,
|
||||
SimplifiedChinese,
|
||||
TraditionalChinese,
|
||||
Japanese,
|
||||
Polish,
|
||||
Spanish,
|
||||
French,
|
||||
German,
|
||||
Korean,
|
||||
Russian,
|
||||
Portuguese
|
||||
};
|
||||
|
||||
void GenerateSnKey(char(&SnKey)[16], NavicatLanguage _language) {
|
||||
static char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
static DES_cblock DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
|
||||
|
||||
@@ -37,42 +50,54 @@ void GenerateSnKey(char(&SnKey)[16]) {
|
||||
temp_SnKey[3] = rand();
|
||||
temp_SnKey[4] = rand();
|
||||
|
||||
#if defined(NAVICAT_ENG)
|
||||
temp_SnKey[5] = 0xAC; // Must be 0xAC for English version.
|
||||
temp_SnKey[6] = 0x88; // Must be 0x88 for English version.
|
||||
#elif defined(NAVICAT_CHS)
|
||||
temp_SnKey[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
|
||||
temp_SnKey[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
|
||||
#elif defined(NAVICAT_CHT)
|
||||
temp_SnKey[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
|
||||
temp_SnKey[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
|
||||
#elif defined(NAVICAT_JAP)
|
||||
temp_SnKey[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_POL)
|
||||
temp_SnKey[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_SPA)
|
||||
temp_SnKey[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_FRE)
|
||||
temp_SnKey[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
|
||||
temp_SnKey[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
|
||||
#elif defined(NAVICAT_GER)
|
||||
temp_SnKey[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_KOR)
|
||||
temp_SnKey[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_RUS)
|
||||
temp_SnKey[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
|
||||
#elif defined(NAVICAT_POR)
|
||||
temp_SnKey[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
|
||||
#else
|
||||
#error "Navicat product type is not specified."
|
||||
#endif
|
||||
switch (_language) {
|
||||
case English:
|
||||
temp_SnKey[5] = 0xAC; // Must be 0xAC for English version.
|
||||
temp_SnKey[6] = 0x88; // Must be 0x88 for English version.
|
||||
break;
|
||||
case SimplifiedChinese:
|
||||
temp_SnKey[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
|
||||
temp_SnKey[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
|
||||
break;
|
||||
case TraditionalChinese:
|
||||
temp_SnKey[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
|
||||
temp_SnKey[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
|
||||
break;
|
||||
case Japanese:
|
||||
temp_SnKey[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case Polish:
|
||||
temp_SnKey[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case Spanish:
|
||||
temp_SnKey[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case French:
|
||||
temp_SnKey[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
|
||||
temp_SnKey[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
|
||||
break;
|
||||
case German:
|
||||
temp_SnKey[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case Korean:
|
||||
temp_SnKey[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case Russian:
|
||||
temp_SnKey[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
|
||||
break;
|
||||
case Portuguese:
|
||||
temp_SnKey[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
|
||||
temp_SnKey[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(NAVICAT_12)
|
||||
temp_SnKey[7] = 0x65; // 0x65 - commercial, 0x66 - non-commercial
|
||||
@@ -173,6 +198,59 @@ BOOL GenerateLicense(RSA* RSAPrivateKey,
|
||||
#endif
|
||||
}
|
||||
|
||||
RSA* ReadRSAPrivateKeyFromFile(LPCTSTR filename) {
|
||||
#ifdef UNICODE
|
||||
int req_size = WideCharToMultiByte(CP_ACP, 0, filename, -1, nullptr, 0, nullptr, nullptr);
|
||||
if (req_size == 0) {
|
||||
_tprintf_s(TEXT("Failed to convert wchar* to char*. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> WideCharToMultiByte]\r\n"), GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char* temp_filename = new char[req_size]();
|
||||
WideCharToMultiByte(CP_ACP, 0, filename, -1, temp_filename, req_size, nullptr, nullptr);
|
||||
|
||||
BIO* b = BIO_new(BIO_s_file());
|
||||
if (b == nullptr) {
|
||||
_tprintf_s(TEXT("Failed to create BIO object. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> BIO_new]\r\n"), ERR_get_error());
|
||||
delete[] temp_filename;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (1 != BIO_read_filename(b, temp_filename)) {
|
||||
_tprintf_s(TEXT("Failed to set target file of BIO. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> BIO_read_filename]\r\n"), ERR_get_error());
|
||||
|
||||
BIO_free_all(b);
|
||||
delete[] temp_filename;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
delete[] temp_filename;
|
||||
#else
|
||||
BIO* b = BIO_new(BIO_s_file());
|
||||
if (b == nullptr) {
|
||||
_tprintf_s(TEXT("Failed to create BIO object. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> BIO_new]\r\n"), ERR_get_error());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (1 != BIO_read_filename(b, filename)) {
|
||||
_tprintf_s(TEXT("Failed to set target file of BIO. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> BIO_read_filename]\r\n"), ERR_get_error());
|
||||
|
||||
BIO_free_all(b);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
RSA* ret = PEM_read_bio_RSAPrivateKey(b, nullptr, nullptr, nullptr);
|
||||
if (ret == nullptr) {
|
||||
_tprintf_s(TEXT("Failed to read RSA private key. CODE: 0x%08x @[ReadRSAPrivateKeyFromFile -> PEM_read_bio_RSAPrivateKey]\r\n"), ERR_get_error());
|
||||
|
||||
BIO_free_all(b);
|
||||
return nullptr;
|
||||
} else {
|
||||
BIO_free_all(b);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int _tmain(int argc, TCHAR* argv[]) {
|
||||
if (argc != 2) {
|
||||
_tprintf_s(TEXT("Usage:\r\n"));
|
||||
@@ -181,28 +259,48 @@ int _tmain(int argc, TCHAR* argv[]) {
|
||||
}
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
#ifdef UNICODE
|
||||
char pem_file_path[MAX_PATH] = { };
|
||||
sprintf_s(pem_file_path, "%S", argv[1]);
|
||||
#else
|
||||
char* pem_file_path = argv[1];
|
||||
#endif
|
||||
|
||||
RSA* PrivateKey = nullptr;
|
||||
{
|
||||
BIO* PrivateKeyFile = BIO_new(BIO_s_file());
|
||||
BIO_read_filename(PrivateKeyFile, pem_file_path);
|
||||
PrivateKey = PEM_read_bio_RSAPrivateKey(PrivateKeyFile, nullptr, nullptr, nullptr);
|
||||
BIO_free_all(PrivateKeyFile);
|
||||
}
|
||||
RSA* PrivateKey = ReadRSAPrivateKeyFromFile(argv[1]);
|
||||
if (PrivateKey == nullptr)
|
||||
return 0;
|
||||
|
||||
if (PrivateKey == nullptr) {
|
||||
_tprintf_s(TEXT("Failed to load private key.\r\n"));
|
||||
return -1;
|
||||
std::cout
|
||||
<< "Which is your Navicat language?" << std::endl
|
||||
<< "0. English" << std::endl
|
||||
<< "1. Simplified Chinese" << std::endl
|
||||
<< "2. Traditional Chinese" << std::endl
|
||||
<< "3. Japanese" << std::endl
|
||||
<< "4. Polish" << std::endl
|
||||
<< "5. Spanish" << std::endl
|
||||
<< "6. French" << std::endl
|
||||
<< "7. German" << std::endl
|
||||
<< "8. Korean" << std::endl
|
||||
<< "9. Russian" << std::endl
|
||||
<< "10. Portuguese" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
int LanguageIndex = -1;
|
||||
while (true) {
|
||||
std::cout << "(input index)>";
|
||||
|
||||
std::string temp;
|
||||
if (!std::getline(std::cin, temp)) {
|
||||
RSA_free(PrivateKey);
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
LanguageIndex = std::stoi(temp);
|
||||
if (LanguageIndex < 0 || LanguageIndex > 10)
|
||||
throw std::invalid_argument("Invalid index");
|
||||
break;
|
||||
} catch (...) {
|
||||
std::cout << "Invalid index." << std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
char SnKey[16] = { };
|
||||
GenerateSnKey(SnKey);
|
||||
GenerateSnKey(SnKey, static_cast<NavicatLanguage>(LanguageIndex));
|
||||
|
||||
std::string strName;
|
||||
std::string strOrganization;
|
||||
|
||||
@@ -3,16 +3,25 @@
|
||||
// Solution0 is for navicat premium of which the version < 12.0.25
|
||||
namespace patcher::Solution0 {
|
||||
|
||||
BOOL Do(LPCTSTR navicat_exe_path) {
|
||||
BOOL Do(LPCTSTR navicat_exe_path, LPCTSTR prepared_key_file) {
|
||||
if (!BackupFile(navicat_exe_path))
|
||||
return FALSE;
|
||||
|
||||
RSA* PrivateKey = GenerateRSAKey();
|
||||
if (PrivateKey == nullptr)
|
||||
return FALSE;
|
||||
RSA* PrivateKey = nullptr;
|
||||
if (prepared_key_file == nullptr) {
|
||||
PrivateKey = GenerateRSAKey();
|
||||
if (PrivateKey == nullptr)
|
||||
return FALSE;
|
||||
|
||||
if (!WriteRSAPrivateKeyToFile(TEXT("RegPrivateKey.pem"), PrivateKey))
|
||||
return FALSE;
|
||||
if (!WriteRSAPrivateKeyToFile(TEXT("RegPrivateKey.pem"), PrivateKey)) {
|
||||
RSA_free(PrivateKey);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
PrivateKey = ReadRSAPrivateKeyFromFile(prepared_key_file);
|
||||
if (PrivateKey == nullptr)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char* pem_pubkey = GetPEMText(PrivateKey);
|
||||
if (pem_pubkey == nullptr)
|
||||
@@ -39,7 +48,7 @@ namespace patcher::Solution0 {
|
||||
delete[] pem_pubkey;
|
||||
return FALSE;
|
||||
} else {
|
||||
_tprintf_s(TEXT("@[patcher::Solution0::Do]: Public key has been replaced.\r\n"));
|
||||
_tprintf_s(TEXT("@[patcher::Solution0::Do]: Public key has been replaced by:\r\n%hs"), pem_pubkey);
|
||||
|
||||
EndUpdateResource(hUpdater, FALSE);
|
||||
delete[] pem_pubkey;
|
||||
|
||||
+276
-20
@@ -40,25 +40,267 @@ namespace patcher::Solution1 {
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Do(LPCTSTR libcc_dll_path, LPCTSTR prepared_key_file) {
|
||||
uint8_t expected_hash[SHA256_DIGEST_LENGTH] = {
|
||||
0x60, 0x7e, 0x0a, 0x84, 0xc7, 0x59, 0x66, 0xb0,
|
||||
0x0f, 0x3d, 0x12, 0xfa, 0x83, 0x3e, 0x91, 0xd1,
|
||||
0x59, 0xe4, 0xf5, 0x1a, 0xc5, 0x1b, 0x6b, 0xa6,
|
||||
0x6f, 0x98, 0xd0, 0xc3, 0xcb, 0xef, 0xdc, 0xe0
|
||||
};
|
||||
static BOOL FindPatchOffset(LPCTSTR libcc_dll_path, DWORD Offset[5]) {
|
||||
Offset[0] = 0;
|
||||
Offset[1] = 0;
|
||||
Offset[2] = 0;
|
||||
Offset[3] = 0;
|
||||
Offset[4] = 0;
|
||||
|
||||
if (!Check_libcc_Hash(libcc_dll_path, expected_hash))
|
||||
HANDLE h_libcc = CreateFile(libcc_dll_path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (h_libcc == INVALID_HANDLE_VALUE) {
|
||||
_tprintf_s(TEXT("Failed to open libcc.dll. CODE: 0x%08x @[FindPatchOffset -> CreateFile]\r\n"), GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// DWORD is enough, you know libcc.dll cannot be larger than 4GB
|
||||
DWORD libcc_size = GetFileSize(h_libcc, nullptr);
|
||||
HANDLE h_libcc_map = CreateFileMapping(h_libcc, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
if (h_libcc_map == NULL) {
|
||||
_tprintf_s(TEXT("Failed to create mapping for libcc.dll. CODE: 0x%08x @[FindPatchOffset -> CreateFileMapping]\r\n"), GetLastError());
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const uint8_t* libcc = reinterpret_cast<const uint8_t*>(MapViewOfFile(h_libcc_map, FILE_MAP_READ, 0, 0, 0));
|
||||
if (libcc == nullptr) {
|
||||
_tprintf_s(TEXT("Failed to map libcc.dll. CODE: 0x%08x @[FindPatchOffset -> MapViewOfFile]\r\n"), GetLastError());
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const IMAGE_DOS_HEADER* libcc_dos_header = reinterpret_cast<const IMAGE_DOS_HEADER*>(libcc);
|
||||
|
||||
// check dos signature
|
||||
if (libcc_dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
_tprintf_s(TEXT("libcc.dll does not have a valid DOS header. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const IMAGE_NT_HEADERS* libcc_nt_header = reinterpret_cast<const IMAGE_NT_HEADERS*>(libcc + libcc_dos_header->e_lfanew);
|
||||
|
||||
// check nt signature
|
||||
if (libcc_nt_header->Signature != IMAGE_NT_SIGNATURE) {
|
||||
_tprintf_s(TEXT("libcc.dll does not have a valid NT header. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// check if a dll
|
||||
if ((libcc_nt_header->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
|
||||
_tprintf_s(TEXT("libcc.dll is not a DLL file. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// check if 32-bits or 64-bits
|
||||
#if defined(_M_X64)
|
||||
if (libcc_nt_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 || libcc_nt_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
_tprintf_s(TEXT("libcc.dll is not a 64-bits DLL file. @[FindPatchOffset]\r\n"));
|
||||
#elif defined(_M_IX86)
|
||||
if (libcc_nt_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 || libcc_nt_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
#else
|
||||
#error "unknown arch"
|
||||
#endif
|
||||
_tprintf_s(TEXT("libcc.dll is not a 32-bits DLL file. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WORD section_num = libcc_nt_header->FileHeader.NumberOfSections;
|
||||
const IMAGE_SECTION_HEADER* libcc_section_headers = reinterpret_cast<const IMAGE_SECTION_HEADER*>(
|
||||
libcc + libcc_dos_header->e_lfanew + sizeof(libcc_nt_header->Signature) + sizeof(libcc_nt_header->FileHeader) + libcc_nt_header->FileHeader.SizeOfOptionalHeader
|
||||
);
|
||||
|
||||
const IMAGE_SECTION_HEADER* rdata_section = nullptr;
|
||||
for (WORD i = 0; i < section_num; ++i) {
|
||||
if (*reinterpret_cast<const uint64_t*>(libcc_section_headers[i].Name) == 0x61746164722e) { // b'\x00\x00atadr.'
|
||||
rdata_section = libcc_section_headers + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rdata_section == nullptr) {
|
||||
_tprintf_s(TEXT(".rdata section is not found. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const IMAGE_SECTION_HEADER* text_section = nullptr;
|
||||
for (WORD i = 0; i < section_num; ++i) {
|
||||
if (*reinterpret_cast<const uint64_t*>(libcc_section_headers[i].Name) == 0x747865742e) { // b'\x00\x00\x00txet.'
|
||||
text_section = libcc_section_headers + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (text_section == nullptr) {
|
||||
_tprintf_s(TEXT(".text section is not found. @[FindPatchOffset]\r\n"));
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// search offset[0]
|
||||
{
|
||||
const uint8_t keyword[] = "D75125B70767B94145B47C1CB3C0755E";
|
||||
const uint8_t* start = libcc + rdata_section->PointerToRawData;
|
||||
DWORD section_size = rdata_section->SizeOfRawData;
|
||||
for (DWORD i = 0; i < section_size; ++i) {
|
||||
if (start[i] == keyword[0]) {
|
||||
bool found = true;
|
||||
for (DWORD j = 1; j < sizeof(keyword) - 1; ++j)
|
||||
if (start[i + j] != keyword[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
Offset[0] = rdata_section->PointerToRawData + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search offset[2]
|
||||
{
|
||||
const uint8_t keyword[] = "E1CED09B9C2186BF71A70C0FE2F1E0AE";
|
||||
const uint8_t* start = libcc + rdata_section->PointerToRawData;
|
||||
DWORD section_size = rdata_section->SizeOfRawData;
|
||||
for (DWORD i = 0; i < section_size; ++i) {
|
||||
if (start[i] == keyword[0]) {
|
||||
bool found = true;
|
||||
for (DWORD j = 1; j < sizeof(keyword) - 1; ++j)
|
||||
if (start[i + j] != keyword[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
Offset[2] = rdata_section->PointerToRawData + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search offset[4]
|
||||
{
|
||||
const uint8_t keyword[] = "92933";
|
||||
const uint8_t* start = libcc + rdata_section->PointerToRawData;
|
||||
DWORD section_size = rdata_section->SizeOfRawData;
|
||||
for (DWORD i = 0; i < section_size; ++i) {
|
||||
if (start[i] == keyword[0]) {
|
||||
bool found = true;
|
||||
for (DWORD j = 1; j < sizeof(keyword) - 1; ++j)
|
||||
if (start[i + j] != keyword[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
Offset[4] = rdata_section->PointerToRawData + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search offset[1]
|
||||
{
|
||||
const uint8_t keyword[] = { 0xfe, 0xea, 0xbc, 0x01 };
|
||||
const uint8_t* start = libcc + text_section->PointerToRawData;
|
||||
DWORD section_size = text_section->SizeOfRawData;
|
||||
for (DWORD i = 0; i < section_size; ++i) {
|
||||
if (start[i] == keyword[0]) {
|
||||
bool found = true;
|
||||
for (DWORD j = 1; j < sizeof(keyword); ++j)
|
||||
if (start[i + j] != keyword[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
Offset[1] = text_section->PointerToRawData + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search offset[3]
|
||||
{
|
||||
const uint8_t keyword[] = { 0x59, 0x08, 0x01, 0x00 };
|
||||
const uint8_t* start = libcc + text_section->PointerToRawData;
|
||||
DWORD section_size = text_section->SizeOfRawData;
|
||||
for (DWORD i = 0; i < section_size; ++i) {
|
||||
if (start[i] == keyword[0]) {
|
||||
bool found = true;
|
||||
for (DWORD j = 1; j < sizeof(keyword); ++j)
|
||||
if (start[i + j] != keyword[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
Offset[3] = text_section->PointerToRawData + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnmapViewOfFile(libcc);
|
||||
CloseHandle(h_libcc_map);
|
||||
CloseHandle(h_libcc);
|
||||
|
||||
if (Offset[0] == 0 || Offset[1] == 0 || Offset[2] == 0 || Offset[3] == 0 || Offset[4] == 0) {
|
||||
_tprintf_s(TEXT("Failed to find all patch offset. Is libcc.dll from official? Or you've patched?\r\n"));
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Do(LPCTSTR libcc_dll_path, LPCTSTR prepared_key_file) {
|
||||
// uint8_t expected_hash[SHA256_DIGEST_LENGTH] = {
|
||||
// 0x60, 0x7e, 0x0a, 0x84, 0xc7, 0x59, 0x66, 0xb0,
|
||||
// 0x0f, 0x3d, 0x12, 0xfa, 0x83, 0x3e, 0x91, 0xd1,
|
||||
// 0x59, 0xe4, 0xf5, 0x1a, 0xc5, 0x1b, 0x6b, 0xa6,
|
||||
// 0x6f, 0x98, 0xd0, 0xc3, 0xcb, 0xef, 0xdc, 0xe0
|
||||
// };
|
||||
//
|
||||
// if (!Check_libcc_Hash(libcc_dll_path, expected_hash))
|
||||
// return FALSE;
|
||||
|
||||
DWORD Patch_Offset[5];
|
||||
if (!FindPatchOffset(libcc_dll_path, Patch_Offset))
|
||||
return FALSE;
|
||||
|
||||
|
||||
|
||||
if (!BackupFile(libcc_dll_path))
|
||||
return FALSE;
|
||||
|
||||
RSA* PrivateKey;
|
||||
RSA* PrivateKey = nullptr;
|
||||
if (prepared_key_file != nullptr) {
|
||||
PrivateKey = ReadRSAPrivateKeyFromFile(prepared_key_file);
|
||||
if (PrivateKey == nullptr)
|
||||
return FALSE;
|
||||
|
||||
if (!CheckRSAKeyIsAppropriate(PrivateKey)) {
|
||||
_tprintf_s(TEXT("The key is not appropriate to use. @[patcher::Solution1::Do -> CheckRSAKeyIsAppropriate]\r\n"));
|
||||
RSA_free(PrivateKey);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
PrivateKey = GenerateAppropriateRSAKey();
|
||||
if (PrivateKey == nullptr)
|
||||
@@ -92,12 +334,6 @@ namespace patcher::Solution1 {
|
||||
uint32_t imm1 = std::stoul(encrypted_pem_pubkey1.c_str());
|
||||
uint32_t imm3 = std::stoul(encrypted_pem_pubkey3.c_str());
|
||||
|
||||
uint32_t patch_offset0 = 0x1A12090;
|
||||
uint32_t patch_offset1 = 0x59D799;
|
||||
uint32_t patch_offset2 = 0x1A11DA0;
|
||||
uint32_t patch_offset3 = 0x59D77F;
|
||||
uint32_t patch_offset4 = 0x1A11D8C;
|
||||
|
||||
HANDLE hFile = CreateFile(libcc_dll_path, GENERIC_WRITE, NULL, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
_tprintf_s(TEXT("Failed to open libcc.dll. CODE: 0x%08x @[patcher::Solution1::Do -> CreateFile]\r\n"), GetLastError());
|
||||
@@ -105,70 +341,90 @@ namespace patcher::Solution1 {
|
||||
}
|
||||
|
||||
// start patch 0
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, patch_offset0, nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("----------Start to do patch 0----------\r\n"));
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, Patch_Offset[0], nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("Failed to set file pointer. CODE: 0x%08x @[patcher::Solution1::Do -> SetFilePointer]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("At offset +0x%08x, write:\r\n\"%hs\"\r\n"), Patch_Offset[0], encrypted_pem_pubkey0.c_str());
|
||||
if (FALSE == WriteFile(hFile, encrypted_pem_pubkey0.c_str(), encrypted_pem_pubkey0.length(), nullptr, nullptr)) {
|
||||
_tprintf_s(TEXT("Failed to write patch 0. CODE: 0x%08x @[patcher::Solution1::Do -> WriteFile]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("----------patch 0 done----------\r\n"));
|
||||
|
||||
// start patch 1
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, patch_offset1, nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("----------Start to do patch 1----------\r\n"));
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, Patch_Offset[1], nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("Failed to set file pointer. CODE: 0x%08x @[patcher::Solution1::Do -> SetFilePointer]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("At offset +0x%08x, write immediate value %d (type: uint32_t)\r\n"), Patch_Offset[1], imm1);
|
||||
if (FALSE == WriteFile(hFile, &imm1, sizeof(imm1), nullptr, nullptr)) {
|
||||
_tprintf_s(TEXT("Failed to write patch 1. CODE: 0x%08x @[patcher::Solution1::Do -> WriteFile]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("----------patch 1 done----------\r\n"));
|
||||
|
||||
// start patch 2
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, patch_offset2, nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("----------Start to do patch 2----------\r\n"));
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, Patch_Offset[2], nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("Failed to set file pointer. CODE: 0x%08x @[patcher::Solution1::Do -> SetFilePointer]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("At offset +0x%08x, write:\r\n\"%hs\"\r\n"), Patch_Offset[2], encrypted_pem_pubkey2.c_str());
|
||||
if (FALSE == WriteFile(hFile, encrypted_pem_pubkey2.c_str(), encrypted_pem_pubkey2.length(), nullptr, nullptr)) {
|
||||
_tprintf_s(TEXT("Failed to write patch 2. CODE: 0x%08x @[patcher::Solution1::Do -> WriteFile]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("----------patch 2 done----------\r\n"));
|
||||
|
||||
// start patch 3
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, patch_offset3, nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("----------Start to do patch 3----------\r\n"));
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, Patch_Offset[3], nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("Failed to set file pointer. CODE: 0x%08x @[patcher::Solution1::Do -> SetFilePointer]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("At offset +0x%08x, write immediate value %d (type: uint32_t)\r\n"), Patch_Offset[3], imm3);
|
||||
if (FALSE == WriteFile(hFile, &imm3, sizeof(imm3), nullptr, nullptr)) {
|
||||
_tprintf_s(TEXT("Failed to write patch 3. CODE: 0x%08x @[patcher::Solution1::Do -> WriteFile]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("----------patch 3 done----------\r\n"));
|
||||
|
||||
// start patch 4
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, patch_offset4, nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("----------Start to do patch 4----------\r\n"));
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, Patch_Offset[4], nullptr, FILE_BEGIN)) {
|
||||
_tprintf_s(TEXT("Failed to set file pointer. CODE: 0x%08x @[patcher::Solution1::Do -> SetFilePointer]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("At offset +0x%08x, write:\r\n\"%hs\"\r\n"), Patch_Offset[4], encrypted_pem_pubkey4.c_str());
|
||||
if (FALSE == WriteFile(hFile, encrypted_pem_pubkey4.c_str(), encrypted_pem_pubkey4.length(), nullptr, nullptr)) {
|
||||
_tprintf_s(TEXT("Failed to write patch 4. CODE: 0x%08x @[patcher::Solution1::Do -> WriteFile]\r\n"), GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_tprintf_s(TEXT("----------patch 4 done----------\r\n"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,9 @@ int _tmain(int argc, TCHAR* argv[]) {
|
||||
BOOL status;
|
||||
if (NavicatMajorVersion <= 0x000C0000 && NavicatMinorVersion < 0x00190000) { // for navicat ver < 12.0.25
|
||||
status = patcher::Solution0::Do(navicat_exe_path.c_str());
|
||||
} else if (NavicatMajorVersion == 0x000C0000 && NavicatMinorVersion == 0x00190000) { // for navicat ver == 12.0.25
|
||||
} else if (NavicatMajorVersion == 0x000C0000 && NavicatMinorVersion == 0x00190000) { // for navicat ver = 12.0.25
|
||||
status = patcher::Solution1::Do(libcc_dll_path.c_str(), argc == 3 ? argv[2] : nullptr);
|
||||
} else if (NavicatMajorVersion == 0x000C0000 && NavicatMinorVersion == 0x001A0000) { // for navicat ver = 12.0.26
|
||||
status = patcher::Solution1::Do(libcc_dll_path.c_str(), argc == 3 ? argv[2] : nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace patcher {
|
||||
char* GetPEMText(RSA* PrivateKey);
|
||||
|
||||
namespace Solution0 {
|
||||
BOOL Do(LPCTSTR navicat_exe_path);
|
||||
BOOL Do(LPCTSTR navicat_exe_path, LPCTSTR prepared_key_file = nullptr);
|
||||
}
|
||||
|
||||
namespace Solution1 {
|
||||
|
||||
Reference in New Issue
Block a user