123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- #include <tchar.h>
- #include <windows.h>
- #include "Exception.hpp"
- #include "ExceptionSystem.hpp"
- #include "FileManipulation.hpp"
- #include "PatchSolution.hpp"
- #undef __BASE_FILE__
- #define __BASE_FILE__ TEXT("_tmain.cpp")
- #define PRINT_MESSAGE_LITERAL(m) _putts(TEXT(m))
- #define PRINT_PTSTR(m) _putts(m)
- #define PRINT_PCSTR(m) puts(m)
- #define PRINT_PCWSTR(m) _putws(m)
- static void Welcome() {
- _putts(TEXT("***************************************************"));
- _putts(TEXT("* Navicat Patcher by @DoubleLabyrinth *"));
- _putts(TEXT("* Version: 3.2 *"));
- _putts(TEXT("***************************************************"));
- _putts(TEXT(""));
- _putts(TEXT("Press Enter to continue or Ctrl + C to abort."));
- _gettchar();
- }
- static void Help() {
- _putts(TEXT("Usage:"));
- _putts(TEXT(" navicat-patcher.exe <Navicat Installation Path> [RSA-2048 PEM File Path]"));
- _putts(TEXT(""));
- _putts(TEXT(" <Navicat Installation Path> The folder path where Navicat is installed."));
- _putts(TEXT(" This parameter must be specified."));
- _putts(TEXT(""));
- _putts(TEXT(" [RSA-2048 PEM File Path] The path to an RSA-2048 private key file."));
- _putts(TEXT(" This parameter is optional."));
- _putts(TEXT(" If not specified, an RSA-2048 private key file"));
- _putts(TEXT(" named \"RegPrivateKey.pem\" will be generated."));
- _putts(TEXT(""));
- _putts(TEXT("Example:"));
- _putts(TEXT(" navicat-patcher.exe \"C:\\Program Files\\PremiumSoft\\Navicat Premium 12\""));
- }
- static void BackupFile(const TString& From, const TString& To) {
- if (::CopyFile(From.c_str(), To.c_str(), TRUE) == FALSE)
- throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
- TEXT("CopyFile failed."));
- }
- static void LoadKey(RSACipher* pCipher, PTSTR pKeyFileName,
- PatchSolution* pSolution0,
- PatchSolution* pSolution1,
- PatchSolution* pSolution2,
- PatchSolution* pSolution3) {
- if (pKeyFileName) {
- _tprintf_s(TEXT("[*] Import RSA-2048 key from file %s\n"), pKeyFileName);
- pCipher->ImportKeyFromFile<RSAKeyType::PrivateKey, RSAKeyFormat::PEM>(TStringEncode(pKeyFileName, CP_UTF8));
- if (pSolution0 && !pSolution0->CheckKey(pCipher) ||
- pSolution1 && !pSolution1->CheckKey(pCipher) ||
- pSolution2 && !pSolution2->CheckKey(pCipher) ||
- pSolution3 && !pSolution3->CheckKey(pCipher))
- throw Exception(__BASE_FILE__, __LINE__,
- TEXT("The RSA private key you provide cannot be used."));
- } else {
- _putts(TEXT("[*] Generating new RSA private key, it may take a long time."));
- do {
- pCipher->GenerateKey(2048);
- } while (pSolution0 && !pSolution0->CheckKey(pCipher) ||
- pSolution1 && !pSolution1->CheckKey(pCipher) ||
- pSolution2 && !pSolution2->CheckKey(pCipher) ||
- pSolution3 && !pSolution3->CheckKey(pCipher)); // re-generate RSA key if one of 'CheckKey's return false
- pCipher->ExportKeyToFile<RSAKeyType::PrivateKey, RSAKeyFormat::NotSpecified>("RegPrivateKey.pem");
- _putts(TEXT("[*] New RSA-2048 private key has been saved to RegPrivateKey.pem."));
- }
- std::string PublicKeyString = pCipher->ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
- _putts(TEXT("[*] Your RSA public key:"));
- printf_s("\n%s\n", PublicKeyString.c_str());
- }
- static void ExceptionReport(const Exception& e) noexcept {
- _tprintf_s(TEXT("[*] ERROR: %s\n"), e.Message().c_str());
- _tprintf_s(TEXT(" | - File: %s\n"), e.File().c_str());
- _tprintf_s(TEXT(" | - Line: %zu\n"), e.Line());
- if (e.HasErrorCode()) {
- _tprintf_s(TEXT(" | - ErrorCode: 0x%.8zx\n"), e.ErrorCode());
- _tprintf_s(TEXT(" | - ErrorString: %s\n"), e.ErrorString().c_str());
- }
- if (e.Hints().size() != 0) {
- _putts(TEXT(" | - Hints:"));
- for (auto& Hint : e.Hints())
- _tprintf_s(TEXT(" | %s\n"), Hint.c_str());
- }
- _putts(TEXT(""));
- }
- int _tmain(int argc, PTSTR argv[]) {
- if (argc != 2 && argc != 3) {
- Help();
- return 0;
- }
- Welcome();
- TString InstallationPath;
- TString MainExeName;
- TString LibccDllName;
- ResourceObject<CppObjectTraits<RSACipher>> pCipher;
- ResourceObject<CppObjectTraits<FileObject>> MainExe;
- ResourceObject<CppObjectTraits<FileMapViewObject>> MainExeMapper;
- ResourceObject<CppObjectTraits<FileObject>> LibccDll;
- ResourceObject<CppObjectTraits<FileMapViewObject>> LibccDllMapper;
- ResourceObject<CppObjectTraits<PatchSolution>> pSolution0;
- ResourceObject<CppObjectTraits<PatchSolution>> pSolution1;
- ResourceObject<CppObjectTraits<PatchSolution>> pSolution2;
- ResourceObject<CppObjectTraits<PatchSolution>> pSolution3;
- try {
- DWORD Attribute = GetFileAttributes(argv[1]);
- if (Attribute == INVALID_FILE_ATTRIBUTES)
- throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
- TEXT("GetFileAttributes failed."));
- if ((Attribute & FILE_ATTRIBUTE_DIRECTORY) == 0)
- throw Exception(__BASE_FILE__, __LINE__,
- TEXT("Path does not point to a directory."));
- InstallationPath = argv[1];
- if (InstallationPath.back() != TEXT('\\') && InstallationPath.back() != TEXT('/'))
- InstallationPath.push_back(TEXT('/')); // for Linux compatible
- } catch (Exception& e) {
- e.Hints().emplace_back(TEXT("Are you sure the path you specified is correct?"));
- e.Hints().emplace_back(TEXT("The path you specified:"));
- e.Hints().emplace_back(argv[1]);
- ExceptionReport(e);
- return -1;
- }
- pCipher.TakeOver(new RSACipher());
-
- // -----------------
- // Map files
- // -----------------
- do {
- try {
- _tprintf_s(TEXT("[*] Try to open libcc.dll ...... "));
- LibccDll.TakeOver(FileObject::Open<FileObject*>(InstallationPath + TEXT("libcc.dll"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ));
- LibccDllMapper.TakeOver(FileMapViewObject::Create<FileMapViewObject*>(LibccDll->GetHandle(),
- PAGE_READWRITE));
- LibccDllMapper->Map(FILE_MAP_READ | FILE_MAP_WRITE);
- LibccDllName = TEXT("libcc.dll");
- _tprintf_s(TEXT("Succeeded\n"));
- break;
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_NOT_FOUND) {
- _tprintf_s(TEXT("Not found\n"));
- LibccDllMapper.Release();
- LibccDll.Release();
- } else {
- _tprintf_s(TEXT("Failed\n"));
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_ACCESS_DENIED)
- e.Hints().emplace_back(TEXT("Please re-run with Administrator privilege."));
- ExceptionReport(e);
- return -1;
- }
- }
- try {
- _tprintf_s(TEXT("[*] Try to open Navicat.exe ...... "));
- MainExe.TakeOver(FileObject::Open<FileObject*>(InstallationPath + TEXT("Navicat.exe"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ));
- MainExeMapper.TakeOver(FileMapViewObject::Create<FileMapViewObject*>(MainExe->GetHandle(),
- PAGE_READWRITE));
- MainExeMapper->Map(FILE_MAP_READ | FILE_MAP_WRITE);
- MainExeName = TEXT("Navicat.exe");
- _tprintf_s(TEXT("Succeeded\n"));
- break;
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_NOT_FOUND) {
- _tprintf_s(TEXT("Not found\n"));
- MainExeMapper.Release();
- MainExe.Release();
- } else {
- _tprintf_s(TEXT("Failed\n"));
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_ACCESS_DENIED)
- e.Hints().emplace_back(TEXT("Please re-run with Administrator privilege."));
- ExceptionReport(e);
- return -1;
- }
- }
- try {
- _tprintf_s(TEXT("[*] Try to open Modeler.exe ...... "));
- MainExe.TakeOver(FileObject::Open<FileObject*>(InstallationPath + TEXT("Modeler.exe"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ));
- MainExeMapper.TakeOver(FileMapViewObject::Create<FileMapViewObject*>(MainExe->GetHandle(),
- PAGE_READWRITE));
- MainExeMapper->Map(FILE_MAP_READ | FILE_MAP_WRITE);
- MainExeName = TEXT("Modeler.exe");
- _tprintf_s(TEXT("Succeeded\n"));
- break;
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_NOT_FOUND) {
- _tprintf_s(TEXT("Not found\n"));
- MainExeMapper.Release();
- MainExe.Release();
- } else {
- _tprintf_s(TEXT("Failed\n"));
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_ACCESS_DENIED)
- e.Hints().emplace_back(TEXT("Please re-run with Administrator privilege."));
- ExceptionReport(e);
- return -1;
- }
- }
- try {
- _tprintf_s(TEXT("[*] Try to open Rviewer.exe ...... "));
- MainExe.TakeOver(FileObject::Open<FileObject*>(InstallationPath + TEXT("Rviewer.exe"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ));
- MainExeMapper.TakeOver(FileMapViewObject::Create<FileMapViewObject*>(MainExe->GetHandle(),
- PAGE_READWRITE));
- MainExeMapper->Map(FILE_MAP_READ | FILE_MAP_WRITE);
- MainExeName = TEXT("Rviewer.exe");
- _tprintf_s(TEXT("Succeeded\n"));
- break;
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_NOT_FOUND) {
- _tprintf_s(TEXT("Not found\n"));
- MainExeMapper.Release();
- MainExe.Release();
- } else {
- _tprintf_s(TEXT("Failed\n"));
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_ACCESS_DENIED)
- e.Hints().emplace_back(TEXT("Please re-run with Administrator privilege."));
- ExceptionReport(e);
- return -1;
- }
- }
- ExceptionReport(Exception(__BASE_FILE__, __LINE__,
- TEXT("None of target files has been found."),
- TEXT("Are you sure the path you specified is correct?"),
- TEXT("The path you specified:"),
- argv[1]));
- return -1;
- } while (false);
- // -----------
- // decide PatchSolutions
- // -----------
- if (MainExeMapper.IsValid()) {
- try {
- pSolution0.TakeOver(new PatchSolution0());
- pSolution0->SetFile(MainExeMapper->View<void>());
- if (pSolution0->FindPatchOffset() == false) {
- _putts(TEXT("[*] PatchSolution0 ...... Omitted"));
- pSolution0.Release();
- }
- } catch (Exception& e) {
- ExceptionReport(e);
- return -1;
- }
- } else {
- _putts(TEXT("[*] PatchSolution0 ...... Omitted"));
- }
- if (LibccDllMapper.IsValid()) {
- try {
- pSolution1.TakeOver(new PatchSolution1());
- pSolution2.TakeOver(new PatchSolution2());
- pSolution3.TakeOver(new PatchSolution3());
- pSolution1->SetFile(LibccDllMapper->View<void>());
- pSolution2->SetFile(LibccDllMapper->View<void>());
- pSolution3->SetFile(LibccDllMapper->View<void>());
- if (pSolution1->FindPatchOffset() == false) {
- _putts(TEXT("[*] PatchSolution1 ...... Omitted"));
- pSolution1.Release();
- }
- if (pSolution2->FindPatchOffset() == false) {
- _putts(TEXT("[*] PatchSolution2 ...... Omitted"));
- pSolution2.Release();
- }
- if (pSolution3->FindPatchOffset() == false) {
- _putts(TEXT("[*] PatchSolution3 ...... Omitted"));
- pSolution3.Release();
- }
- } catch (Exception& e) {
- ExceptionReport(e);
- return -1;
- }
- } else {
- _putts(TEXT("[*] PatchSolution1 ...... Omitted"));
- _putts(TEXT("[*] PatchSolution2 ...... Omitted"));
- _putts(TEXT("[*] PatchSolution3 ...... Omitted"));
- }
- if (pSolution0.IsValid() == false) {
- MainExeMapper.Release();
- MainExe.Release();
- }
- if (pSolution1.IsValid() == false && pSolution2.IsValid() == false && pSolution3.IsValid() == false) {
- LibccDllMapper.Release();
- LibccDll.Release();
- }
- if (pSolution0.IsValid() == false &&
- pSolution1.IsValid() == false &&
- pSolution2.IsValid() == false &&
- pSolution3.IsValid() == false)
- {
- ExceptionReport(Exception(__BASE_FILE__, __LINE__,
- TEXT("Cannot find Navicat official RSA public key."),
- TEXT("Are you sure your Navicat has not been patched/modified before?")));
- return -1;
- }
- // -------------
- // LoadKey
- // -------------
- try {
- LoadKey(pCipher,
- argc == 3 ? argv[2] : nullptr,
- pSolution0,
- pSolution1,
- pSolution2,
- pSolution3);
- } catch (Exception& e) {
- ExceptionReport(e);
- return -1;
- }
- // -------------
- // BackupFile
- // -------------
- try {
- if (MainExe.IsValid())
- BackupFile(InstallationPath + MainExeName,
- InstallationPath + MainExeName + TEXT(".backup"));
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_EXISTS) {
- e.Hints().emplace_back(TStringFormat(TEXT("The backup of %s has been found."),
- MainExeName.c_str()));
- e.Hints().emplace_back(TStringFormat(TEXT("Please remove %s.backup in Navicat installation folder if you're sure %s has not been patched."),
- MainExeName.c_str(),
- MainExeName.c_str()));
- e.Hints().emplace_back(TStringFormat(TEXT("Otherwise please restore %s by %s.backup and remove %s.backup then try again."),
- MainExeName.c_str(),
- MainExeName.c_str(),
- MainExeName.c_str()));
- }
- ExceptionReport(e);
- return -1;
- }
- try {
- if (LibccDll.IsValid())
- BackupFile(InstallationPath + LibccDllName,
- InstallationPath + LibccDllName + TEXT(".backup"));
- } catch (Exception& e) {
- if (e.HasErrorCode() && e.ErrorCode() == ERROR_FILE_EXISTS) {
- e.Hints().emplace_back(TStringFormat(TEXT("The backup of %s has been found."),
- LibccDllName.c_str()));
- e.Hints().emplace_back(TStringFormat(TEXT("Please remove %s.backup in Navicat installation folder if you're sure %s has not been patched."),
- LibccDllName.c_str(),
- LibccDllName.c_str()));
- e.Hints().emplace_back(TStringFormat(TEXT("Otherwise please restore %s by %s.backup and remove %s.backup then try again."),
- LibccDllName.c_str(),
- LibccDllName.c_str(),
- LibccDllName.c_str()));
- }
- ExceptionReport(e);
- return -1;
- }
- // -------------
- // MakePatch
- // -------------
- try {
- if (pSolution0.IsValid()) {
- pSolution0->MakePatch(pCipher);
- _putts(TEXT(""));
- }
- if (pSolution1.IsValid()) {
- pSolution1->MakePatch(pCipher);
- _putts(TEXT(""));
- }
- if (pSolution2.IsValid()) {
- pSolution2->MakePatch(pCipher);
- _putts(TEXT(""));
- }
- if (pSolution3.IsValid()) {
- pSolution3->MakePatch(pCipher);
- _putts(TEXT(""));
- }
- } catch (Exception& e) {
- ExceptionReport(e);
- return -1;
- }
- _putts(TEXT("[*] Patch has been done successfully."));
- _putts(TEXT("[*] Have fun and enjoy~"));
- return 0;
- }
|