Relax requirement for RSA private key in PatchSolution1

This commit is contained in:
Double Sine
2019-01-19 16:12:58 +08:00
parent d14695a524
commit acd61f1822
2 changed files with 176 additions and 107 deletions
+27 -9
View File
@@ -22,8 +22,8 @@
class PatchSolution{
public:
virtual void SetFile(FileMapper* pLibccFile) = 0;
virtual bool CheckKey(RSACipher* pCipher) const = 0;
virtual bool FindPatchOffset() noexcept = 0;
virtual bool CheckKey(RSACipher* pCipher) const = 0;
virtual void MakePatch(RSACipher* pCipher) const = 0;
virtual ~PatchSolution() {}
};
@@ -58,17 +58,35 @@ public:
virtual void MakePatch(RSACipher* cipher) const override;
};
// PatchSolution1 will replace the RSA public key stored in libcc.dll
// PatchSolution1, 2, 3 will replace the RSA public key stored in libcc.dll
class PatchSolution1 : public PatchSolution {
private:
static const char* Keywords[5];
static const size_t KeywordsLength[5];
enum KeywordDataType {
IMM_DATA,
STRING_DATA
};
struct KeywordInfo {
const char* PtrToData;
size_t Length;
KeywordDataType Type;
};
struct PatchPointInfo {
uint8_t* PtrToPatch;
size_t PatchSize;
size_t MaxPatchSize;
};
static constexpr size_t KeywordsCount = 5;
static const KeywordInfo Keywords[KeywordsCount];
ImageInterpreter _TargetFile;
off_t PatchOffsets[5];
mutable PatchPointInfo _Patches[KeywordsCount];
public:
PatchSolution1() :
PatchOffsets{ -1, -1, -1, -1, -1 } {}
PatchSolution1() : _Patches{ } {}
virtual void SetFile(FileMapper* pLibccFile) override {
if (!_TargetFile.ParseImage(pLibccFile->GetView<PVOID>(), true)) {
@@ -77,11 +95,11 @@ public:
}
}
virtual bool CheckKey(RSACipher* cipher) const override;
virtual bool CheckKey(RSACipher* pCipher) const override;
virtual bool FindPatchOffset() noexcept override;
virtual void MakePatch(RSACipher* cipher) const override;
virtual void MakePatch(RSACipher* pCipher) const override;
};
class PatchSolution2 : public PatchSolution {
+149 -98
View File
@@ -5,15 +5,24 @@
#undef __BASE_FILE__
#define __BASE_FILE__ "PatchSolution1.cpp"
const char* PatchSolution1::Keywords[5] = {
const PatchSolution1::KeywordInfo PatchSolution1::Keywords[5] = {
{
"D75125B70767B94145B47C1CB3C0755E"
"7CCB8825C5DCE0C58ACF944E08280140"
"9A02472FAFFD1CD77864BB821AE36766"
"FEEDE6A24F12662954168BFA314BD950"
"32B9D82445355ED7BC0B880887D650F5",
160,
STRING_DATA
},
{
"\xfe\xea\xbc\x01",
4,
IMM_DATA
},
{
"E1CED09B9C2186BF71A70C0FE2F1E0AE"
"F3BD6B75277AAB20DFAF3D110F75912B"
"FB63AC50EC4C48689D1502715243A79F"
@@ -38,23 +47,24 @@ const char* PatchSolution1::Keywords[5] = {
"460F41ACF997C30E7C3AF025FA171B5F"
"5AD4D6B15E95C27F6B35AD61875E5505"
"449B4E",
742,
STRING_DATA
},
{
"\x59\x08\x01\x00",
"92933"
};
const size_t PatchSolution1::KeywordsLength[5] = {
160,
4,
742,
4,
5
4,
IMM_DATA
},
{
"92933",
5,
STRING_DATA
}
};
bool PatchSolution1::CheckKey(RSACipher* cipher) const {
BOOL bOk = FALSE;
std::string RSAPublicKeyPEM =
cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
Helper::ReplaceSubString(RSAPublicKeyPEM, "\n", "\r\n");
@@ -64,202 +74,243 @@ bool PatchSolution1::CheckKey(RSACipher* cipher) const {
if (EncryptedPem.length() != 920)
return false;
if (EncryptedPem[160] > '9' || EncryptedPem[160] < '1')
// we require the chars in [p1, p2) of EncryptedPem must be number chars
size_t p1, p2;
p1 = _Patches[0].MaxPatchSize;
p2 = Keywords[0].Length + 8; // 8 = strlen("29158142")
if (p1 >= p2)
p1 = p2 - 1;
if (('1' <= EncryptedPem[p1] && EncryptedPem[p1] <= '9') == false)
return false;
for (int i = 1; i < 8; ++i)
if (EncryptedPem[160 + i] > '9' || EncryptedPem[160 + i] < '0')
for (size_t i = p1 + 1; i < p2; ++i)
if (('0' <= EncryptedPem[i] && EncryptedPem[i] <= '9') == false)
return false;
if (EncryptedPem[910] > '9' || EncryptedPem[910] < '1')
_Patches[0].PatchSize = p1;
p1 = Keywords[0].Length + 8 + _Patches[2].MaxPatchSize;
p2 = Keywords[0].Length + 8 + Keywords[2].Length + 5;
if (p1 >= p2)
p1 = p2 - 1;
if (('1' <= EncryptedPem[p1] && EncryptedPem[p1] <= '9') == false)
return false;
for (int i = 1; i < 5; ++i)
if (EncryptedPem[910 + i] > '9' || EncryptedPem[910 + i] < '0')
for (size_t i = p1 + 1; i < p2; ++i)
if (('0' <= EncryptedPem[i] && EncryptedPem[i] <= '9') == false)
return false;
_Patches[2].PatchSize = p1 - Keywords[0].Length - 8;
_Patches[4].PatchSize = Keywords[4].Length;
return true;
}
bool PatchSolution1::FindPatchOffset() noexcept {
PIMAGE_SECTION_HEADER textSectionHeader = _TargetFile.GetSectionHeader(".text");
PIMAGE_SECTION_HEADER rdataSectionHeader = _TargetFile.GetSectionHeader(".rdata");
uint8_t* PtrToSectiontext = _TargetFile.GetSectionView<uint8_t>(".text");
uint8_t* PtrToSectionrdata = _TargetFile.GetSectionView<uint8_t>(".rdata");
off_t Offsets[5] = { -1, -1, -1, -1, -1 };
PIMAGE_SECTION_HEADER SectionHeader_text = _TargetFile.GetSectionHeader(".text");
PIMAGE_SECTION_HEADER SectionHeader_rdata = _TargetFile.GetSectionHeader(".rdata");
uint8_t* PtrToSection_text = _TargetFile.GetSectionView<uint8_t>(".text");
uint8_t* PtrToSection_rdata = _TargetFile.GetSectionView<uint8_t>(".rdata");
PatchPointInfo TempPatches[KeywordsCount] = {};
if (textSectionHeader == nullptr)
if (SectionHeader_text == nullptr)
return false;
if (rdataSectionHeader == nullptr)
if (SectionHeader_rdata == nullptr)
return false;
// -------------------------
// try to search Keywords[0]
// -------------------------
for (DWORD i = 0; i < rdataSectionHeader->SizeOfRawData; ++i) {
if (memcmp(PtrToSectionrdata + i, Keywords[0], KeywordsLength[0]) == 0) {
Offsets[0] = rdataSectionHeader->PointerToRawData + i;
for (DWORD i = 0; i < SectionHeader_rdata->SizeOfRawData; ++i) {
if (memcmp(PtrToSection_rdata + i, Keywords[0].PtrToData, Keywords[0].Length) == 0) {
TempPatches[0].PtrToPatch = PtrToSection_rdata + i;
size_t j = Keywords[0].Length;
while (TempPatches[0].PtrToPatch[j] == 0)
++j;
TempPatches[0].MaxPatchSize = j - 1;
break;
}
}
if (Offsets[0] == -1)
if (TempPatches[0].PtrToPatch == nullptr)
return false;
// -------------------------
// try to search Keywords[2]
// -------------------------
for (DWORD i = 0; i < rdataSectionHeader->SizeOfRawData; ++i) {
if (memcmp(PtrToSectionrdata + i, Keywords[2], KeywordsLength[2]) == 0) {
Offsets[2] = rdataSectionHeader->PointerToRawData + i;
for (DWORD i = 0; i < SectionHeader_rdata->SizeOfRawData; ++i) {
if (memcmp(PtrToSection_rdata + i, Keywords[2].PtrToData, Keywords[2].Length) == 0) {
TempPatches[2].PtrToPatch = PtrToSection_rdata + i;
size_t j = Keywords[2].Length;
while (TempPatches[2].PtrToPatch[j] == 0)
++j;
TempPatches[2].MaxPatchSize = j - 1;
break;
}
}
if (Offsets[2] == -1)
if (TempPatches[2].PtrToPatch == nullptr)
return false;
// -------------------------
// try to search Keywords[4]
// -------------------------
for (DWORD i = 0; i < rdataSectionHeader->SizeOfRawData; ++i) {
if (memcmp(PtrToSectionrdata + i, Keywords[4], KeywordsLength[4]) == 0) {
Offsets[4] = rdataSectionHeader->PointerToRawData + i;
for (DWORD i = 0; i < SectionHeader_rdata->SizeOfRawData; ++i) {
if (memcmp(PtrToSection_rdata + i, Keywords[4].PtrToData, Keywords[4].Length) == 0) {
TempPatches[4].PtrToPatch = PtrToSection_rdata + i;
size_t j = Keywords[4].Length;
while (TempPatches[4].PtrToPatch[j] == 0)
++j;
TempPatches[4].MaxPatchSize = j - 1;
break;
}
}
if (Offsets[4] == -1)
if (TempPatches[4].PtrToPatch == nullptr)
return false;
// -------------------------
// try to search Keywords[1] and Keywords[3]
// -------------------------
for (DWORD i = 0; i < textSectionHeader->SizeOfRawData; ++i) {
if (memcmp(PtrToSectiontext + i, Keywords[1], KeywordsLength[1]) == 0) {
for (DWORD i = 0; i < SectionHeader_text->SizeOfRawData; ++i) {
if (memcmp(PtrToSection_text + i, Keywords[1].PtrToData, Keywords[1].Length) == 0) {
// Keywords[3] must be close to Keywords[1]
for (DWORD j = i - 64; j < i + 64; ++j) {
if (memcmp(PtrToSectiontext + j, Keywords[3], KeywordsLength[3]) == 0) {
Offsets[1] = textSectionHeader->PointerToRawData + i;
Offsets[3] = textSectionHeader->PointerToRawData + j;
if (memcmp(PtrToSection_text + j, Keywords[3].PtrToData, Keywords[3].Length) == 0) {
TempPatches[1].PtrToPatch = PtrToSection_text + i;
TempPatches[1].PatchSize = Keywords[1].Length;
TempPatches[1].MaxPatchSize = Keywords[1].Length;
TempPatches[3].PtrToPatch = PtrToSection_text + j;
TempPatches[3].PatchSize = Keywords[3].Length;
TempPatches[3].MaxPatchSize = Keywords[3].Length;
break;
}
}
// Offsets[1] and Offsets[3] are set synchronously
// so check Offsets[1] is enough
if (Offsets[1] != -1)
if (TempPatches[3].PtrToPatch)
break;
}
}
if (Offsets[1] == -1)
if (TempPatches[1].PtrToPatch == nullptr || TempPatches[3].PtrToPatch == nullptr)
return false;
PatchOffsets[0] = Offsets[0];
PatchOffsets[1] = Offsets[1];
PatchOffsets[2] = Offsets[2];
PatchOffsets[3] = Offsets[3];
PatchOffsets[4] = Offsets[4];
_tprintf_s(TEXT("MESSAGE: [PatchSolution1] Keywords[0] has been found: offset = +0x%08lx.\n"), PatchOffsets[0]);
_tprintf_s(TEXT("MESSAGE: [PatchSolution1] Keywords[1] has been found: offset = +0x%08lx.\n"), PatchOffsets[1]);
_tprintf_s(TEXT("MESSAGE: [PatchSolution1] Keywords[2] has been found: offset = +0x%08lx.\n"), PatchOffsets[2]);
_tprintf_s(TEXT("MESSAGE: [PatchSolution1] Keywords[3] has been found: offset = +0x%08lx.\n"), PatchOffsets[3]);
_tprintf_s(TEXT("MESSAGE: [PatchSolution1] Keywords[4] has been found: offset = +0x%08lx.\n"), PatchOffsets[4]);
for (size_t i = 0; i < KeywordsCount; ++i) {
_Patches[i] = TempPatches[i];
_tprintf_s(TEXT("MESSAGE: PatchSolution1: Keywords[%zu] has been found: offset = +0x%08llx.\n"),
i,
_Patches[i].PtrToPatch - _TargetFile.GetImageBaseView<uint8_t>());
}
return true;
}
void PatchSolution1::MakePatch(RSACipher* pCipher) const {
std::string PublicKeyPEM;
std::string EncryptedPEM;
uint8_t* pFileView = _TargetFile.GetImageBaseView<uint8_t>();
PublicKeyPEM =
std::string PublicKeyPEM =
pCipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
Helper::ReplaceSubString(PublicKeyPEM, "\n", "\r\n");
EncryptedPEM = Helper::NavicatCipher.EncryptString(PublicKeyPEM);
std::string EncryptedPEM = Helper::NavicatCipher.EncryptString(PublicKeyPEM);
// split encrypted_pem_pubkey to 5 part: |160 chars|8 chars|742 chars|5 chars|5 chars|
// | |
// \ / \ /
// ImmValue1 ImmValue3
std::string EncryptedPEM0(EncryptedPEM.begin(), EncryptedPEM.begin() + 160);
std::string EncryptedPEM1(EncryptedPEM.begin() + 160, EncryptedPEM.begin() + 160 + 8);
std::string EncryptedPEM2(EncryptedPEM.begin() + 160 + 8, EncryptedPEM.begin() + 160 + 8 + 742);
std::string EncryptedPEM3(EncryptedPEM.begin() + 160 + 8 + 742, EncryptedPEM.begin() + 160 + 8 + 742 + 5);
std::string EncryptedPEM4(EncryptedPEM.begin() + 160 + 8 + 742 + 5, EncryptedPEM.end());
size_t p0, p1, p2, p3, p4, p5;
p0 = 0;
p1 = p0 + _Patches[0].PatchSize;
p2 = Keywords[0].Length + 8;
p3 = p2 + _Patches[2].PatchSize;
p4 = Keywords[0].Length + 8 + Keywords[2].Length + 5;
p5 = 920;
std::string EncryptedPEM0(EncryptedPEM.begin() + p0, EncryptedPEM.begin() + p1);
std::string EncryptedPEM1(EncryptedPEM.begin() + p1, EncryptedPEM.begin() + p2);
std::string EncryptedPEM2(EncryptedPEM.begin() + p2, EncryptedPEM.begin() + p3);
std::string EncryptedPEM3(EncryptedPEM.begin() + p3, EncryptedPEM.begin() + p4);
std::string EncryptedPEM4(EncryptedPEM.begin() + p4, EncryptedPEM.begin() + p5);
uint32_t ImmValue1 = std::stoul(EncryptedPEM1.c_str());
uint32_t ImmValue3 = std::stoul(EncryptedPEM3.c_str());
// ----------------------------------
// process PatchOffsets[0]
// ----------------------------------
_tprintf_s(TEXT("@ +0x%08lx\nPrevious:\n"), PatchOffsets[0]);
Helper::PrintMemory(pFileView + PatchOffsets[0],
pFileView + PatchOffsets[0] + KeywordsLength[0],
_tprintf_s(TEXT("@ +0x%08zx\nPrevious:\n"), _Patches[0].PtrToPatch - pFileView);
Helper::PrintMemory(_Patches[0].PtrToPatch,
_Patches[0].PtrToPatch + _Patches[0].PatchSize,
pFileView);
memcpy(pFileView + PatchOffsets[0], EncryptedPEM0.c_str(), KeywordsLength[0]);
memcpy(_Patches[0].PtrToPatch, EncryptedPEM0.c_str(), _Patches[0].PatchSize);
_putts(TEXT("After:"));
Helper::PrintMemory(pFileView + PatchOffsets[0],
pFileView + PatchOffsets[0] + KeywordsLength[0],
Helper::PrintMemory(_Patches[0].PtrToPatch,
_Patches[0].PtrToPatch + _Patches[0].PatchSize,
pFileView);
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[1]
// ----------------------------------
_tprintf_s(TEXT("@ +0x%08lx\nPrevious:\n"), PatchOffsets[1]);
Helper::PrintMemory(pFileView + PatchOffsets[1],
pFileView + PatchOffsets[1] + KeywordsLength[1],
_tprintf_s(TEXT("@ +0x%08zx\nPrevious:\n"), _Patches[1].PtrToPatch - pFileView);
Helper::PrintMemory(_Patches[1].PtrToPatch,
_Patches[1].PtrToPatch + _Patches[1].PatchSize,
pFileView);
memcpy(pFileView + PatchOffsets[1], &ImmValue1, KeywordsLength[1]);
memcpy(_Patches[1].PtrToPatch, &ImmValue1, sizeof(uint32_t));
_putts(TEXT("After:"));
Helper::PrintMemory(pFileView + PatchOffsets[1],
pFileView + PatchOffsets[1] + KeywordsLength[1],
Helper::PrintMemory(_Patches[1].PtrToPatch,
_Patches[1].PtrToPatch + _Patches[1].PatchSize,
pFileView);
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[2]
// ----------------------------------
_tprintf_s(TEXT("@ +0x%08lx\nPrevious:\n"), PatchOffsets[2]);
Helper::PrintMemory(pFileView + PatchOffsets[2],
pFileView + PatchOffsets[2] + KeywordsLength[2],
_tprintf_s(TEXT("@ +0x%08zx\nPrevious:\n"), _Patches[2].PtrToPatch - pFileView);
Helper::PrintMemory(_Patches[2].PtrToPatch,
_Patches[2].PtrToPatch + _Patches[2].PatchSize,
pFileView);
memcpy(pFileView + PatchOffsets[2], EncryptedPEM2.c_str(), KeywordsLength[2]);
memcpy(_Patches[2].PtrToPatch, EncryptedPEM2.c_str(), _Patches[2].PatchSize);
_putts(TEXT("After:"));
Helper::PrintMemory(pFileView + PatchOffsets[2],
pFileView + PatchOffsets[2] + KeywordsLength[2],
Helper::PrintMemory(_Patches[2].PtrToPatch,
_Patches[2].PtrToPatch + _Patches[2].PatchSize,
pFileView);
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[3]
// ----------------------------------
_tprintf_s(TEXT("@ +0x%08lx\nPrevious:\n"), PatchOffsets[3]);
Helper::PrintMemory(pFileView + PatchOffsets[3],
pFileView + PatchOffsets[3] + KeywordsLength[3],
_tprintf_s(TEXT("@ +0x%08zx\nPrevious:\n"), _Patches[3].PtrToPatch - pFileView);
Helper::PrintMemory(_Patches[3].PtrToPatch,
_Patches[3].PtrToPatch + _Patches[3].PatchSize,
pFileView);
memcpy(pFileView + PatchOffsets[3], &ImmValue3, KeywordsLength[3]);
memcpy(_Patches[3].PtrToPatch, &ImmValue3, sizeof(uint32_t));
_putts(TEXT("After:"));
Helper::PrintMemory(pFileView + PatchOffsets[3],
pFileView + PatchOffsets[3] + KeywordsLength[3],
Helper::PrintMemory(_Patches[3].PtrToPatch,
_Patches[3].PtrToPatch + _Patches[3].PatchSize,
pFileView);
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[4]
// ----------------------------------
_tprintf_s(TEXT("@ +0x%08lx\nPrevious:\n"), PatchOffsets[4]);
Helper::PrintMemory(pFileView + PatchOffsets[4],
pFileView + PatchOffsets[4] + KeywordsLength[4],
_tprintf_s(TEXT("@ +0x%08zx\nPrevious:\n"), _Patches[4].PtrToPatch - pFileView);
Helper::PrintMemory(_Patches[4].PtrToPatch,
_Patches[4].PtrToPatch + _Patches[4].PatchSize,
pFileView);
memcpy(pFileView + PatchOffsets[4], EncryptedPEM4.c_str(), KeywordsLength[4]);
memcpy(_Patches[4].PtrToPatch, EncryptedPEM4.c_str(), _Patches[4].PatchSize);
_putts(TEXT("After:"));
Helper::PrintMemory(pFileView + PatchOffsets[4],
pFileView + PatchOffsets[4] + KeywordsLength[4],
Helper::PrintMemory(_Patches[4].PtrToPatch,
_Patches[4].PtrToPatch + _Patches[4].PatchSize,
pFileView);
_putts(TEXT(""));
}