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

时间:2019-04-25 23:33:32

标签: c++ visual-studio-2017 self-modifying

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

代码很简单:

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!\n");
    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. 示例代码中的
  4. temp变量包含值0xCC
  5. 从字面上看,该字节是其他数百个字节中唯一不变的一个字节。这是“内存视图”中唯一标记为黑色的字节(其余均为红色,因为它们已更改)
  6. Dll在Debug / x86中编译。 / MTd标志设置。没有随机地址(/ DYNAMICBASE:NO,/ FIXED:NO)。否整个程序优化。
  7. 未修改的字节不是变量。因此它不能被“未初始化”。它实际上是一个非常重要的字节:它是指令操作码。一切都在那个字节上崩溃了。
  8. 解密例程(XOR代码)对错误没有影响。我进入代码,在temp到达xor之前先看一下它的值。这意味着永远不会使用解密密钥,因此不会导致问题。
  9. 虚拟保护成功。


快照The black byte cannot be read or written to although visaul studio can display it


Visual studio can read the address Visual Studio可以读取地址



Can't read byte inside program 无法读取程序内部的字节


我知道不是单个地址上的字节值引起了问题(因为我发现其他具有相同值的字节已被成功处理)。也许字节仍然是“受保护的”?

为什么会这样?

1 个答案:

答案 0 :(得分:3)

您可以很好地处理Software Breakpoints的非常常见的情况。 实际上,Software breakpoints是通过用断点指令替换要断点的指令来设置的。

断点指令存在于大多数CPU中,通常与最短指令一样短,因此只有one byte on x86 (0xCC, INT 3)

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