【发布时间】:2019-09-28 21:42:57
【问题描述】:
我正在尝试编写一些自修改代码,但是一旦我找到了要在内存中写入补丁的位置,我实际上无法将补丁写入内存。
我尝试使用不同的方法来确保我尝试修补的内存区域的权限对于我想要做的事情是正确的 (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 函数中的程序集,使其只返回而不是打印 hi!
我是否还可以指出,我想在不使用指向 say_hi 函数的指针的情况下执行此操作,而是在内存中搜索它。这是因为我将在一个无法访问指向函数的直接指针的项目中实现此技术。
更新:
我已经删除了对WriteProcessMemory 的调用,并将其替换为CopyMemory。我现在还使用GetModuleHandle 来获取模块的基地址。现在它将自行编译...尽管它似乎仍然没有覆盖say_hi 函数中的代码。
【问题讨论】:
-
代码失败的原因是什么?
-
在自己的进程中读/写内存时不需要使用
(Read|Write)ProcessMemory()。您可以直接读/写内存,例如使用memcpy()或CopyMemory()。仅当在其他进程中读取/写入内存时才使用(Read|Write)ProcessMemory()。 -
代码失败,因为它没有写入该位置,
say_hi函数仍在执行,而不仅仅是返回。 -
嗯,我尝试过使用
CopyMemory()或memcpy(),但我仍然无法使用这些方法使其工作。例如CopyMemory((LPVOID)(base_address + patternOffset), REPLACE, LEN) -
@Dylanhalls 好吧,对于初学者来说,您的代码甚至不应该如图所示编译,因为
patch_mem()甚至在声明之前尝试使用base_address。所以这不可能是你真正的代码。
标签: c windows winapi self-modifying