修改内存区域 - returns 0xCC VC++
Modifying region of memory - returns 0xCC VC++
我正在修改在 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;
观察:
- 在我修改内存之前,我"unprotect"带有
PAGE_EXECUTE_READWRITE
标志的区域。
- visual studio 中的内存视图清楚地显示了该特定地址的值。更奇怪的是,在第二次我从调试器手动修改值时,我的代码也能够更改该值。
temp
示例代码中的变量包含值 0xCC
- 这个字节实际上是数百个其他字节中唯一不变的字节。它是内存视图中唯一标记为黑色的字节(其余为红色,因为它们被更改)
- Dll 在 Debug/x86 中编译。 /MTd 标志设置。无随机地址(/DYNAMICBASE : NO , /FIXED: NO)。没有整个程序优化。
- 未修改的字节不是变量。所以不可能是"uninitialized"。它实际上是一个非常重要的字节:它是指令操作码。一切都在那个字节上崩溃。
- 解密例程(异或码)对错误没有影响。我进入代码并在
temp
到达 xor
之前查看它的值。这意味着从未使用过解密密钥,因此不会导致问题。
- 虚拟保护成功。
快照:
Visual studio可以读取地址
无法读取程序中的字节
我知道导致问题的不是单个地址处的字节值(因为我发现具有相同值的其他字节已成功处理)。也许字节仍然是"protected"?
为什么会这样?
您可以很好地处理 Software Breakpoints
的非常常见的情况。
Software breakpoints
实际上是通过将要断点的指令替换为断点指令来设置的。
断点指令存在于大多数CPU中,并且通常与最短指令一样短,所以只有one byte on x86 (0xCC, INT 3)
。
因为我不知道你的源代码中是否有任何断点,我只能假设这是你的问题。
我正在修改在 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;
观察:
- 在我修改内存之前,我"unprotect"带有
PAGE_EXECUTE_READWRITE
标志的区域。 - visual studio 中的内存视图清楚地显示了该特定地址的值。更奇怪的是,在第二次我从调试器手动修改值时,我的代码也能够更改该值。
temp
示例代码中的变量包含值0xCC
- 这个字节实际上是数百个其他字节中唯一不变的字节。它是内存视图中唯一标记为黑色的字节(其余为红色,因为它们被更改)
- Dll 在 Debug/x86 中编译。 /MTd 标志设置。无随机地址(/DYNAMICBASE : NO , /FIXED: NO)。没有整个程序优化。
- 未修改的字节不是变量。所以不可能是"uninitialized"。它实际上是一个非常重要的字节:它是指令操作码。一切都在那个字节上崩溃。
- 解密例程(异或码)对错误没有影响。我进入代码并在
temp
到达xor
之前查看它的值。这意味着从未使用过解密密钥,因此不会导致问题。 - 虚拟保护成功。
快照:
我知道导致问题的不是单个地址处的字节值(因为我发现具有相同值的其他字节已成功处理)。也许字节仍然是"protected"?
为什么会这样?
您可以很好地处理 Software Breakpoints
的非常常见的情况。
Software breakpoints
实际上是通过将要断点的指令替换为断点指令来设置的。
断点指令存在于大多数CPU中,并且通常与最短指令一样短,所以只有one byte on x86 (0xCC, INT 3)
。
因为我不知道你的源代码中是否有任何断点,我只能假设这是你的问题。