【发布时间】:2020-11-16 01:02:45
【问题描述】:
我是一名学生,对 C++ 和安全性还很陌生。我接到了一项关于检查文件中的签名/幻数的任务,但我在加快阅读时间方面遇到了一点问题。
我的想法是使用 ifstream 以二进制模式读取文件,将其数据存储在向量中,然后将其转换为十六进制字符串。最后,我将检查给定的签名是否存在于十六进制字符串中。
理论上一切正常,只是分配向量内存、读取和转换文件数据的整个过程需要很长时间。只有读取部分需要 44ms。
我想知道如何改进这一点?这是我的代码
UINT CheckForSignature(CString source, CString dest_path) {
// source is the HEX string need to find in file, dest_path is the destination of the file
ifstream file(dest_path, ios::binary);
if (file.is_open()) {
// check for size of the file
file.seekg(0, ios::end);
int iFileSize = file.tellg();
// if the file size exceed 50MB, pass
if (iFileSize > 50000000) {
// return -1, means file exceed 50MB, which do not need to be checked
return -1;
}
// read file and store data in hex string
file.seekg(0, ios::beg);
vector<char> memblock(iFileSize);
file.read(((char*)memblock.data()), iFileSize); // 18ms alloc memory
ostringstream ostrData; // 44ms read file
// add to a total of 62ms
// if consider the time need to translate all the memblock
// then this will be long as hell
// need to improve this
for (int i = 0; i < memblock.size(); i++) {
int z = memblock[i] & 0xff;
ostrData << hex << setfill('0') << setw(2) << z;
}
string strDataHex = ostrData.str();
string strHexSource = (CT2A)source;
if (strDataHex.find(strHexSource) != string::npos) {
// return 1, means there exits the signature in the file
return 1;
}
else {
// return 0; means there isn't the signature in the file
return 0;
}
}
}
我愿意接受有关解决方案和代码改进的所有帮助和建议。非常感谢!
【问题讨论】:
-
您为什么不使用
std::hex读取文件,并且只保留足够的数据来在您读取时检查签名?然后您可以避免存储数据,或从 bin 转换为 hex。 -
提示:如果你不能从文件的前 1024 个字节中找出幻数,你可能做的太多了。
-
为什么还要乱用十六进制表示?只需将少量字节存储在
std::byte数组/向量中。十六进制表示是等效字节表示的 2 倍,因此您需要两倍的内存和比较,但没有明显的好处。 -
我正在尝试检测文件中开头可能没有幻数的签名。例如,一个包含 PNG 图像的 *.doc 文件将在其中某处有一个字符串 89504E470D0A1A0A,但不是第一个字符。这就是为什么我想转换整个文件而不是只检查一些开始位。
标签: c++ performance magic-numbers