navicat-keygen/navicat-patcher/Solution0.cpp
2018-09-22 11:59:59 +08:00

263 lines
9.2 KiB
C++

#include "def.hpp"
// The following APIs are in version.lib
// GetFileVersionInfoSize
// GetFileVersionInfo
// VerQueryValue
// #pragma comment(lib, "version.lib")
namespace Patcher {
const char Solution0::Keyword[461] =
"-----BEGIN PUBLIC KEY-----\r\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I\r\n"
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv\r\n"
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF\r\n"
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2\r\n"
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt\r\n"
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ\r\n"
"awIDAQAB\r\n"
"-----END PUBLIC KEY-----\r\n";
BOOL Solution0::SetPath(const std::Tstring& Path) {
DWORD Attr;
Attr = GetFileAttributes(Path.c_str());
if (Attr == INVALID_FILE_ATTRIBUTES) {
if (GetLastError() == ERROR_INVALID_NAME || GetLastError() == ERROR_FILE_NOT_FOUND)
REPORT_ERROR("ERROR: Invalid path. Are you sure the path you specified is correct?");
else
REPORT_ERROR_WITH_CODE("ERROR: GetFileAttributes failed.", GetLastError());
return FALSE;
}
if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
REPORT_ERROR("ERROR: Path is not a directory.");
return FALSE;
}
ReleaseFile();
InstallationPath = Path;
if (InstallationPath.back() != TEXT('\\') && InstallationPath.back() != TEXT('/'))
InstallationPath.push_back(TEXT('/')); // for Linux compatible
return TRUE;
}
// Solution0 does not have any requirements for RSA-2048 key
BOOL Solution0::CheckKey(RSACipher* cipher) const {
return TRUE;
}
DWORD Solution0::TryFile(const std::Tstring& Name) {
std::Tstring MainAppFullName = InstallationPath + Name;
HANDLE hFile;
hFile = CreateFile(MainAppFullName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
nullptr, // default SA
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
ReleaseFile();
MainAppHandle = hFile;
MainAppName = Name;
return ERROR_SUCCESS;
}
DWORD Solution0::MapFile() {
DWORD dwLastError = ERROR_SUCCESS;
HANDLE hMapping = NULL;
PVOID lpMapView = nullptr;
hMapping = CreateFileMapping(MainAppHandle,
nullptr, // default SA
PAGE_READWRITE,
0, 0, // map all
nullptr); // we don't need a name
if (hMapping == NULL) {
dwLastError = GetLastError();
goto ON_Solution0_MapFile_ERROR;
}
lpMapView = MapViewOfFile(hMapping,
FILE_MAP_READ | FILE_MAP_WRITE,
0, 0, 0); // map all
if (lpMapView == nullptr) {
dwLastError = GetLastError();
goto ON_Solution0_MapFile_ERROR;
}
ReleaseMap();
MainAppMappingView = lpMapView;
lpMapView = nullptr;
MainAppMappingHandle = hMapping;
hMapping = NULL;
ON_Solution0_MapFile_ERROR:
if (hMapping)
CloseHandle(hMapping);
return dwLastError;
}
BOOL Solution0::FindPatchOffset() {
BOOL bFound = FALSE;
DWORD dwFileSize = 0;
uint8_t* lpFileContent = reinterpret_cast<uint8_t*>(MainAppMappingView);
dwFileSize = GetFileSize(MainAppHandle, nullptr);
for (DWORD i = 0; i < dwFileSize; ++i) {
if (memcmp(lpFileContent + i, Keyword, KeywordLength) == 0) {
PatchOffset = i;
bFound = TRUE;
break;
}
}
if (bFound)
_tprintf_s(TEXT("MESSAGE: [Solution0] Keyword has been found: offset = +0x%08lx.\n"), PatchOffset);
return bFound;
}
DWORD Solution0::BackupFile() {
std::Tstring TargetFileFullName = InstallationPath + MainAppName;
std::Tstring BackupFileFullName = InstallationPath + MainAppName + TEXT(".backup");
if (!CopyFile(TargetFileFullName.c_str(), BackupFileFullName.c_str(), TRUE))
return GetLastError();
else
return ERROR_SUCCESS;
}
BOOL Solution0::MakePatch(RSACipher* cipher) {
BOOL bSuccess = FALSE;
uint8_t* lpFileContent = reinterpret_cast<uint8_t*>(MainAppMappingView);
std::string RSAPublicKeyPEM;
RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
if (RSAPublicKeyPEM.empty()) {
REPORT_ERROR("ERROR: cipher->ExportKeyString failed.");
goto ON_Do_ERROR;
}
// lambda function, replace '\n' to '\r\n'
[](std::string& str, const std::string& OldSub, const std::string& NewSub) {
std::string::size_type pos = 0;
std::string::size_type srclen = OldSub.size();
std::string::size_type dstlen = NewSub.size();
while ((pos = str.find(OldSub, pos)) != std::string::npos) {
str.replace(pos, srclen, NewSub);
pos += dstlen;
}
} (RSAPublicKeyPEM, "\n", "\r\n");
if (RSAPublicKeyPEM.length() != KeywordLength) {
REPORT_ERROR("ERROR: Public key length does not match.");
goto ON_Do_ERROR;
}
_tprintf_s(TEXT("@%s+0x%08X\nPrevious:\n"), MainAppName.c_str(), PatchOffset);
Helper::PrintMemory(lpFileContent + PatchOffset,
lpFileContent + PatchOffset + KeywordLength,
lpFileContent);
memcpy(lpFileContent + PatchOffset, RSAPublicKeyPEM.c_str(), KeywordLength);
PRINT_MESSAGE("After:");
Helper::PrintMemory(lpFileContent + PatchOffset,
lpFileContent + PatchOffset + KeywordLength,
lpFileContent);
PRINT_MESSAGE("");
bSuccess = TRUE;
ON_Do_ERROR:
return bSuccess;
}
// DWORD Solution0::GetMainAppVersion(LPDWORD lpMajorVer, LPDWORD lpMinorVer) {
// BOOL bSuccess = FALSE;
// DWORD dwLastError = ERROR_SUCCESS;
// std::Tstring TargetFileFullName = InstallationPath + MainAppName;
//
// DWORD dwSize = 0;
// PVOID lpData = NULL;
// VS_FIXEDFILEINFO* lpVersionInfo = NULL;
// UINT VersionInfoSize = 0;
//
// dwSize = GetFileVersionInfoSize(TargetFileFullName.c_str(),
// &dwSize); // MSDN doesn't say it can be NULL.
// // so I use dwSize to receive this deprecated value
// if (dwSize == 0) {
// dwLastError = GetLastError();
// REPORT_ERROR_WITH_CODE("ERROR: GetFileVersionInfoSize failed.", dwLastError);
// goto ON_Solution0_GetMainAppVersion_ERROR;
// }
//
// lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
// if (lpData == nullptr) {
// dwLastError = GetLastError();
// REPORT_ERROR_WITH_CODE("ERROR: HeapAlloc failed.", dwLastError);
// goto ON_Solution0_GetMainAppVersion_ERROR;
// }
//
// if (!GetFileVersionInfo(TargetFileFullName.c_str(), NULL, dwSize, lpData)) {
// dwLastError = GetLastError();
// REPORT_ERROR_WITH_CODE("ERROR: GetFileVersionInfo failed.", dwLastError);
// goto ON_Solution0_GetMainAppVersion_ERROR;
// }
//
// if (!VerQueryValue(lpData, TEXT("\\"), reinterpret_cast<LPVOID*>(&lpVersionInfo), &VersionInfoSize)) {
// dwLastError = GetLastError();
// REPORT_ERROR_WITH_CODE("ERROR: VerQueryValue failed.", dwLastError);
// goto ON_Solution0_GetMainAppVersion_ERROR;
// }
//
// *lpMajorVer = lpVersionInfo->dwProductVersionMS;
// *lpMinorVer = lpVersionInfo->dwProductVersionLS;
//
// bSuccess = TRUE;
// ON_Solution0_GetMainAppVersion_ERROR:
// if (lpData)
// HeapFree(GetProcessHeap(), NULL, lpData);
// return bSuccess;
// }
const std::Tstring& Solution0::GetMainAppName() {
return MainAppName;
}
void Solution0::ReleaseFile() {
ReleaseMap();
if (MainAppHandle != INVALID_HANDLE_VALUE && MainAppHandle) {
CloseHandle(MainAppHandle);
MainAppHandle = INVALID_HANDLE_VALUE;
}
}
void Solution0::ReleaseMap() {
if (MainAppMappingView) {
UnmapViewOfFile(MainAppMappingView);
MainAppMappingView = nullptr;
}
if (MainAppMappingHandle) {
CloseHandle(MainAppMappingHandle);
MainAppMappingHandle = NULL;
}
}
Solution0::~Solution0() {
ReleaseFile();
}
}