// NavicatCrackerDlg.cpp: 实现文件 // #include "pch.h" #include "framework.h" #include "NavicatCracker.h" #include "NavicatCrackerDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #define NKG_CURRENT_SOURCE_FILE() u8".\\Navicat-Cracker\\NavicatCrackerDlg.cpp" #define NKG_CURRENT_SOURCE_LINE() __LINE__ void select_patch_solutions (nkg::resource_wrapper>& solution0) { return; } void load_rsa_privkey(nkg::rsa_cipher& cipher, std::filesystem::path& rsa_privkey_filepath, nkg::patch_solution* solution0) { if (!rsa_privkey_filepath.empty()) { cipher.import_private_key_file(rsa_privkey_filepath); if (solution0 && !solution0->check_rsa_privkey(cipher)) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"The RSA private key you provide cannot be used."); } } else { do { cipher.generate_key(2048); } while (solution0 && !solution0->check_rsa_privkey(cipher)); // re-generate RSA key if one of `check_rsa_privkey` returns false } } template bool all_patch_solutions_are_suppressed(args_t&&... args) { return (!args.is_valid() && ...); } void detect_backup(const std::filesystem::path& file_path) { std::filesystem::path backup_path = file_path.native() + L".bak"; if (std::filesystem::is_regular_file(backup_path)) { while (true) { wprintf_s(L"[*] Previous backup %s is detected. Delete? (y/n)", backup_path.native().c_str()); auto select = getwchar(); while (select != L'\n' && getwchar() != L'\n') {} if (select == L'Y' || select == L'y') { std::filesystem::remove(backup_path); break; } else if (select == TEXT('N') || select == TEXT('n')) { throw nkg::exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Backup file still exists. Patch abort!"); } else { continue; } } } } void make_backup(const std::filesystem::path& file_path) { std::filesystem::path backup_path = file_path.native() + L".bak"; if (std::filesystem::exists(backup_path)) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Previous backup is detected.") .push_hint(fmt::format(u8"Please delete {} and try again.", nkg::cp_converter<-1, CP_UTF8>::convert(backup_path.native()))); } else { std::filesystem::copy_file(file_path, backup_path); } } CNavicatCrackerDlg::CNavicatCrackerDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_NavicatCracker_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CNavicatCrackerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_ActivationCode, m_actcode); DDX_Control(pDX, IDC_CopyBTN, m_copy); DDX_Control(pDX, IDC_GenActBTN, m_genact); DDX_Control(pDX, IDC_GenerateBTN, m_genkey); DDX_Control(pDX, IDC_InstallPath, m_path); DDX_Control(pDX, IDC_Key, m_key); DDX_Control(pDX, IDC_LanguageBox, m_lang); DDX_Control(pDX, IDC_Organ, m_org); DDX_Control(pDX, IDC_PatchBTN, m_patch); DDX_Control(pDX, IDC_InstallPath, m_path); DDX_Control(pDX, IDC_ProductionBox, m_product); DDX_Control(pDX, IDC_RequestCode, m_reqcode); DDX_Control(pDX, IDC_UserName, m_name); DDX_Control(pDX, IDC_VersionBox, m_ver); DDX_Control(pDX, IDC_KeyFile, m_keyfile); DDX_Control(pDX, IDC_OpenKeyBTN, m_open); DDX_Control(pDX, IDC_CheckKey, m_checkkey); DDX_Control(pDX, IDC_ADVANCE, m_checkadv); DDX_Control(pDX, IDC_LangHex1, m_langhex1); DDX_Control(pDX, IDC_LangHex2, m_langhex2); DDX_Control(pDX, IDC_ProdHex, m_prodhex); DDX_Control(pDX, IDC_hosts, m_hosts); DDX_Control(pDX, IDC_Logo, m_logo); } BEGIN_MESSAGE_MAP(CNavicatCrackerDlg, CDialogEx) ON_BN_CLICKED(IDC_PatchBTN, &CNavicatCrackerDlg::OnClickedPatchbtn) ON_BN_CLICKED(IDC_GenerateBTN, &CNavicatCrackerDlg::OnClickedGeneratebtn) ON_BN_CLICKED(IDC_GenActBTN, &CNavicatCrackerDlg::OnClickedGenActbtn) ON_BN_CLICKED(IDC_CopyBTN, &CNavicatCrackerDlg::OnClickedCopybtn) ON_BN_CLICKED(IDC_CheckKey, &CNavicatCrackerDlg::OnClickedCheckKey) ON_BN_CLICKED(IDC_OpenKeyBTN, &CNavicatCrackerDlg::OnClickedOpenKeybtn) ON_BN_CLICKED(IDC_OpenPath, &CNavicatCrackerDlg::OnBnClickedOpenpath) ON_BN_CLICKED(IDC_ADVANCE, &CNavicatCrackerDlg::OnBnClickedAdvance) ON_BN_CLICKED(IDC_About, &CNavicatCrackerDlg::OnBnClickedAbout) ON_BN_CLICKED(IDC_hosts, &CNavicatCrackerDlg::OnBnClickedhosts) END_MESSAGE_MAP() // CNavicatCrackerDlg 消息处理程序 BOOL CNavicatCrackerDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != nullptr) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 ShowWindow(SW_NORMAL); // 初始化代码 m_ver.SetCurSel(0); m_product.SetCurSel(1); m_lang.SetCurSel(1); m_path.SetWindowTextW(defaultpath); m_name.SetWindowTextW(username); m_org.SetWindowTextW(organization); m_keyfile.SetWindowTextW(keyfile); // setup logo png CBitmap bitmap_logo; CPngImage png_image; png_image.Load(IDB_PNG1, nullptr); bitmap_logo.Attach(png_image.Detach()); m_logo.SetBitmap(bitmap_logo); m_hosts.SetCheck(TRUE); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CNavicatCrackerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CNavicatCrackerDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } void CNavicatCrackerDlg::OnClickedPatchbtn() { CString pathData; m_path.GetWindowTextW(pathData); // patcher navicat_install_path = pathData.GetString(); try { if (!std::filesystem::is_directory(navicat_install_path)) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Navicat install path doesn't point to a directory.") .push_hint(u8"Are you sure the path you specified is correct?") .push_hint(fmt::format(u8"The path you specified: {}", nkg::cp_converter<-1, CP_UTF8>::convert(navicat_install_path.native()))); } std::filesystem::path libcc_filepath = navicat_install_path / "libcc.dll"; nkg::resource_wrapper libcc_handle{ nkg::resource_traits::win32::file_handle{} }; nkg::resource_wrapper libcc_map_handle{ nkg::resource_traits::win32::generic_handle{} }; nkg::resource_wrapper libcc_map_view{ nkg::resource_traits::win32::map_view_ptr{} }; std::optional libcc_interpreter; nkg::resource_wrapper solution0{ nkg::resource_traits::cxx_object_traits{} }; // open libcc.dll libcc_handle.set(CreateFileW(libcc_filepath.native().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)); if (!libcc_handle.is_valid()) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Try to open libcc.dll ... NOT FOUND!"); } else { throw nkg::exceptions::win32_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), u8"Failed to open libcc.dll"); } } if (libcc_handle.is_valid()) { libcc_map_handle.set(CreateFileMapping(libcc_handle.get(), NULL, PAGE_READWRITE, 0, 0, NULL)); if (!libcc_map_handle.is_valid()) { throw nkg::exceptions::win32_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), u8"CreateFileMapping failed."); } libcc_map_view.set(MapViewOfFile(libcc_map_handle.get(), FILE_MAP_ALL_ACCESS, 0, 0, 0)); if (!libcc_map_view.is_valid()) { throw nkg::exceptions::win32_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), u8"MapViewOfFile failed."); } libcc_interpreter = nkg::image_interpreter::parse(libcc_map_view.get(), true); solution0.set(new nkg::patch_solution_since<16, 0, 7, 0>(libcc_interpreter.value())); } // find patch and decide which solution will be applied if (solution0.is_valid()) { auto patch_found = solution0->find_patch(); if (!patch_found) { solution0.release(); } } select_patch_solutions(solution0); if (all_patch_solutions_are_suppressed(solution0)) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"All patch solutions are suppressed. Patch abort!") .push_hint(u8"Are you sure your navicat has not been patched/modified before?"); } // load key if (m_checkkey.GetCheck()) { CString cs_keypath{}; m_keyfile.GetWindowTextW(cs_keypath); rsa_privkey_filepath = cs_keypath.GetString(); if (!PathFileExists(rsa_privkey_filepath.c_str())) { m_checkkey.SetCheck(FALSE); OnClickedCheckKey(); rsa_privkey_filepath.clear(); } } load_rsa_privkey(cipher, rsa_privkey_filepath, solution0.get()); // detecting backups if (solution0.is_valid()) { detect_backup(libcc_filepath); } // make backup if (solution0.is_valid()) { make_backup(libcc_filepath); } // make patch // no way to go back from here :-) if (solution0.is_valid()) { solution0->make_patch(cipher); } // patch hosts if (m_hosts.GetCheck()) { LPCWSTR lpshosts = _T("C:\\Windows\\System32\\drivers\\etc\\hosts"); SetFileAttributesW(lpshosts, GetFileAttributes(lpshosts) & ~FILE_ATTRIBUTE_READONLY); CStdioFile hosts; if (hosts.Open(lpshosts, CFile::modeWrite)) { hosts.SeekToEnd(); hosts.WriteString(_T("127.0.0.1\tactivate.navicat.com\n")); } else { AfxMessageBox(L"Can't modify HOSTS file!\nPlease check your permission!", MB_ICONSTOP); } hosts.Close(); } // private key export if (!m_checkkey.GetCheck()) { if(AfxMessageBox(L"Patch Success Applied to libcc.dll!\nDO You Want to Export Private Key?", MB_ICONINFORMATION | MB_YESNOCANCEL) == IDYES){ cipher.export_private_key_file(u8"Navicat_2048bit_rsa_private_key.pem"); } } else { AfxMessageBox(L"Patch Success Applied to libcc.dll!\n", MB_ICONINFORMATION | MB_OK); } PATCH = TRUE; } catch (nkg::exception& e) { catched_message.Format(L"[-] %s:%d ->\n", nkg::cp_converter::convert(e.source_file()).c_str(), e.source_line()); catched_message.AppendFormat(L" %s\n", nkg::cp_converter::convert(e.custom_message()).c_str()); if (e.error_code_exists()) { catched_message.AppendFormat(L" %s (0x%zx)\n", nkg::cp_converter::convert(e.error_string()).c_str(), e.error_code()); } for (auto& hint : e.hints()) { catched_message.AppendFormat(L" HINT: %s\n", nkg::cp_converter::convert(hint).c_str()); } AfxMessageBox(catched_message, MB_ICONSTOP); } catch (std::exception& e) { catched_message.Format(L"[-] %s\n", nkg::cp_converter::convert(e.what()).c_str()); AfxMessageBox(catched_message, MB_ICONSTOP); } } void CNavicatCrackerDlg::OnClickedGeneratebtn() { int verData; CString strData; verData = 16 - m_ver.GetCurSel(); try { if (!m_checkadv.GetCheck()) { int proData = m_product.GetCurSel(); int langData = m_lang.GetCurSel(); lpfnCollectInformation = nkg::CollectInformationNormal; sn_generator = lpfnCollectInformation(proData, langData, verData); } else { CString temp; std::uint8_t prod, lang1, lang2; m_prodhex.GetWindowTextW(temp); prod = static_cast(std::stoul(temp.GetString(), nullptr, 16)); m_langhex1.GetWindowTextW(temp); lang1 = static_cast(std::stoul(temp.GetString(), nullptr, 16)); m_langhex2.GetWindowTextW(temp); lang2 = static_cast(std::stoul(temp.GetString(), nullptr, 16)); sn_generator = nkg::CollectInformationAdvanced(prod, lang1, lang2, verData); } sn_generator.generate(); m_key.SetWindowTextW(nkg::cp_converter::convert(sn_generator.serial_number_formatted()).c_str()); KEYGEN = TRUE; } catch (nkg::exception& e) { catched_message.Format(L"[-] %s:%d ->\n", nkg::cp_converter::convert(e.source_file()).c_str(), e.source_line()); catched_message.AppendFormat(L" %s\n", nkg::cp_converter::convert(e.custom_message()).c_str()); if (e.error_code_exists()) { catched_message.AppendFormat(L" %s (0x%zx)\n", nkg::cp_converter::convert(e.error_string()).c_str(), e.error_code()); } for (auto& hint : e.hints()) { catched_message.AppendFormat(L" HINT: %s\n", nkg::cp_converter::convert(hint).c_str()); } AfxMessageBox(catched_message, MB_ICONSTOP); } catch (std::exception& e) { catched_message.Format(L"[-] %s\n", nkg::cp_converter::convert(e.what()).c_str()); if (m_checkadv.GetCheck()) { catched_message.AppendFormat(L"In ADV mode Production should be 0x00~0xFF.\n"); catched_message.AppendFormat(L"In ADV mode Language(each part) should be 0x00~0xFF."); } AfxMessageBox(catched_message, MB_ICONSTOP); } catched_message.Empty(); } void CNavicatCrackerDlg::OnClickedGenActbtn() { try { if (!PATCH) { if (!m_checkkey.GetCheck()) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Can't Generate Activation Code.") .push_hint(u8"Please Patch first Or Specified RSA private key."); } else { CString private_path; m_keyfile.GetWindowTextW(private_path); cipher.import_private_key_file(nkg::cp_converter<-1, CP_UTF8>::convert(private_path.GetString())); } } if (!KEYGEN) { throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Can't Generate Activation Code.") .push_hint(u8"Please Generate a key!"); } lpfnGenerateLicense = nkg::GenerateLicenseText; m_name.GetWindowTextW(username); m_org.GetWindowTextW(organization); m_reqcode.GetWindowTextW(reqcode); actcode = lpfnGenerateLicense(cipher, sn_generator, username.GetString(), organization.GetString(), reqcode.GetString()).c_str(); m_actcode.SetWindowTextW(actcode); } catch (nkg::exception& e) { catched_message.Format(L"[-] %s:%d ->\n", nkg::cp_converter::convert(e.source_file()).c_str(), e.source_line()); catched_message.AppendFormat(L" %s\n", nkg::cp_converter::convert(e.custom_message()).c_str()); if (e.error_code_exists()) { catched_message.AppendFormat(L" %s (0x%zx)\n", nkg::cp_converter::convert(e.error_string()).c_str(), e.error_code()); } for (auto& hint : e.hints()) { catched_message.AppendFormat(L" HINT: %s\n", nkg::cp_converter::convert(hint).c_str()); } AfxMessageBox(catched_message, MB_ICONSTOP); } catch (std::exception& e) { catched_message.Format(L"[-] %s\n", nkg::cp_converter::convert(e.what()).c_str()); AfxMessageBox(catched_message, MB_ICONSTOP); } catched_message.Empty(); } void CNavicatCrackerDlg::OnClickedCopybtn() { CString source; m_key.GetWindowTextW(source); if (OpenClipboard()) { //防止非ASCII语言复制到剪切板为乱码 int buff_size = source.GetLength(); CStringW strWide = CStringW(source); int nLen = strWide.GetLength(); HANDLE clipbuffer = ::GlobalAlloc(GMEM_MOVEABLE, (nLen + 1) * 2); if (!clipbuffer) { ::CloseClipboard(); return; } char* buffer = (char*)::GlobalLock(clipbuffer); if (buffer != 0) { memset(buffer, 0, (static_cast(nLen) + 1) * 2); memcpy_s(buffer, nLen * 2, strWide.GetBuffer(0), nLen * 2); strWide.ReleaseBuffer(); ::GlobalUnlock(clipbuffer); ::EmptyClipboard(); ::SetClipboardData(CF_UNICODETEXT, clipbuffer); ::CloseClipboard(); } else { ::CloseClipboard(); return; } } } void CNavicatCrackerDlg::OnClickedCheckKey() { if (m_checkkey.GetCheck()) { m_keyfile.EnableWindow(); m_open.EnableWindow(); } else { m_keyfile.EnableWindow(0); m_open.EnableWindow(0); } } void CNavicatCrackerDlg::OnClickedOpenKeybtn() { CFileDialog openFileDlg(FALSE, L".", L"PrivateKey.pem", OFN_HIDEREADONLY | OFN_READONLY, L"Private Key (*.pem)|*.pem||", NULL); INT_PTR result = openFileDlg.DoModal(); if (result == IDOK) { m_keyfile.SetWindowTextW(openFileDlg.GetPathName()); } // 失焦解决方法:"https://kira-96.github.io/" 一些基本没什么用的MFC技巧 ::SetForegroundWindow(::GetDesktopWindow()); this->SetForegroundWindow(); } void CNavicatCrackerDlg::OnBnClickedOpenpath() { CFolderPickerDialog openFolderDlg; openFolderDlg.m_ofn.lpstrTitle = L"Choose The Navicat Installation Path:"; openFolderDlg.m_ofn.lpstrInitialDir = L"."; INT_PTR result = openFolderDlg.DoModal(); if (result == IDOK) { m_path.SetWindowTextW(openFolderDlg.GetPathName()); } ::SetForegroundWindow(::GetDesktopWindow()); this->SetForegroundWindow(); } void CNavicatCrackerDlg::OnBnClickedAdvance() { if (m_checkadv.GetCheck()) { m_lang.ShowWindow(SW_HIDE); m_product.ShowWindow(SW_HIDE); m_prodhex.ShowWindow(SW_SHOW); m_langhex1.ShowWindow(SW_SHOW); m_langhex2.ShowWindow(SW_SHOW); } else { m_lang.ShowWindow(SW_SHOW); m_product.ShowWindow(SW_SHOW); m_prodhex.ShowWindow(SW_HIDE); m_langhex1.ShowWindow(SW_HIDE); m_langhex2.ShowWindow(SW_HIDE); } } void CNavicatCrackerDlg::OnBnClickedAbout() { AfxMessageBox(L"Author : tgMrZ\nBased on DoubleSine's work\n\n\nDoubleSine yyds!!!", MB_OK | MB_ICONQUESTION); } void CNavicatCrackerDlg::OnBnClickedhosts() { if (m_hosts.GetCheck()) { AfxMessageBox(L"Please make sure you have permission to modify HOSTS file!"); } }