PatchSolution1.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "PatchSolutions.hpp"
  2. #include "NavicatCrypto.hpp"
  3. #undef NKG_CURRENT_SOURCE_FILE
  4. #undef NKG_CURRENT_SOURCE_LINE
  5. #define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution1.cpp")
  6. #define NKG_CURRENT_SOURCE_LINE() __LINE__
  7. namespace nkg {
  8. static Navicat11Crypto g_NavicatCipher = Navicat11Crypto("23970790", 8);
  9. const char PatchSolution1::Keyword0[160 + 1] =
  10. "D75125B70767B94145B47C1CB3C0755E"
  11. "7CCB8825C5DCE0C58ACF944E08280140"
  12. "9A02472FAFFD1CD77864BB821AE36766"
  13. "FEEDE6A24F12662954168BFA314BD950"
  14. "32B9D82445355ED7BC0B880887D650F5";
  15. const char PatchSolution1::Keyword1[4 + 1] =
  16. "\xfe\xea\xbc\x01";
  17. const char PatchSolution1::Keyword2[742 + 1] =
  18. "E1CED09B9C2186BF71A70C0FE2F1E0AE"
  19. "F3BD6B75277AAB20DFAF3D110F75912B"
  20. "FB63AC50EC4C48689D1502715243A79F"
  21. "39FF2DE2BF15CE438FF885745ED54573"
  22. "850E8A9F40EE2FF505EB7476F95ADB78"
  23. "3B28CA374FAC4632892AB82FB3BF4715"
  24. "FCFE6E82D03731FC3762B6AAC3DF1C3B"
  25. "C646FE9CD3C62663A97EE72DB932A301"
  26. "312B4A7633100C8CC357262C39A2B3A6"
  27. "4B224F5276D5EDBDF0804DC3AC4B8351"
  28. "62BB1969EAEBADC43D2511D6E0239287"
  29. "81B167A48273B953378D3D2080CC0677"
  30. "7E8A2364F0234B81064C5C739A8DA28D"
  31. "C5889072BF37685CBC94C2D31D0179AD"
  32. "86D8E3AA8090D4F0B281BE37E0143746"
  33. "E6049CCC06899401264FA471C016A96C"
  34. "79815B55BBC26B43052609D9D175FBCD"
  35. "E455392F10E51EC162F51CF732E6BB39"
  36. "1F56BBFD8D957DF3D4C55B71CEFD54B1"
  37. "9C16D458757373E698D7E693A8FC3981"
  38. "5A8BF03BA05EA8C8778D38F9873D62B4"
  39. "460F41ACF997C30E7C3AF025FA171B5F"
  40. "5AD4D6B15E95C27F6B35AD61875E5505"
  41. "449B4E";
  42. const char PatchSolution1::Keyword3[4 + 1] =
  43. "\x59\x08\x01\x00";
  44. const char PatchSolution1::Keyword4[5 + 1] =
  45. "92933";
  46. [[nodiscard]]
  47. bool PatchSolution1::FindPatchOffset() noexcept {
  48. try {
  49. PIMAGE_SECTION_HEADER SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
  50. PIMAGE_SECTION_HEADER SectionHeader_rdata = _Image.ImageSectionHeaderByName(".rdata");
  51. const uint8_t* pbPatch[_countof(_PatchOffset)] = {};
  52. pbPatch[0] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
  53. __try {
  54. return memcmp(p, Keyword0, sizeof(Keyword0)) == 0;
  55. } __except (EXCEPTION_EXECUTE_HANDLER) {
  56. return false;
  57. }
  58. });
  59. pbPatch[2] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
  60. __try {
  61. return memcmp(p, Keyword2, sizeof(Keyword2)) == 0;
  62. } __except (EXCEPTION_EXECUTE_HANDLER) {
  63. return false;
  64. }
  65. });
  66. pbPatch[4] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
  67. __try {
  68. return memcmp(p, Keyword4, sizeof(Keyword4)) == 0;
  69. } __except (EXCEPTION_EXECUTE_HANDLER) {
  70. return false;
  71. }
  72. });
  73. pbPatch[1] = _Image.SearchSection<const uint8_t*>(SectionHeader_text, [&pbPatch](const uint8_t* p) {
  74. __try {
  75. if (memcmp(p, Keyword1, literal_length(Keyword1)) == 0) {
  76. // Keyword3 must be close to Keyword1
  77. for (auto j = p - 64; j < p + 64; ++j) {
  78. if (memcmp(j, Keyword3, literal_length(Keyword3)) == 0) {
  79. pbPatch[3] = j;
  80. return true;
  81. }
  82. }
  83. }
  84. return false;
  85. } __except (EXCEPTION_EXECUTE_HANDLER) {
  86. return false;
  87. }
  88. });
  89. for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
  90. _PatchOffset[i] = _Image.PointerToFileOffset(pbPatch[i]);
  91. }
  92. _PatchSize[0] = literal_length(Keyword0);
  93. while (pbPatch[0][_PatchSize[0] + 1] == 0 && _PatchSize[0] < literal_length(Keyword0) + literal_length("29158142") - 1) {
  94. ++_PatchSize[0];
  95. }
  96. _PatchSize[1] = sizeof(uint32_t);
  97. _PatchSize[2] = literal_length(Keyword2);
  98. while (pbPatch[2][_PatchSize[2] + 1] == 0 && _PatchSize[2] < literal_length(Keyword2) + literal_length("67673") - 1) {
  99. ++_PatchSize[2];
  100. }
  101. _PatchSize[3] = sizeof(uint32_t);
  102. _PatchSize[4] = literal_length(Keyword4);
  103. LOG_SUCCESS(0, "PatchSolution1 ...... Ready to apply");
  104. LOG_HINT(4, "[0] Patch offset = +0x%.8zx", _PatchOffset[0]);
  105. LOG_HINT(4, "[1] Patch offset = +0x%.8zx", _PatchOffset[1]);
  106. LOG_HINT(4, "[2] Patch offset = +0x%.8zx", _PatchOffset[2]);
  107. LOG_HINT(4, "[3] Patch offset = +0x%.8zx", _PatchOffset[3]);
  108. LOG_HINT(4, "[4] Patch offset = +0x%.8zx", _PatchOffset[4]);
  109. return true;
  110. } catch (nkg::Exception&) {
  111. for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
  112. _PatchOffset[i] = InvalidOffset;
  113. _PatchSize[i] = 0;
  114. }
  115. LOG_FAILURE(0, "PatchSolution1 ...... Omitted");
  116. return false;
  117. }
  118. }
  119. [[nodiscard]]
  120. bool PatchSolution1::CheckKey(const RSACipher& Cipher) const noexcept {
  121. if (_PatchSize[0] && _PatchSize[1] && _PatchSize[2] && _PatchSize[3] && _PatchSize[4]) {
  122. auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
  123. for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
  124. szPublicKey.replace(i, 1, "\r\n");
  125. }
  126. auto szPublicKeyEncrypted = g_NavicatCipher.EncryptString(szPublicKey);
  127. if (szPublicKeyEncrypted.length() != 920) {
  128. return false;
  129. }
  130. // we require the chars in [p1, p2) of szPublicKeyEncrypted must be number chars
  131. size_t p1, p2;
  132. p1 = _PatchSize[0];
  133. p2 = literal_length(Keyword0) + literal_length("29158142");
  134. if (('1' <= szPublicKeyEncrypted[p1] && szPublicKeyEncrypted[p1] <= '9') == false) {
  135. return false;
  136. }
  137. for (size_t i = p1 + 1; i < p2; ++i) {
  138. if (('0' <= szPublicKeyEncrypted[i] && szPublicKeyEncrypted[i] <= '9') == false) {
  139. return false;
  140. }
  141. }
  142. // we require the chars in [p1, p2) of szPublicKeyEncrypted must be number chars
  143. p1 = literal_length(Keyword0) + literal_length("29158142") + _PatchSize[2];
  144. p2 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673");
  145. if (('1' <= szPublicKeyEncrypted[p1] && szPublicKeyEncrypted[p1] <= '9') == false) {
  146. return false;
  147. }
  148. for (size_t i = p1 + 1; i < p2; ++i) {
  149. if (('0' <= szPublicKeyEncrypted[i] && szPublicKeyEncrypted[i] <= '9') == false) {
  150. return false;
  151. }
  152. }
  153. return true;
  154. } else {
  155. return false;
  156. }
  157. }
  158. void PatchSolution1::MakePatch(const RSACipher& Cipher) const {
  159. if (_PatchSize[0] && _PatchSize[1] && _PatchSize[2] && _PatchSize[3] && _PatchSize[4]) {
  160. auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
  161. for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
  162. szPublicKey.replace(i, 1, "\r\n");
  163. }
  164. auto szPublicKeyEncrypted = g_NavicatCipher.EncryptString(szPublicKey);
  165. //
  166. // p0 p1 p2 p3 p4 p5
  167. // Original encrypted public key layout: |160 chars|8 chars|742 chars|5 chars|5 chars|
  168. // | |
  169. // V V
  170. // ImmValue1 ImmValue3
  171. size_t p0, p1, p2, p3, p4, p5;
  172. p0 = 0;
  173. p1 = _PatchSize[0];
  174. p2 = literal_length(Keyword0) + literal_length("29158142");
  175. p3 = literal_length(Keyword0) + literal_length("29158142") + _PatchSize[2];
  176. p4 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673");
  177. p5 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673") + literal_length(Keyword4);
  178. if (szPublicKeyEncrypted.length() != 920) {
  179. throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("szPublicKeyEncrypted.length() != 920"));
  180. }
  181. std::string EncryptedPEM0(szPublicKeyEncrypted.begin() + p0, szPublicKeyEncrypted.begin() + p1);
  182. std::string EncryptedPEM1(szPublicKeyEncrypted.begin() + p1, szPublicKeyEncrypted.begin() + p2);
  183. std::string EncryptedPEM2(szPublicKeyEncrypted.begin() + p2, szPublicKeyEncrypted.begin() + p3);
  184. std::string EncryptedPEM3(szPublicKeyEncrypted.begin() + p3, szPublicKeyEncrypted.begin() + p4);
  185. std::string EncryptedPEM4(szPublicKeyEncrypted.begin() + p4, szPublicKeyEncrypted.begin() + p5);
  186. uint32_t ImmValue1 = std::stoul(EncryptedPEM1.c_str());
  187. uint32_t ImmValue3 = std::stoul(EncryptedPEM3.c_str());
  188. uint8_t* pbPatch[_countof(_PatchOffset)] = {};
  189. for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
  190. pbPatch[i] = _Image.FileOffsetToPointer<uint8_t*>(_PatchOffset[i]);
  191. }
  192. _putts(TEXT("*******************************************************"));
  193. _putts(TEXT("* PatchSolution1 *"));
  194. _putts(TEXT("*******************************************************"));
  195. // ----------------------------------
  196. // process PatchOffsets[0]
  197. // ----------------------------------
  198. LOG_HINT(0, "Previous:");
  199. PrintMemory(pbPatch[0], _PatchSize[0], _Image.ImageBase());
  200. memcpy(pbPatch[0], EncryptedPEM0.data(), _PatchSize[0]);
  201. LOG_HINT(0, "After:");
  202. PrintMemory(pbPatch[0], _PatchSize[0], _Image.ImageBase());
  203. _putts(TEXT(""));
  204. // ----------------------------------
  205. // process PatchOffsets[1]
  206. // ----------------------------------
  207. LOG_HINT(0, "Previous:");
  208. PrintMemory(pbPatch[1], _PatchSize[1], _Image.ImageBase());
  209. memcpy(pbPatch[1], &ImmValue1, _PatchSize[1]);
  210. LOG_HINT(0, "After:");
  211. PrintMemory(pbPatch[1], _PatchSize[1], _Image.ImageBase());
  212. _putts(TEXT(""));
  213. // ----------------------------------
  214. // process PatchOffsets[2]
  215. // ----------------------------------
  216. LOG_HINT(0, "Previous:");
  217. PrintMemory(pbPatch[2], _PatchSize[2], _Image.ImageBase());
  218. memcpy(pbPatch[2], EncryptedPEM2.data(), _PatchSize[2]);
  219. LOG_HINT(0, "After:");
  220. PrintMemory(pbPatch[2], _PatchSize[2], _Image.ImageBase());
  221. _putts(TEXT(""));
  222. // ----------------------------------
  223. // process PatchOffsets[3]
  224. // ----------------------------------
  225. LOG_HINT(0, "Previous:");
  226. PrintMemory(pbPatch[3], _PatchSize[3], _Image.ImageBase());
  227. memcpy(pbPatch[3], &ImmValue3, _PatchSize[3]);
  228. LOG_HINT(0, "After:");
  229. PrintMemory(pbPatch[3], _PatchSize[3], _Image.ImageBase());
  230. _putts(TEXT(""));
  231. // ----------------------------------
  232. // process PatchOffsets[4]
  233. // ----------------------------------
  234. LOG_HINT(0, "Previous:");
  235. PrintMemory(pbPatch[4], _PatchSize[4], _Image.ImageBase());
  236. memcpy(pbPatch[4], EncryptedPEM4.data(), _PatchSize[4]);
  237. LOG_HINT(0, "After:");
  238. PrintMemory(pbPatch[4], _PatchSize[4], _Image.ImageBase());
  239. _putts(TEXT(""));
  240. } else {
  241. throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution1 has not been ready yet."));
  242. }
  243. }
  244. }