如何在C ++中编辑操作码或写入内存或编辑字节?

时间:2013-04-28 04:06:01

标签: c++ pointers reverse-engineering memory-editing

我正在编辑一款名为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;

这会导致崩溃。

1 个答案:

答案 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_tstdint.h C99标准库标题中定义;你必须包括它。关于code未被声明的错误是前一个错误uint8_t的副作用。

5。 这不是不合理的。您正在将NOP注入到假定的明确定义的地址中,而不考虑您要覆盖的内容。举个简单的例子:

假设我在内存调用I1中有一条指令,它占用两个字节:[I1_0, I1_1]。现在,你正在做的是用NOP覆盖其中一个字节,而不考虑周围的字节是否仍然有效作为指令,例如: [0x90, I1_1][I1_0, 0x90]。如果仅I1_0I1_1是无效的操作码序列,那么程序当然会崩溃!

这可能不起作用的另一个原因是,调试器(在您的情况下,OllyDbg)以与OS不同的方式布局正在调试的进程的地址空间是常见的(至少在Mac和Linux上)当进程本地运行时。这意味着像0x45B75F这样的地址在调试器中可能有意义,但在尝试操作本机进程的内存时却毫无意义。

这可能不起作用的第三个原因是对内存的写入(没有来自您的更多信息)似乎在您的进程的内存上运行而不是在另一个进程的内存上运行(除非您正在尝试做)。如果该存储器地址被映射,则它仍然可能无法写入(由于页面保护)。