Я пытаюсь написать некоторый самоизменяющийся код, но как только я нашел местоположение, в которое я хочу записать патч в память, я не могу фактически записать патч в память.
Я пытался использовать разные способы, чтобы гарантировать, что разрешения на область памяти, которую я пытаюсь исправить, правильны (PAGE_EXECUTE_READWRITE
) для того, что я хочу сделать.Я думаю, что проблема в том, как я называю WriteProcessMemory
, хотя я не уверен, почему это так.
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#define PATTERN "\x55\x48\x89\xe5\x48\x83\xec\x20\x48\x8d\x0d\x91\x2a\x00\x00\xe8\x3c\x16\x00\x00\x90\x48\x83\xc4\x20\x5d\xc3"
#define REPLACE "\x55\x48\x89\xe5\x90\x5d\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90x\90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xc3"
#define LEN 27
DWORD SearchPattern(unsigned char* mem, unsigned char* signature, DWORD signatureLen)
{
ULONG offset = 0;
for (int i = 0; i < 0x200000; i++) {
if (*(unsigned char*)(mem + i) == signature[0] && *(unsigned char*)(mem + i + 1) == signature[1]) {
if (memcmp(mem + i, signature, signatureLen) == 0) {
// Found the signature
offset = i;
break;
}
}
}
return offset;
}
void patch_mem()
{
DWORD oldProtect, oldOldProtect;
unsigned char *exe = (unsigned char *)GetModuleHandle("patching_tests.exe");
DWORD patternOffset = SearchPattern(exe, PATTERN, LEN);
if (patternOffset == 0)
{
printf("Error finding offset, returning\n");
return;
}
printf("offset: %#010x\n", (exe + patternOffset));
VirtualProtect((exe + patternOffset), LEN, PAGE_EXECUTE_READWRITE, &oldProtect);
CopyMemory((exe + patternOffset), REPLACE, LEN);
VirtualProtect((exe + patternOffset), LEN, oldProtect, &oldOldProtect);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (!FlushInstructionCache(handle, (LPCVOID)(exe + patternOffset), LEN))
{
printf("FlushInstructionCache, %d\n", GetLastError());
}
return;
}
int say_hi()
{
printf("hi!\n");
}
int main()
{
printf("calling say_hi...\n");
say_hi();
printf("patching memory...\n");
patch_mem();
printf("calling say_hi again...\n");
say_hi();
return 0;
}
Цель состоит в том, чтобы изменить сборку в функции say_hi
, чтобы она просто возвращала, а не печаталаПривет!
Могу ли я также отметить, что я хотел бы сделать это без использования указателя на функцию say_hi
и скорее искать его в памяти.Это потому, что я собираюсь реализовать эту технику в проекте, где невозможно получить прямой доступ к указателю на функцию.
ОБНОВЛЕНИЕ: Я удалил вызов WriteProcessMemory
и заменил егос CopyMemory
.Я также теперь использовал GetModuleHandle
, чтобы получить базовый адрес модуля.Теперь он скомпилируется сам по себе ... хотя, похоже, он не перезаписывает код в функции say_hi
.