Created
June 9, 2026 07:19
-
-
Save sunmeat/1ec0eebce70e6cace445610ac2fb0b7e to your computer and use it in GitHub Desktop.
пример находит строку текста в памяти другого процесса, и меняет её на другую строку такой же длины (проверять в notepad++)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <windows.h> | |
| #include <tlhelp32.h> | |
| #include <iostream> | |
| #include <vector> | |
| #include <string> | |
| #include <shellapi.h> | |
| bool IsRunAsAdmin() { | |
| bool isAdmin = false; | |
| HANDLE token = NULL; | |
| if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { | |
| TOKEN_ELEVATION elevation; | |
| DWORD size = sizeof(elevation); | |
| if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) { | |
| isAdmin = elevation.TokenIsElevated != 0; | |
| } | |
| CloseHandle(token); | |
| } | |
| return isAdmin; | |
| } | |
| void ElevatePrivileges() { | |
| wchar_t szPath[MAX_PATH]; | |
| if (GetModuleFileNameW(NULL, szPath, MAX_PATH)) { | |
| SHELLEXECUTEINFOW sei = { sizeof(sei) }; | |
| sei.cbSize = sizeof(sei); | |
| sei.lpVerb = L"runas"; | |
| sei.lpFile = szPath; | |
| sei.hwnd = NULL; | |
| sei.nShow = SW_NORMAL; | |
| if (ShellExecuteExW(&sei)) { | |
| ExitProcess(0); | |
| } | |
| } | |
| } | |
| DWORD GetProcessIdByName(const wchar_t* processName) { | |
| DWORD pid = 0; | |
| HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
| if (snapshot != INVALID_HANDLE_VALUE) { | |
| PROCESSENTRY32W processEntry; | |
| processEntry.dwSize = sizeof(processEntry); | |
| if (Process32FirstW(snapshot, &processEntry)) { | |
| do { | |
| if (wcscmp(processEntry.szExeFile, processName) == 0) { | |
| pid = processEntry.th32ProcessID; | |
| break; | |
| } | |
| } while (Process32NextW(snapshot, &processEntry)); | |
| } | |
| CloseHandle(snapshot); | |
| } | |
| return pid; | |
| } | |
| int main() { | |
| if (!IsRunAsAdmin()) { | |
| ElevatePrivileges(); | |
| return 0; | |
| } | |
| // Нацеливаемся на классический Win32 Notepad++ | |
| const wchar_t* targetProcess = L"notepad++.exe"; | |
| std::string targetStr, newStr; | |
| std::cout << "Enter string to find (e.g. hello): "; | |
| std::cin >> targetStr; | |
| std::cout << "Enter new string (must be same length, e.g. world): "; | |
| std::cin >> newStr; | |
| if (targetStr.length() != newStr.length()) { | |
| std::cout << "Strings must be of equal length for this simple example!" << std::endl; | |
| system("pause"); | |
| return 1; | |
| } | |
| DWORD pid = GetProcessIdByName(targetProcess); | |
| if (pid == 0) { | |
| std::cout << "Process notepad++.exe not found. Please open Notepad++ first." << std::endl; | |
| system("pause"); | |
| return 1; | |
| } | |
| HANDLE processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, pid); | |
| if (!processHandle) { | |
| std::cout << "Failed to open process. Error code: " << GetLastError() << std::endl; | |
| system("pause"); | |
| return 1; | |
| } | |
| SYSTEM_INFO sysInfo; | |
| GetSystemInfo(&sysInfo); | |
| char* address = static_cast<char*>(sysInfo.lpMinimumApplicationAddress); | |
| char* maxAddress = static_cast<char*>(sysInfo.lpMaximumApplicationAddress); | |
| size_t replacementsCount = 0; | |
| while (address < maxAddress) { | |
| MEMORY_BASIC_INFORMATION mbi; | |
| if (VirtualQueryEx(processHandle, address, &mbi, sizeof(mbi)) == sizeof(mbi)) { | |
| if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE) && !(mbi.Protect & PAGE_GUARD)) { | |
| std::vector<char> buffer(mbi.RegionSize); | |
| SIZE_T bytesRead; | |
| if (ReadProcessMemory(processHandle, mbi.BaseAddress, buffer.data(), mbi.RegionSize, &bytesRead)) { | |
| for (size_t i = 0; i <= bytesRead - targetStr.length(); ++i) { | |
| if (memcmp(&buffer[i], targetStr.c_str(), targetStr.length()) == 0) { | |
| char* matchAddress = static_cast<char*>(mbi.BaseAddress) + i; | |
| SIZE_T bytesWritten; | |
| if (WriteProcessMemory(processHandle, matchAddress, newStr.c_str(), newStr.length(), &bytesWritten)) { | |
| replacementsCount++; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| address += mbi.RegionSize; | |
| } | |
| else { | |
| address += sysInfo.dwPageSize; | |
| } | |
| } | |
| std::cout << "Scan finished. Total replacements made: " << replacementsCount << std::endl; | |
| CloseHandle(processHandle); | |
| system("pause"); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment