PatchSolution4-i386.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "PatchSolutions.hpp"
  2. #include <xstring.hpp>
  3. #undef NKG_CURRENT_SOURCE_FILE
  4. #undef NKG_CURRENT_SOURCE_LINE
  5. #define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution4-i386.cpp")
  6. #define NKG_CURRENT_SOURCE_LINE() __LINE__
  7. namespace nkg {
  8. PatchSolution4::PatchSolution4(const ImageInterpreter& Image) :
  9. _Image(Image),
  10. _DisassemblyEngine(CS_ARCH_X86, CS_MODE_32),
  11. _AssemblyEngine(KS_ARCH_X86, KS_MODE_32),
  12. _pbPatchMachineCode(nullptr),
  13. _pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
  14. PatchSolution4::PatchSolution4(const ImageInterpreter* Image) :
  15. _Image(*Image),
  16. _DisassemblyEngine(CS_ARCH_X86, CS_MODE_32),
  17. _AssemblyEngine(KS_ARCH_X86, KS_MODE_32),
  18. _pbPatchMachineCode(nullptr),
  19. _pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
  20. bool PatchSolution4::FindPatchOffset() noexcept {
  21. try {
  22. _pbPatchMachineCode = _Image.SearchSection<uint8_t*>(".text", [](const uint8_t* p) {
  23. __try {
  24. return
  25. p[0] == 0x83 && // prefix of "cmp [ebp+var_30], 10h"
  26. p[4] == 0x8d && // prefix of "lea ecx, [ebp+Dst]"
  27. p[7] == 0x8d && // prefix of "lea eax, [ebp+Memory]"
  28. p[10] == 0x0f && p[11] == 0x43 && // prefix of "cmovnb ecx, [ebp+Dst]"
  29. p[14] == 0x83 && // prefix of "cmp [ebp+var_18], 10h"
  30. p[18] == 0x0f && p[19] == 0x43 && // prefix of "cmovnb eax, [ebp+Memory]"
  31. p[22] == 0x8a && // prefix of "mov dl, [eax+ebx]"
  32. p[25] == 0x02; // prefix of "add dl, [ecx+ebx]"
  33. // p[28]
  34. } __except (EXCEPTION_EXECUTE_HANDLER) {
  35. return false;
  36. }
  37. });
  38. auto RegisterIndex = X86_REG_INVALID;
  39. auto RegisterFinalValue = X86_REG_INVALID;
  40. auto Disassembler = _DisassemblyEngine.CreateDisassembler();
  41. Disassembler.SetContext({ _pbPatchMachineCode, 28, _Image.PointerToVa(_pbPatchMachineCode) });
  42. if (Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next()) {
  43. auto lpInsn = Disassembler.GetInstruction();
  44. if (_stricmp(lpInsn->mnemonic, "mov") == 0 &&
  45. lpInsn->detail->x86.op_count == 2 &&
  46. lpInsn->detail->x86.operands[0].type == X86_OP_REG &&
  47. lpInsn->detail->x86.operands[1].type == X86_OP_MEM &&
  48. lpInsn->detail->x86.operands[1].size == 1 &&
  49. lpInsn->detail->x86.operands[1].mem.scale == 1)
  50. {
  51. RegisterIndex = lpInsn->detail->x86.operands[1].mem.index;
  52. } else {
  53. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
  54. }
  55. } else {
  56. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
  57. }
  58. if (Disassembler.Next()) {
  59. auto lpInsn = Disassembler.GetInstruction();
  60. if (_stricmp(lpInsn->mnemonic, "add") == 0 &&
  61. lpInsn->detail->x86.op_count >= 1 &&
  62. lpInsn->detail->x86.operands[0].type == X86_OP_REG &&
  63. lpInsn->detail->x86.operands[0].size == 1)
  64. {
  65. RegisterFinalValue = lpInsn->detail->x86.operands[0].reg;
  66. } else {
  67. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
  68. }
  69. } else {
  70. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
  71. }
  72. for (size_t i = 0; i < _Image.NumberOfSections(); ++i) {
  73. auto lpSectionHeader = _Image.ImageSectionHeader(i);
  74. if (lpSectionHeader->SizeOfRawData > lpSectionHeader->Misc.VirtualSize) {
  75. auto cbReserved =
  76. lpSectionHeader->SizeOfRawData -
  77. lpSectionHeader->Misc.VirtualSize;
  78. if (cbReserved >= 0x188) {
  79. _pbPatchNewPublicKey = _Image.ImageSectionView<uint8_t*>(lpSectionHeader, lpSectionHeader->Misc.VirtualSize);
  80. auto Assembler = _AssemblyEngine.CreateAssembler();
  81. _NewMachineCode = Assembler.GenerateMachineCode(
  82. std::xstring::format(
  83. TEXT(
  84. "call +5;"
  85. "pop eax;"
  86. "add eax, 0x%.8x;"
  87. "mov %hs, byte ptr [eax + %hs];"
  88. ),
  89. _Image.PointerToVa(_pbPatchNewPublicKey) - (_Image.PointerToVa(_pbPatchMachineCode) + 5),
  90. _DisassemblyEngine.GetRegisterName(RegisterFinalValue),
  91. _DisassemblyEngine.GetRegisterName(RegisterIndex)
  92. ).explicit_string().c_str()
  93. );
  94. // >>>>>>>>>>>> .text:113FE4A0 83 7D D0 10 cmp [ebp+var_30], 10h
  95. // 28 BYTES .text:113FE4A4 8D 4D BC lea ecx, [ebp+Dst]
  96. // .text:113FE4A7 8D 45 D4 lea eax, [ebp+Memory]
  97. // THESE CODE .text:113FE4AA 0F 43 4D BC cmovnb ecx, [ebp+Dst]
  98. // WILL BE .text:113FE4AE 83 7D E8 10 cmp [ebp+var_18], 10h
  99. // REPLACED .text:113FE4B2 0F 43 45 D4 cmovnb eax, [ebp+Memory]
  100. // .text:113FE4B6 8A 14 18 mov dl, [eax+ebx]
  101. // <<<<<<<<<<<< .text:113FE4B9 02 14 19 add dl, [ecx+ebx]
  102. while (_NewMachineCode.size() < 28) {
  103. _NewMachineCode.emplace_back(0x90); // padding with "nop"
  104. }
  105. if (_NewMachineCode.size() != 28) {
  106. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Something unexpected happens."));
  107. }
  108. LOG_SUCCESS(0, "PatchSolution4 ...... Ready to apply");
  109. LOG_HINT(4, "Machine code patch VA = 0x%zx", _Image.PointerToVa(_pbPatchMachineCode));
  110. LOG_HINT(4, "New public key VA = 0x%zx", _Image.PointerToVa(_pbPatchNewPublicKey));
  111. LOG_HINT(4, "New public key offset = 0x%zx", _Image.PointerToFileOffset(_pbPatchNewPublicKey));
  112. return true;
  113. }
  114. }
  115. }
  116. throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("No space to store public key."));
  117. } catch (nkg::Exception&) {
  118. _pbPatchMachineCode = nullptr;
  119. _pbPatchNewPublicKey = nullptr;
  120. _NewMachineCode.clear();
  121. LOG_FAILURE(0, "PatchSolution4 ...... Omitted");
  122. return false;
  123. }
  124. }
  125. }