我有一个从这段代码编译的非常小的 exe(调试,没有优化):
struct some_data
{
unsigned long long a;
unsigned long long b;
}
int main ()
{
constexpr some_data {0x1234567890abcdef, 0xabcdabcdabcdabcd}
cout << some_data.a << endl;
return 0;
}
现在我想制作另一个程序,它会在第一个 exe 中找到值 0x1234567890abcdef,并将其替换为 0x111111111111111,然后保存 exe,所以下次我运行它时,我会得到“注入(inject)的”0x111111111111111 作为输出。
我编写了一个简单的程序来执行以下操作:
uint64_t key = 0x1234567890abcdef;
uint64_t value;
fstream file ("file", ios::in| ios::out | ios::binary);
if (file.is_open())
{
while (not_end_of_file) {
file.read (&value, sizeof(value));
if (value == key) {
//code that overwrittes the old value with new
}
}
它确实工作了一两次让我很高兴,但是在我向第一个项目添加一些代码并重建它之后,替换(第二个项目)突然停止工作。在停止输入代码的 if (value == key) 部分。我认为发生这种情况的原因是,在添加一些代码后,.data 部分中的结构在文件中向前移动了几个字节,现在当读取 8 字节的 block 时,它不再像这样在一个 block 中(little_endianess)
XX XX XX ef cd ab 90 78 one read operation
56 34 12 XX XX XX XX XX the next read operation
你觉得是这样吗?我可以期望 .data 和 .rdata 部分以任何可靠的方式对齐吗?您将如何实现将这种转变考虑在内的检查?或者,也许有人对如何轻松地以编程方式更改此值有完全不同的想法。
最好的问候 马尔辛
最佳答案
这可能看起来有点贫民窟,但您可以将整个文件加载到字节数组中,然后像这样将字节取消引用到 uint64_t:
(是的,抱歉,我没有包含完整的代码,但这应该给你一个想法/清楚)
byte* bytes = new byte[filesizeinbytes];
//read to the byte array
then:
DWORD offset = 0;
while( *(uint64_t*)((DWORD)bytes+offset) != 0x1234567890abcdef )
{
offset++;
}
//We found the right address, so we can replace the bytes/address/offset
*(uint64_t*)((DWORD)bytes+offset) = 0x111111111111111;
//write the entire file, starting from bytes till the end of the file
delete[] bytes; // free the allocated memory
bytes = 0;
关于c++ - 从 exe 的 .data 和 .rdata 读取值。字节对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42213469/