Solution1.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "def.hpp"
  2. namespace Patcher {
  3. const char* Solution1::Keywords[5] = {
  4. "D75125B70767B94145B47C1CB3C0755E"
  5. "7CCB8825C5DCE0C58ACF944E08280140"
  6. "9A02472FAFFD1CD77864BB821AE36766"
  7. "FEEDE6A24F12662954168BFA314BD950"
  8. "32B9D82445355ED7BC0B880887D650F5",
  9. "\xfe\xea\xbc\x01",
  10. "E1CED09B9C2186BF71A70C0FE2F1E0AE"
  11. "F3BD6B75277AAB20DFAF3D110F75912B"
  12. "FB63AC50EC4C48689D1502715243A79F"
  13. "39FF2DE2BF15CE438FF885745ED54573"
  14. "850E8A9F40EE2FF505EB7476F95ADB78"
  15. "3B28CA374FAC4632892AB82FB3BF4715"
  16. "FCFE6E82D03731FC3762B6AAC3DF1C3B"
  17. "C646FE9CD3C62663A97EE72DB932A301"
  18. "312B4A7633100C8CC357262C39A2B3A6"
  19. "4B224F5276D5EDBDF0804DC3AC4B8351"
  20. "62BB1969EAEBADC43D2511D6E0239287"
  21. "81B167A48273B953378D3D2080CC0677"
  22. "7E8A2364F0234B81064C5C739A8DA28D"
  23. "C5889072BF37685CBC94C2D31D0179AD"
  24. "86D8E3AA8090D4F0B281BE37E0143746"
  25. "E6049CCC06899401264FA471C016A96C"
  26. "79815B55BBC26B43052609D9D175FBCD"
  27. "E455392F10E51EC162F51CF732E6BB39"
  28. "1F56BBFD8D957DF3D4C55B71CEFD54B1"
  29. "9C16D458757373E698D7E693A8FC3981"
  30. "5A8BF03BA05EA8C8778D38F9873D62B4"
  31. "460F41ACF997C30E7C3AF025FA171B5F"
  32. "5AD4D6B15E95C27F6B35AD61875E5505"
  33. "449B4E",
  34. "\x59\x08\x01\x00",
  35. "92933"
  36. };
  37. const int Solution1::KeywordsLength[5] = {
  38. 160,
  39. 4,
  40. 742,
  41. 4,
  42. 5
  43. };
  44. bool Solution1::CheckKey(RSACipher* cipher) const noexcept {
  45. BOOL bOk = FALSE;
  46. std::string RSAPublicKeyPEM;
  47. RSAPublicKeyPEM =
  48. cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
  49. if (RSAPublicKeyPEM.empty()) {
  50. REPORT_ERROR("ERROR: cipher->ExportKeyString failed.");
  51. return false;
  52. }
  53. [](std::string& str, const std::string& OldSub, const std::string& NewSub) {
  54. std::string::size_type pos = 0;
  55. std::string::size_type srclen = OldSub.size();
  56. std::string::size_type dstlen = NewSub.size();
  57. while ((pos = str.find(OldSub, pos)) != std::string::npos) {
  58. str.replace(pos, srclen, NewSub);
  59. pos += dstlen;
  60. }
  61. } (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
  62. std::string encrypted_pem_text = Helper::EncryptPublicKey(RSAPublicKeyPEM);
  63. if (encrypted_pem_text[160] > '9' || encrypted_pem_text[160] < '1')
  64. return false;
  65. for (int i = 1; i < 8; ++i)
  66. if (encrypted_pem_text[160 + i] > '9' || encrypted_pem_text[160 + i] < '0')
  67. return false;
  68. if (encrypted_pem_text[910] > '9' || encrypted_pem_text[910] < '1')
  69. return false;
  70. for (int i = 1; i < 5; ++i)
  71. if (encrypted_pem_text[910 + i] > '9' || encrypted_pem_text[910 + i] < '0')
  72. return false;
  73. return true;
  74. }
  75. bool Solution1::FindPatchOffset() noexcept {
  76. PIMAGE_SECTION_HEADER textSection = nullptr;
  77. PIMAGE_SECTION_HEADER rdataSection = nullptr;
  78. uint8_t* pTargetFileView = pTargetFile->GetView<uint8_t>();
  79. off_t Offsets[5] = { -1, -1, -1, -1, -1 };
  80. textSection = Helper::ImageSectionHeader(pTargetFileView, ".text");
  81. if (textSection == nullptr) {
  82. // REPORT_ERROR("ERROR: Cannot find .text section.");
  83. return false;
  84. }
  85. rdataSection = Helper::ImageSectionHeader(pTargetFileView, ".rdata");
  86. if (textSection == nullptr) {
  87. // REPORT_ERROR("ERROR: Cannot find .rdata section.");
  88. return false;
  89. }
  90. // -------------------------
  91. // try to search Keywords[0]
  92. // -------------------------
  93. for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
  94. if (memcmp(pTargetFileView + rdataSection->PointerToRawData + i, Keywords[0], KeywordsLength[0]) == 0) {
  95. Offsets[0] = rdataSection->PointerToRawData + i;
  96. break;
  97. }
  98. }
  99. if (Offsets[0] == -1) {
  100. // REPORT_ERROR("ERROR: Cannot find Keywords[0].");
  101. return false;
  102. }
  103. // -------------------------
  104. // try to search Keywords[2]
  105. // -------------------------
  106. for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
  107. if (memcmp(pTargetFileView + rdataSection->PointerToRawData + i, Keywords[2], KeywordsLength[2]) == 0) {
  108. Offsets[2] = rdataSection->PointerToRawData + i;
  109. break;
  110. }
  111. }
  112. if (Offsets[2] == -1) {
  113. // REPORT_ERROR("ERROR: Cannot find Keywords[2].");
  114. return false;
  115. }
  116. // -------------------------
  117. // try to search Keywords[4]
  118. // -------------------------
  119. for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
  120. if (memcmp((uint8_t*)pTargetFileView + rdataSection->PointerToRawData + i, Keywords[4], KeywordsLength[4]) == 0) {
  121. Offsets[4] = rdataSection->PointerToRawData + i;
  122. break;
  123. }
  124. }
  125. if (Offsets[4] == -1) {
  126. // REPORT_ERROR("ERROR: Cannot find Keywords[4].");
  127. return false;
  128. }
  129. // -------------------------
  130. // try to search Keywords[1] and Keywords[3]
  131. // -------------------------
  132. for (DWORD i = 0; i < textSection->SizeOfRawData; ++i) {
  133. if (memcmp(pTargetFileView + textSection->PointerToRawData + i, Keywords[1], KeywordsLength[1]) == 0) {
  134. // Keywords[3] must be close to Keywords[1]
  135. for (DWORD j = i - 64; j < i + 64; ++j) {
  136. if (memcmp(pTargetFileView + textSection->PointerToRawData + j, Keywords[3], KeywordsLength[3]) == 0) {
  137. Offsets[1] = textSection->PointerToRawData + i;
  138. Offsets[3] = textSection->PointerToRawData + j;
  139. break;
  140. }
  141. }
  142. // Offsets[1] and Offsets[3] are set synchronously
  143. // so check Offsets[1] is enough
  144. if (Offsets[1] != -1)
  145. break;
  146. }
  147. }
  148. if (Offsets[1] == -1) {
  149. // REPORT_ERROR("ERROR: Cannot find Keywords[1] and Keywords[3].");
  150. return false;
  151. }
  152. PatchOffsets[0] = Offsets[0];
  153. PatchOffsets[1] = Offsets[1];
  154. PatchOffsets[2] = Offsets[2];
  155. PatchOffsets[3] = Offsets[3];
  156. PatchOffsets[4] = Offsets[4];
  157. _tprintf_s(TEXT("MESSAGE: [Solution1] Keywords[0] has been found: offset = +0x%08lx.\n"), PatchOffsets[0]);
  158. _tprintf_s(TEXT("MESSAGE: [Solution1] Keywords[1] has been found: offset = +0x%08lx.\n"), PatchOffsets[1]);
  159. _tprintf_s(TEXT("MESSAGE: [Solution1] Keywords[2] has been found: offset = +0x%08lx.\n"), PatchOffsets[2]);
  160. _tprintf_s(TEXT("MESSAGE: [Solution1] Keywords[3] has been found: offset = +0x%08lx.\n"), PatchOffsets[3]);
  161. _tprintf_s(TEXT("MESSAGE: [Solution1] Keywords[4] has been found: offset = +0x%08lx.\n"), PatchOffsets[4]);
  162. return true;
  163. }
  164. bool Solution1::MakePatch(RSACipher* cipher) const {
  165. std::string RSAPublicKeyPEM;
  166. std::string encrypted_pem_pubkey;
  167. uint8_t* pTargetFileView = pTargetFile->GetView<uint8_t>();
  168. RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
  169. if (RSAPublicKeyPEM.empty()) {
  170. REPORT_ERROR("ERROR: cipher->ExportKeyString failed.");
  171. return FALSE;
  172. }
  173. [](std::string& str, const std::string& OldSub, const std::string& NewSub) {
  174. std::string::size_type pos = 0;
  175. std::string::size_type srclen = OldSub.size();
  176. std::string::size_type dstlen = NewSub.size();
  177. while ((pos = str.find(OldSub, pos)) != std::string::npos) {
  178. str.replace(pos, srclen, NewSub);
  179. pos += dstlen;
  180. }
  181. } (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
  182. encrypted_pem_pubkey = Helper::EncryptPublicKey(RSAPublicKeyPEM);
  183. // split encrypted_pem_pubkey to 5 part: |160 chars|8 chars|742 chars|5 chars|5 chars|
  184. // | |
  185. // \ / \ /
  186. // imm1 imm3
  187. std::string encrypted_pem_pubkey0(encrypted_pem_pubkey.begin(), encrypted_pem_pubkey.begin() + 160);
  188. std::string encrypted_pem_pubkey1(encrypted_pem_pubkey.begin() + 160, encrypted_pem_pubkey.begin() + 160 + 8);
  189. std::string encrypted_pem_pubkey2(encrypted_pem_pubkey.begin() + 160 + 8, encrypted_pem_pubkey.begin() + 160 + 8 + 742);
  190. std::string encrypted_pem_pubkey3(encrypted_pem_pubkey.begin() + 160 + 8 + 742, encrypted_pem_pubkey.begin() + 160 + 8 + 742 + 5);
  191. std::string encrypted_pem_pubkey4(encrypted_pem_pubkey.begin() + 160 + 8 + 742 + 5, encrypted_pem_pubkey.end());
  192. uint32_t imm1 = std::stoul(encrypted_pem_pubkey1.c_str());
  193. uint32_t imm3 = std::stoul(encrypted_pem_pubkey3.c_str());
  194. PRINT_MESSAGE("//");
  195. PRINT_MESSAGE("// Begin Solution1");
  196. PRINT_MESSAGE("//");
  197. // ----------------------------------
  198. // process PatchOffsets[0]
  199. // ----------------------------------
  200. _tprintf_s(TEXT("@+0x%08X\nPrevious:\n"), PatchOffsets[0]);
  201. Helper::PrintMemory(pTargetFileView + PatchOffsets[0],
  202. pTargetFileView + PatchOffsets[0] + KeywordsLength[0],
  203. pTargetFileView);
  204. memcpy(pTargetFileView + PatchOffsets[0], encrypted_pem_pubkey0.c_str(), KeywordsLength[0]);
  205. PRINT_MESSAGE("After:");
  206. Helper::PrintMemory(pTargetFileView + PatchOffsets[0],
  207. pTargetFileView + PatchOffsets[0] + KeywordsLength[0],
  208. pTargetFileView);
  209. PRINT_MESSAGE("");
  210. // ----------------------------------
  211. // process PatchOffsets[1]
  212. // ----------------------------------
  213. _tprintf_s(TEXT("@+0x%08X\nPrevious:\n"), PatchOffsets[1]);
  214. Helper::PrintMemory(pTargetFileView + PatchOffsets[1],
  215. pTargetFileView + PatchOffsets[1] + KeywordsLength[1],
  216. pTargetFileView);
  217. memcpy(pTargetFileView + PatchOffsets[1], &imm1, KeywordsLength[1]);
  218. PRINT_MESSAGE("After:");
  219. Helper::PrintMemory(pTargetFileView + PatchOffsets[1],
  220. pTargetFileView + PatchOffsets[1] + KeywordsLength[1],
  221. pTargetFileView);
  222. PRINT_MESSAGE("");
  223. // ----------------------------------
  224. // process PatchOffsets[2]
  225. // ----------------------------------
  226. _tprintf_s(TEXT("@+0x%08X\nPrevious:\n"), PatchOffsets[2]);
  227. Helper::PrintMemory(pTargetFileView + PatchOffsets[2],
  228. pTargetFileView + PatchOffsets[2] + KeywordsLength[2],
  229. pTargetFileView);
  230. memcpy(pTargetFileView + PatchOffsets[2], encrypted_pem_pubkey2.c_str(), KeywordsLength[2]);
  231. PRINT_MESSAGE("After:");
  232. Helper::PrintMemory(pTargetFileView + PatchOffsets[2],
  233. pTargetFileView + PatchOffsets[2] + KeywordsLength[2],
  234. pTargetFileView);
  235. PRINT_MESSAGE("");
  236. // ----------------------------------
  237. // process PatchOffsets[3]
  238. // ----------------------------------
  239. _tprintf_s(TEXT("@+0x%08X\nPrevious:\n"), PatchOffsets[3]);
  240. Helper::PrintMemory(pTargetFileView + PatchOffsets[3],
  241. pTargetFileView + PatchOffsets[3] + KeywordsLength[3],
  242. pTargetFileView);
  243. memcpy(pTargetFileView + PatchOffsets[3], &imm3, KeywordsLength[3]);
  244. PRINT_MESSAGE("After:");
  245. Helper::PrintMemory(pTargetFileView + PatchOffsets[3],
  246. pTargetFileView + PatchOffsets[3] + KeywordsLength[3],
  247. pTargetFileView);
  248. PRINT_MESSAGE("");
  249. // ----------------------------------
  250. // process PatchOffsets[4]
  251. // ----------------------------------
  252. _tprintf_s(TEXT("@+0x%08X\nPrevious:\n"), PatchOffsets[4]);
  253. Helper::PrintMemory(pTargetFileView + PatchOffsets[4],
  254. pTargetFileView + PatchOffsets[4] + KeywordsLength[4],
  255. pTargetFileView);
  256. memcpy(pTargetFileView + PatchOffsets[4], encrypted_pem_pubkey4.c_str(), KeywordsLength[4]);
  257. PRINT_MESSAGE("After:");
  258. Helper::PrintMemory(pTargetFileView + PatchOffsets[4],
  259. pTargetFileView + PatchOffsets[4] + KeywordsLength[4],
  260. pTargetFileView);
  261. PRINT_MESSAGE("");
  262. return TRUE;
  263. }
  264. }