PatchSolution.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #pragma once
  2. #include "FileMapper.hpp"
  3. #include "RSACipher.hpp"
  4. #include <capstone/capstone.h>
  5. #include "ExceptionCapstone.hpp"
  6. #include "ResourceGuardCapstone.hpp"
  7. #include "ImageInterpreter.hpp"
  8. // lib required by capstone
  9. #pragma comment(lib, "legacy_stdio_definitions.lib")
  10. #if defined(_M_AMD64)
  11. #pragma comment(lib, "capstone_static.lib")
  12. #else
  13. #pragma comment(lib, "capstone.lib")
  14. #endif
  15. #undef __BASE_FILE__
  16. #define __BASE_FILE__ "PatchSolution.hpp"
  17. class PatchSolution{
  18. public:
  19. virtual void SetFile(FileMapper* pLibccFile) = 0;
  20. virtual bool CheckKey(RSACipher* pCipher) const = 0;
  21. virtual bool FindPatchOffset() noexcept = 0;
  22. virtual void MakePatch(RSACipher* pCipher) const = 0;
  23. virtual ~PatchSolution() {}
  24. };
  25. // PatchSolution0 will replace the RSA public key stored in main application.
  26. class PatchSolution0 : public PatchSolution {
  27. private:
  28. static const char Keyword[461];
  29. static constexpr size_t KeywordLength = 460;
  30. ImageInterpreter _TargetFile;
  31. off_t PatchOffset;
  32. public:
  33. PatchSolution0() :
  34. PatchOffset(-1) {}
  35. virtual void SetFile(FileMapper* pMainApp) override {
  36. if (!_TargetFile.ParseImage(pMainApp->GetView<PVOID>(), true)) {
  37. throw Exception(__BASE_FILE__, __LINE__,
  38. "Invalid PE file.");
  39. }
  40. }
  41. virtual bool CheckKey(RSACipher* pCipher) const override;
  42. // Return true if found, other return false
  43. virtual bool FindPatchOffset() noexcept override;
  44. // Make a patch based on an RSA private key given
  45. // Return true if success, otherwise return false
  46. virtual void MakePatch(RSACipher* cipher) const override;
  47. };
  48. // PatchSolution1 will replace the RSA public key stored in libcc.dll
  49. class PatchSolution1 : public PatchSolution {
  50. private:
  51. static const char* Keywords[5];
  52. static const size_t KeywordsLength[5];
  53. ImageInterpreter _TargetFile;
  54. off_t PatchOffsets[5];
  55. public:
  56. PatchSolution1() :
  57. PatchOffsets{ -1, -1, -1, -1, -1 } {}
  58. virtual void SetFile(FileMapper* pLibccFile) override {
  59. if (!_TargetFile.ParseImage(pLibccFile->GetView<PVOID>(), true)) {
  60. throw Exception(__BASE_FILE__, __LINE__,
  61. "Invalid PE file.");
  62. }
  63. }
  64. virtual bool CheckKey(RSACipher* cipher) const override;
  65. virtual bool FindPatchOffset() noexcept override;
  66. virtual void MakePatch(RSACipher* cipher) const override;
  67. };
  68. class PatchSolution2 : public PatchSolution {
  69. private:
  70. static constexpr size_t KeywordsCount = 0x188;
  71. static const char KeywordsMeta[KeywordsCount + 1];
  72. static uint8_t Keywords[KeywordsCount][5];
  73. ImageInterpreter _TargetFile;
  74. off_t PatchOffsets[KeywordsCount];
  75. void BuildKeywords() noexcept;
  76. public:
  77. PatchSolution2() {
  78. memset(PatchOffsets, -1, sizeof(PatchOffsets));
  79. }
  80. virtual void SetFile(FileMapper* pLibccFile) override {
  81. if (!_TargetFile.ParseImage(pLibccFile->GetView<PVOID>(), true)) {
  82. throw Exception(__BASE_FILE__, __LINE__,
  83. "Invalid PE file.");
  84. }
  85. }
  86. virtual bool CheckKey(RSACipher* pCipher) const override;
  87. virtual bool FindPatchOffset() noexcept override;
  88. virtual void MakePatch(RSACipher* pCipher) const override;
  89. };
  90. class PatchSolution3 : public PatchSolution {
  91. private:
  92. enum KeywordDataType {
  93. IMM_DATA,
  94. STRING_DATA,
  95. };
  96. struct KeywordType {
  97. uint8_t Data[8];
  98. size_t Length;
  99. KeywordDataType Type;
  100. bool NotRecommendedToModify;
  101. };
  102. struct BranchContext {
  103. const uint8_t* PtrOfCode;
  104. size_t SizeOfCode;
  105. #if defined(_M_AMD64)
  106. uint64_t Rip;
  107. #elif defined(_M_IX86)
  108. uint64_t Eip;
  109. #else
  110. #error "Unknown architecture."
  111. #endif
  112. };
  113. struct PatchPointInfo {
  114. uint8_t* PtrToRelativeCode;
  115. uint64_t RelativeCodeRVA;
  116. uint8_t* PtrToPatch;
  117. size_t PatchSize;
  118. char* PtrToOriginalString;
  119. char* PtrToReplaceString;
  120. };
  121. static constexpr size_t KeywordsCount = 111;
  122. static const KeywordType Keywords[KeywordsCount];
  123. ResourceGuard<CapstoneHandleTraits> _CapstoneHandle;
  124. ImageInterpreter _TargetFile;
  125. mutable PatchPointInfo _Patches[KeywordsCount];
  126. bool CheckIfMatchPattern(cs_insn* PtrToInstruction) const;
  127. bool CheckIfFound(cs_insn* PtrToInstruction,
  128. size_t i) const;
  129. PatchPointInfo CreatePatchPoint(const uint8_t* PtrToCode,
  130. cs_insn* PtrToInstruction,
  131. size_t i) const;
  132. BranchContext GetJumpedBranch(const BranchContext& NotJumpedBranch,
  133. cs_insn* PtrToJmpInstruction) const;
  134. BranchContext HandleJcc(const BranchContext& NotJumpedBranch,
  135. const BranchContext& JumpedBranch,
  136. size_t i) const;
  137. public:
  138. PatchSolution3();
  139. virtual void SetFile(FileMapper* pLibccFile) override {
  140. if (!_TargetFile.ParseImage(pLibccFile->GetView<PVOID>())) {
  141. throw Exception(__BASE_FILE__, __LINE__,
  142. "Invalid PE file.");
  143. }
  144. }
  145. virtual bool FindPatchOffset() noexcept override;
  146. virtual bool CheckKey(RSACipher* pCipher) const override;
  147. virtual void MakePatch(RSACipher* pCipher) const override;
  148. virtual ~PatchSolution3() = default;
  149. };