【发布时间】:2019-04-25 23:33:31
【问题描述】:
我正在修改在 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;
观察:
- 在修改内存之前,我使用
PAGE_EXECUTE_READWRITE标志“取消保护”该区域。 - Visual Studio 中的内存视图清楚地显示了该特定地址的值。更奇怪的是,在第二次我从调试器手动修改值时,我的代码也能够更改该值。
-
示例代码中的
temp变量包含值0xCC - 在数百个其他字节的海洋中,这个字节实际上是唯一不变的。它是内存视图中唯一标记为黑色的字节(其余为红色,因为它们已更改)
- Dll 在 Debug/x86 中编译。 /MTd 标志设置。没有随机地址(/DYNAMICBASE : NO , /FIXED: NO)。没有整个程序优化。
- 未修改的字节不是变量。所以它不能“未初始化”。它实际上是一个非常重要的字节:它是指令操作码。一切都在该字节上崩溃。
- 解密例程(XOR 码)对错误没有影响。我进入代码并查看
temp的值,然后它才到达xor。这意味着解密密钥从未使用过,因此不会导致问题。 - 虚拟保护成功。
我知道导致问题的不是该单个地址处的字节值(因为我发现其他具有相同值的字节已成功处理)。也许字节仍然“受保护”?
为什么会这样?
【问题讨论】:
-
您的解密密钥中是否包含几个零字节?
-
您能否提供更多上下文以及我们可以编译并用于测试的短代码?
-
不,密钥不包含零。关于编译:我无法提供任何附加代码。但我只想知道这一点:virtualprotect 没有隐藏的“功能”或其他明显的内存行为会产生此错误。如果我提供的代码通常不会产生这个错误,至少你已经给我提供了一个线索:错误在别的地方,埋在我的代码中。
-
Visual Studio 在什么情况下会返回 0xCC ?我发现了一些与 unitializd 内存有关的东西。会这样吗?
标签: c++ visual-studio-2017 self-modifying