我正在编辑一款名为Assault Cube的游戏,可以在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, "\x8B\xFF\x55\x8B\xEC", 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;
这会导致崩溃。
答案 0 :(得分:1)
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
是无效的操作码序列,那么程序当然会崩溃!
这可能不起作用的另一个原因是,调试器(在您的情况下,OllyDbg)以与OS不同的方式布局正在调试的进程的地址空间是常见的(至少在Mac和Linux上)当进程本地运行时。这意味着像0x45B75F
这样的地址在调试器中可能有意义,但在尝试操作本机进程的内存时却毫无意义。
这可能不起作用的第三个原因是对内存的写入(没有来自您的更多信息)似乎在您的进程的内存上运行而不是在另一个进程的内存上运行(除非您正在尝试做)。如果该存储器地址被映射,则它仍然可能无法写入(由于页面保护)。