Advertisement
Guest User

Find and patch a running process (windows, x86_64)

a guest
Nov 1st, 2016
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.67 KB | None | 0 0
  1.  
  2. #include <Windows.h>
  3. #include <string>
  4. #include <iostream>
  5. #include <list>
  6. #include <psapi.h>
  7.  
  8. std::string GetProcessName(DWORD processID)
  9. {
  10.     std::string result;
  11.     TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
  12.     HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
  13.                                   PROCESS_VM_READ,
  14.                                   FALSE, processID);
  15.     if (hProcess) {
  16.         HMODULE hMod;
  17.         DWORD cbNeeded;
  18.         if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
  19.                                &cbNeeded)) {
  20.             GetModuleBaseName(hProcess, hMod, szProcessName,
  21.                               sizeof(szProcessName) / sizeof(TCHAR));
  22.         }
  23.     }
  24.  
  25.     for (size_t i = 0 ; i < MAX_PATH && szProcessName[i] ; ++i) {
  26.         if (szProcessName[i] >= 32 && szProcessName[i] < 128) {
  27.             result.push_back(static_cast<char>(szProcessName[i]));
  28.         } else {
  29.             result.push_back('?');
  30.         }
  31.     }
  32.     CloseHandle(hProcess);
  33.     return result;
  34. }
  35.  
  36. bool Same(const std::string &s1, const std::string &s2)
  37. {
  38.     if (s1.size() != s2.size()) {
  39.         return false;
  40.     }
  41.     for (size_t i = 0 ; i < s1.size() ; ++i) {
  42.         if (tolower(s1[i]) != tolower(s2[i])) {
  43.             return false;
  44.         }
  45.     }
  46.     return true;
  47. }
  48.  
  49. DWORD FindProcess(const std::string &name)
  50. {
  51.     DWORD aProcesses[1024], cbNeeded, cProcesses;
  52.     unsigned int i;
  53.     if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
  54.         return 0;
  55.     }
  56.     cProcesses = cbNeeded / sizeof(DWORD);
  57.     for (i = 0; i < cProcesses; i++) {
  58.         if (aProcesses[i] != 0) {
  59.             std::string processName = GetProcessName(aProcesses[i]);
  60.             if (Same(processName, name)) {
  61.                 return aProcesses[i];
  62.             }
  63.         }
  64.     }
  65.     return 0;
  66. }
  67.  
  68. HANDLE FindModule(HANDLE process, const std::string &name)
  69. {
  70.     HMODULE hMods[1024];
  71.     DWORD cbNeeded;
  72.     if (EnumProcessModules(process, hMods, sizeof(hMods), &cbNeeded)) {
  73.         for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
  74.             TCHAR szModName[MAX_PATH];
  75.             if (!hMods[i]) {
  76.                 continue;
  77.             }
  78.             if (size_t len = GetModuleFileNameEx(process, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
  79.                 std::string name2;
  80.                 for (size_t j = 0 ; j < len ; ++j) {
  81.                     name2.push_back((static_cast<unsigned>(szModName[j]) > 32 && static_cast<unsigned>(szModName[j]) <= 127) ? szModName[j] : '?');
  82.                 }
  83.                 if (name.size() > name2.size()) {
  84.                     continue;
  85.                 }
  86.                 if (!Same(name2.substr(name2.size() - name.size()), name)) {
  87.                     continue;
  88.                 }
  89.                 return hMods[i];
  90.             }
  91.         }
  92.     }
  93.     return 0;
  94. }
  95.  
  96. bool ReadMemoryBYTES(HANDLE process, UINT64 address, unsigned char *buffer, UINT32 size)
  97. {
  98.     DWORD flOldProtect;
  99.     VirtualProtectEx(process, (LPVOID) address, size, PAGE_EXECUTE_READ, &flOldProtect);
  100.     SIZE_T br = 0;
  101.     bool result = false;
  102.     if (ReadProcessMemory(process, reinterpret_cast<LPVOID>(address), buffer, size, &br)) {
  103.         if (br == size) {
  104.             result = true;
  105.         }
  106.     }
  107.     VirtualProtectEx(process, (LPVOID) address, size, flOldProtect, &flOldProtect);
  108.     return result;
  109. }
  110.  
  111. void WriteMemoryBYTES(HANDLE process, UINT64 address, const void *bytes, unsigned int len)
  112. {
  113.     DWORD flOldProtect;
  114.     SIZE_T uNumberOfBytesWritten;
  115.  
  116.     VirtualProtectEx(process, (LPVOID) address, len, PAGE_WRITECOPY, &flOldProtect);
  117.     WriteProcessMemory(process, (LPVOID) address, bytes, len, &uNumberOfBytesWritten);
  118.     FlushInstructionCache(process, (LPVOID) address, len);
  119.     VirtualProtectEx(process, (LPVOID) address, len, flOldProtect, &flOldProtect);
  120. }
  121.  
  122. class PatchData {
  123. public:
  124.     class PatchItem {
  125.     public:
  126.         PatchItem(const UINT64 address, const char *oldData, const char *newData, const size_t size) :
  127.             address(address), oldData(oldData, size), newData(newData, size), size(size)
  128.         {
  129.         }
  130.  
  131.     public:
  132.         const UINT64 address;
  133.         const std::string oldData;
  134.         const std::string newData;
  135.         const size_t size;
  136.     };
  137.  
  138.     PatchData(const bool reverse) :
  139.         reverse(reverse)
  140.     {
  141.     }
  142.  
  143.     void Add(const UINT64 address, const char *oldData, const char *newData, const size_t size)
  144.     {
  145.         if (reverse) {
  146.             items.push_back(PatchItem(address, newData, oldData, size));
  147.         } else {
  148.             items.push_back(PatchItem(address, oldData, newData, size));
  149.         }
  150.     }
  151.  
  152.     const bool reverse;
  153.     std::list<PatchItem> items;
  154. };
  155.  
  156. std::string Hex(const void *data, const size_t size)
  157. {
  158.     std::string result;
  159.     char buffer[16];
  160.     for (size_t i = 0 ; i < size ; ++i) {
  161.         sprintf(buffer, "%02X", reinterpret_cast<const unsigned char*>(data)[i]);
  162.         if (i) {
  163.             result.push_back(' ');
  164.         }
  165.         result += buffer;
  166.     }
  167.     return result;
  168. }
  169.  
  170. int main(int argc, char **argv)
  171. {
  172.     if (argc > 2 || (argc == 2 && std::string("-r") != argv[1])) {
  173.         std::cerr << "Usage: " << argv[0] << "[-r]" << std::endl;
  174.         return 1;
  175.     }
  176.  
  177.     const std::string processName = "l2server.exe";
  178.     const std::string moduleName = "l2server.exe";
  179.     const bool reverse = (argc == 2);
  180.  
  181.     PatchData data(reverse);
  182.  
  183.     data.Add(0x4ABC3A, "\x45\x3B\xD4\x45\x0F\x4C\xE2", "\x31\xDB\x89\x5C\x24\x3C\x90", 7);
  184.     data.Add(0x4ABC4A, "\x3B\xCE\x45\x0F\x4C\xF1", "\x8D\x74\x24\xA0\x31\xFF", 6);
  185.     data.Add(0x4AC31E, "\x44\x3B\xCF\x41\x0F\x4C\xF9", "\x31\xDB\x89\x5C\x24\x68\x90", 7);
  186.     data.Add(0x4AC32C, "\x45\x3B\xC6\x45\x0F\x4C\xF0", "\x44\x8D\x77\xA0\x45\x31\xE4", 7);
  187.  
  188.     std::cerr << "Searching for process " << processName << std::endl;
  189.  
  190.     DWORD pid = FindProcess(processName);
  191.     if (!pid) {
  192.         std::cerr << "Can't find process " << processName << std::endl;
  193.         return 1;
  194.     }
  195.  
  196.     std::cerr << "Found " << processName << std::endl;
  197.  
  198.     std::cerr << "Opening process " << pid << std::endl;
  199.  
  200.     HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
  201.  
  202.     if (!process) {
  203.         std::cerr << "Can't open process " << pid << ": " << GetLastError() << std::endl;
  204.         return 1;
  205.     }
  206.  
  207.     std::cerr << "Process " << pid << " open" << std::endl;
  208.  
  209.     std::cerr << "Searching for module " << moduleName << std::endl;
  210.  
  211.     HANDLE module = FindModule(process, moduleName);
  212.     if (!module) {
  213.         std::cerr << "Can't find module " << moduleName << std::endl;
  214.         return 1;
  215.     }
  216.  
  217.     std::cerr << "Found module " << moduleName << " at " << module << std::endl;
  218.  
  219.     for (std::list<PatchData::PatchItem>::const_iterator i = data.items.begin() ; i != data.items.end() ; ++i) {
  220.         UINT64 addr = reinterpret_cast<UINT64>(module) + i->address;
  221.  
  222.         std::cerr << "Checking " << i->size << " bytes of old data at " << reinterpret_cast<void*>(addr) << std::endl;
  223.  
  224.         std::string buffer(i->size, '\x00');
  225.         ReadMemoryBYTES(process, addr, reinterpret_cast<unsigned char*>(const_cast<char*>(buffer.data())), i->size);
  226.         if (buffer != i->oldData) {
  227.             std::cerr << "Data mismatch at " << reinterpret_cast<void*>(addr) << std::endl;
  228.             std::cerr << "Expected " << Hex(i->oldData.data(), i->size) << std::endl;
  229.             std::cerr << "Got " << Hex(buffer.data(), i->size) << std::endl;
  230.             return 1;
  231.         }
  232.     }
  233.  
  234.     std::cerr << "Data match" << std::endl;
  235.  
  236.     for (std::list<PatchData::PatchItem>::const_iterator i = data.items.begin() ; i != data.items.end() ; ++i) {
  237.         UINT64 addr = reinterpret_cast<UINT64>(module) + i->address;
  238.  
  239.         std::cerr << "Patching " << i->size << " bytes at " << reinterpret_cast<void*>(addr) << std::endl;
  240.  
  241.         WriteMemoryBYTES(process, addr, reinterpret_cast<const void*>(i->newData.data()), i->size);
  242.     }
  243.  
  244.     std::cerr << "Done!" << std::endl;
  245.  
  246.     return 0;
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement