【问题标题】:Write and read struct to file将结构写入和读取到文件
【发布时间】:2016-09-04 10:09:32
【问题描述】:

我在尝试将结构保存到新的 PE 部分然后阅读时遇到问题。 结构如下:

    #pragma pack(push, 1)
typedef struct _SCRIPT_STRUCT
{
     DWORD dwKeySize;
     unsigned char *lpKeyBuffer;
     DWORD dwScriptSize;
     unsigned char *lpScriptBuffer;
} SCRIPT, *PSCRIPT;
#pragma pack(pop)

lpKeyBuffer 是一个随机的十六进制值 (0-255) 数组,lpScriptBuffer 包含一个加密的 (RC4) 脚本(如果重要的话,在 Lua 中)。

我认为结构已成功写入创建的新部分,但我无法读取缓冲区。

(写作):

SCRIPT tScript;

tScript.dwKeySize = KEY_SIZE;
tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
GenerateKey(tScript.lpKeyBuffer, KEY_SIZE);

tScript.dwScriptSize = szScript.size();
tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
memcpy(tScript.lpScriptBuffer, szScript.c_str(), tScript.dwScriptSize);
tScript.lpScriptBuffer = (unsigned char*)szScript.c_str();

rc4_encryption(tScript.lpScriptBuffer, tScript.dwScriptSize, tScript.lpKeyBuffer, tScript.dwKeySize);

DWORD dwScriptStructSize = sizeof(DWORD) + tScript.dwKeySize + sizeof(DWORD) + tScript.dwScriptSize;
char lpStructBuffer[dwScriptStructSize];
ZeroMemory(lpStructBuffer, dwScriptStructSize);
memcpy(lpStructBuffer, &tScript, dwScriptStructSize);

//CreateFile, create new section, etc
SetFilePointer(hCurrent, LastHeader->PointerToRawData, NULL, FILE_BEGIN);
WriteFile(hCurrent, lpStructBuffer, dwScriptStructSize, &dwRead, 0);

(阅读):

SCRIPT tScript;
memcpy(&tScript, lpScriptBuffer, dwSectionSize);

tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
tScript.lpKeyBuffer[tScript.dwKeySize] = 0x00;

tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
tScript.lpScriptBuffer[tScript.dwScriptSize] = 0x00;

printf("dwScriptSize = %lu\n", tScript.dwScriptSize);
printf("dwKeySize = %lu\n", tScript.dwKeySize);
rc4_encryption(tScript.lpScriptBuffer, tScript.dwScriptSize, tScript.lpKeyBuffer, tScript.dwKeySize);

printf("script: %s\n", tScript.lpScriptBuffer);

DWORD 输出正确,但最后一个 printf 显示奇怪的符号。

【问题讨论】:

  • 谷歌“C++ 序列化”。
  • char lpStructBuffer[dwScriptStructSize]; 不是标准 C++。

标签: c++ winapi serialization struct binary


【解决方案1】:

您不能从一个进程保存指向文件的指针,然后从另一个进程读取它们并期望它能够工作。每个进程的指针通常是唯一的,尤其是对于动态分配的数据。当您从另一个进程(即使它是同一个程序)的文件中读取指针时,该指针将不再指向分配的数据,它将只是一个“随机”杂散指针,并取消引用它(就像您在打印时所做的那样它作为一个字符串)将导致未定义的行为

您需要将字符串与结构分开保存。读取时很容易,因为您拥有可变长度数据的大小,并且您知道数据保存在哪里(相对于结构)。


来自 shrike 的评论让我思考并仔细查看了您提供的代码。它不完整,所以这都是猜测,但实际问题实际上可能与我上面描述的有所不同。

让我们看一下“阅读”代码中的几行代码(实际上并没有显示任何阅读内容):

SCRIPT tScript;
memcpy(&tScript, lpScriptBuffer, dwSectionSize);

tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
tScript.lpKeyBuffer[tScript.dwKeySize] = 0x00;

tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
tScript.lpScriptBuffer[tScript.dwScriptSize] = 0x00;

现在假设您将结构读入字符缓冲区lpScriptBuffer(类似于您在写入时使用一个,虽然不是真正需要的),那么您仍然对我上面提到的指针有同样的问题,但是有另一个问题:您重新分配指针以指向一些新分配的内存。这一切都很好,但这里的问题是您实际上并没有尝试初始化该内存。并不是说您真的不能使用您显示的代码,但这不是重点。您未初始化内存的问题恰恰在于,它未初始化,因此将具有 indeterminate 内容,看似随机且很可能不是有效文本。使用未初始化的内存,就像取消引用杂散指针一样,未定义的行为


还有一个另一个问题:你写的内存超出了你分配的范围。如您所知,数组中的索引是从零开始的。因此,如果您分配 size 字节,则有效索引是从(包括)0size - 1

因为你分配例如tScript.dwKeySize 字节的内存,那么顶部索引是 tScript.dwKeySize - 1,但随后您使用 tScript.dwKeySize 作为索引,这超出了范围,并且会再次导致未定义的行为。

如果大小尚未包含字符串终止符,则需要分配 tScript.dwKeySize + 1 字节。

【讨论】:

  • 我怀疑这一点,但我不知道该怎么做。
  • @Joachim:OP 没有写指向文件的指针,他正在写一个char lpStructBuffer[dwScriptStructSize],这可能是格式正确的。问题更可能出现在读取部分。
  • @shrike 不,格式不正确:memcpy(lpStructBuffer, &tScript, dwScriptStructSize);。但是你有一个观点,让我仔细查看了所提供的代码,现在告诉我一些不同的东西,所以你指出了我(希望)正确的方向。现在正在编辑答案。谢谢。 :)
  • @J.Doe 用一些 other 问题更新了我的答案。
  • 我也尝试设置 +1 大小的缓冲区,但没有奏效。我正在尝试用你写的很棒的回答来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 2015-01-09
相关资源
最近更新 更多