我正在记忆编辑一个叫做突击魔方的游戏,可以在:http://assault.cubers.net/
我不知道如何描述它,所以我做了一个视频:www.youtube.com/watch?v=SS1swxQIbDI
请注意,我的弹药在编辑前下降。编辑后,弹药保持不变。基本上,在0x45B75F,我需要插入两个nop。
我在网上找到了以下内容:
1。
BYTE NewBytes[] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
*(PBYTE)0xXXXXXXXX[0] = NewBytes;
所以我试着做:
BYTE NewBytes[] = { 0x90, 0x90 };
*(PBYTE)0x45B75F[0] = NewBytes;
但是我得到这个错误:error C2109: subscript requires array or pointer type
2。
DWORD origProtect;
VirtualProtect( ( void* )0x77D142CF, 5, PAGE_EXECUTE_READWRITE, &origProtect );
memcpy( ( void* )0x77D142CF, "x8BxFFx55x8BxEC", 5 );
VirtualProtect( ( void* )0x77D142CF, 5, origProtect, NULL );
我宁愿不使用memcpy或任何方法。
3。
char val = 0x48;
BOOL success = WriteProcessMemory(target, 0x10134CE0, &val, 1, NULL);
再说一次,我宁愿不使用方法。
4。
uint8_t* code = (uint8_t*)0x45B75F;
*code = 0x90;
上面的代码给了我这些错误:
error C2065: 'uint8_t' : undeclared identifier
error C2065: 'code' : undeclared identifier
error C2065: 'uint8_t' : undeclared identifier
error C2059: syntax error : ')'
error C2065: 'code' : undeclared identifier
5 .
*(char*)0x45B75F = 0x90;
这会导致崩溃
1。你在这里进行了双重解引用。你想要的是:
*((BYTE *) (0x45B75F + 0)) = NewBytes[0];
*((BYTE *) (0x45B75F + 1)) = NewBytes[1];
当覆盖代码时,您需要确保执行没有运行您正在覆盖的代码。否则,您可能会引入竞争条件,在短时间内意外地引入无效或不需要的指令。您可以研究原子操作(如果适用)来执行二进制重写。
2。你对memcpy
的厌恶似乎有问题。编译器有可能将memcpy
优化为双字MOV
,后跟单字MOV
。您可以通过将5个字节编码为一个32位整数和单个字节来强制解决此问题。或者,您可以连续5次写入内存,编译器可能会自动将它们组合起来。例如:
code[0] = byte0;
code[1] = byte1;
etc.
3。为什么要避免使用这个函数?我不熟悉windows,但这似乎是一个标准的方式来写入另一个进程的内存。
4。uint8_t
定义在stdint.h
C99标准库头文件中;你必须包含它。没有声明code
的错误是前一个uint8_t
错误的副作用。
5。这并非不合理。您将NOP
注入到假定的定义良好的地址中,而不考虑您正在覆盖的内容。看这个简单的例子:
假设我在内存中有一条指令调用I1
,它占用两个字节:[I1_0, I1_1]
。现在,你正在做的是用NOP
覆盖其中一个字节,而不考虑周围的字节是否仍然作为指令有效,例如[0x90, I1_1]
或[I1_0, 0x90]
。如果I1_0
或I1_1
单独是无效的操作码序列,那么程序当然会崩溃!
这可能不起作用的另一个原因是,通常(至少在Mac和Linux上)调试器(在您的例子中是OllyDbg)以与操作系统在本机运行进程时不同的方式布置正在调试的进程的地址空间。这意味着像0x45B75F
这样的地址在调试器中可能是有意义的,但在试图操作本机进程的内存时却没有意义。
这可能不起作用的第三个原因是,写入内存(没有来自您的更多信息)似乎是在您的进程的内存上操作,而不是在另一个进程的内存上操作(除非这是您正在尝试做的)。即使该内存地址被映射,它仍然可能无法用于写入(由于页面保护)。