修改内存区域 - 返回 0xCC VC++

2022-01-12 00:00:00 visual-studio-2017 c++ self-modifying

我正在修改在 dll 中编译的可执行代码的某些部分.但是我正在修改的整个段的固定地址上的单个字节无法更改,甚至无法读取.

I am modifying some sections of an executable code compiled in a dll. But a single byte at a fixed address from the entire segment that I am modifying can't be changed, not even read.

代码很简单:

SEGMENT_DATA segInfo = getSegmentInfo(mHandle, segmentName);

if (segInfo.inFileSegmentAddr == 0) return false;

DWORD mOlProtection;
DWORD mOlProtection_1;

if (segInfo.architecture != MY_ARCH) {
    printf(" Not the same architecture!
");
    return 0;
}

if(VirtualProtect((LPVOID)segInfo.segmentAddr, segInfo.segmentSize, PAGE_EXECUTE_READWRITE, &mOlProtection)==0) return false;
DWORD i=0;
for (size_t k = 0; k < segInfo.segmentSize; k++) {
    BYTE *lpByteValue = (BYTE*)(segInfo.segmentAddr + k);

    BYTE temp = *lpByteValue;
    *lpByteValue = temp ^ lDecryptionKey[i];
    i++;
    i %= decryptionKeyLength;
}

if(VirtualProtect((LPVOID)segInfo.segmentAddr, segInfo.segmentSize, mOlProtection, &mOlProtection_1)==0) return false;

观察:

  1. 在修改内存之前,我使用 PAGE_EXECUTE_READWRITE 标志取消保护"该区域.
  2. Visual Studio 中的内存视图清楚地向我展示了该特定地址的价值.更奇怪的是,在第二次我从调试器手动修改值时,我的代码也能够更改该值.
  3. 示例代码中的temp变量包含值0xCC
  4. 在数百个其他字节的海洋中,这个字节实际上是唯一不变的.它是内存视图中唯一标记为黑色的字节(其余为红色,因为它们已更改)
  5. Dll 在 Debug/x86 中编译./MTd 标志设置.没有随机地址(/DYNAMICBASE : NO ,/FIXED: NO).没有整个程序优化.
  6. 未修改的字节不是变量.所以它不能未初始化".它实际上是一个非常重要的字节:它是指令操作码.一切都在该字节上崩溃.
  7. 解密例程(XOR 码)对错误没有影响.我进入代码并在 temp 到达 xor 之前查看它的值.这意味着解密密钥从未使用过,因此不会导致问题.
  8. 虚拟保护成功.
  1. Before I modify the memory, I "unprotect" the region with PAGE_EXECUTE_READWRITE flag.
  2. Memory View in visual studio clearly shows me the value at that particular address. Even weirder is that in the second I modify the value manually from the debugger, my code is also able to change that value.
  3. temp variable in the example code contains the value 0xCC
  4. This byte is literally the only one unchanged in a sea of hundred other bytes. It is the only byte marked black in Memory View (the rest are red because they were changed)
  5. Dll is compiled in Debug/x86 . /MTd flag set. No random address (/DYNAMICBASE : NO , /FIXED: NO). No Whole program optimization.
  6. The unmodified byte IS NOT a variable. So it can't be "uninitialized". It is actually a very important byte: it is the instruction opcode. Everything crashes on that byte.
  7. The decryption routine (XOR code) has no effect on the error. I step into the code and look at temp's value before it reaches the xor. This means the decryption key is never used and therefore it can't cause the problem.
  8. Virtual protect succeeds.


快照:


Visual Studio 可以读取地址

Visual studio can read the address


无法读取程序内的字节

我知道导致问题的不是该单个地址处的字节值(因为我发现其他具有相同值的字节已成功处理).也许字节仍然受保护"?

I know it's not the value of the byte at that single address that is causing problems (because I found other bytes with the same value that were processed successfully). Perhaps the byte is still "protected"?

为什么会这样?

推荐答案

你可以很好地处理一个非常常见的软件断点场景.软件断点实际上是通过用断点指令替换要断点的指令来设置的.

You could very well deal with a very common scenario of Software Breakpoints. Software breakpoints are in fact set by replacing the instruction to be breakpointed with a breakpoint instruction.

断点指令存在于大多数 CPU 中,并且通常与最短指令一样短,因此只有 x86 上的一个字节(0xCC,INT 3).

The breakpoint instruction is present in most CPUs, and usually as short as the shortest instruction, so only one byte on x86 (0xCC, INT 3).

由于我不知道您的源代码中是否有任何断点,我只能假设这是您的问题.

As I don't know if there are any breakpoints at all in your source I can only assume that this is your problem.

相关文章