写入和读取struct to file

时间:2016-05-09 16:59:34

标签: c++ winapi serialization struct binary

我在尝试将结构保存到新的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显示奇怪的符号。

1 个答案:

答案 0 :(得分:4)

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

您需要将字符串与结构分开保存。阅读起来很简单,因为您拥有可变长度数据的大小,并且您知道数据的保存位置(与结构相关)。

来自伯劳的评论让我思考并仔细研究你所呈现的代码。它不完整,所以这都是猜测工作,但实际问题实际上可能与我上面描述的不同。

让我们来看看你的#34;阅读"代码(实际上并没有显示任何读数):

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(类似于您在编写时使用的方式,但实际上并不需要),那么您对上面提到的指针仍有同样的问题,但是还有另一个问题:你重新分配指针指向一些新分配的内存。这一切都很好,但问题在于你实际上并没有尝试初始化那个记忆。并不是说你真的可以使用你展示的代码,但这不是重点。你没有初始化内存的问题恰恰是它没有初始化,因此会有一个不确定的内容,看似随机,很可能不是有效的文本。使用未初始化的内存就像解除引用指针一样,未定义的行为

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

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

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