如何使用 WinAPI/Win32 查找二进制文件中的序列?
How to find the sequence in the binary file using WinAPI/Win32?
我想识别二进制文件中的指定序列,如0001。文件打开并读取。
此外,文件的大小显示得很好。不幸的是,我无法制定检测规定序列的算法。我陷入了这个麻烦。有人有什么想法吗?
文件名和进程名等参数由命令提示符提供。
下面列出了代码。
int blockchain(wchar_t *box)
{
int i=0;
DWORD dwCounter=0;
BYTE buffer[BUFFERSIZE]={0};
HANDLE hFile = CreateFile(box, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile) {
wprintf(L"Error! Wrong file name!\n");
return -5;
}
if(FALSE==ReadFile(hFile, &buffer, BUFFERSIZE, &dwCounter, NULL)) {
wprintf(L"Terminal failure: Unable to read from file.\n");
CloseHandle(hFile);
return -5;
} else {
for(i;i<dwCounter;i++) {
if(wcscmp(buffer,L"0001") == 0)
wprintf(L"The data is found");
}
wprintf(L"\nData read from %s (%d bytes): \n", box, dwCounter);
}
CloseHandle(hFile);
return 0;
}
(仅回答因为我还没有代表发表评论。)
您在上面评论中的 memcmp
用法对我来说不太正确,原始问题中 wcscmp
的用法也不正确;你在每次测试后递增 i
,但每次都使用相同的缓冲区指针未修改 - 根据我的阅读,在这两种情况下你在每次通过时测试完全相同的字节( [=13 的最开始=]) 而不是继续加载您加载的数据。此外,对于 memcmp
情况,您使用的是 wchar_t
字符串文字 (L"0001"
);这在内存中的长度为 8 个字节,而不是您评论调用中的 4 个字节,因此比较仅针对前两个零。
此处正确的方法将取决于您处理的数据的性质。您是否试图在 ASCII 编码文件中查找字符序列 0001
,或在 Unicode 文件中查找 0001
(如用户所见),或十六进制字节 0x1
,或一些该表示的其他含义?如果它是 ASCII 文件中的字符序列,您可能正在寻找类似 if (memcmp(buffer + i, "0001", std::min((dwCounter - i), 4) == 0)
的内容来逐字节检查字符序列,遍历缓冲区并比较每次迭代中缓冲区中剩余的字节数.
但是,如果有合理可行的替代方案,我建议不要使用这样的线路。听起来您尝试做的事情也可以包含在问题 How to search in a BYTE array for a pattern? 中,我怀疑该问题的答案也可能比这种逐字节的方法表现得更好。或者,您可以考虑使用正则表达式实现(如果可用)并且您正在处理 character/text 数据,其中目标值可以通过正则表达式合理表达。
来自 https://pp.userapi.com/c849236/v849236424/46ac8/yy8w6ak1Ddc.jpg 我假设你想找到给定的字节序列。
所以看起来标准函数 strstr
无法工作,因为它无法处理 NUL 字节(等于 0)。
从匹配函数开始(你可以在下一个函数中内联它,为了清楚起见,我单独给出):
bool MatchBytes( const BYTE* a, const BYTE* b, int num_bytes )
{
return memcmp( a, b, num_bytes ) == 0;
}
编写查找序列的函数:
int FindBytesIndex(
const BYTE* find_in,
int num_bytes_in_find_in,
const BYTE* to_find,
int num_bytes_to_find )
{
int pos;
for ( pos = 0 ; pos <= num_bytes_in_find_in - num_bytes_to_find ; ++pos )
if ( MatchBytes( find_in + pos, to_find, num_bytes_to_find ) )
return pos;
return -1;
}
或者:
const BYTE* FindBytesPtr(
const BYTE* find_in,
int num_bytes_in_find_in,
const BYTE* to_find,
int num_bytes_to_find )
{
const BYTE* end = find_in + num_bytes_in_find_in - num_bytes_to_find;
for ( ; find_in < end ; ++find_in )
if ( MatchBytes( find_in, to_find, num_bytes_to_find ) )
return find_in;
return NULL;
}
用法:
BYTE bytes[] = { 0, 0, 0, 1 };
int num_bytes = 4;
int index = FindBytesIndex( buffer, dwCounter, bytes, num_bytes );
if ( index >= 0 )
printf( "Found at index %d\n", index );
else
printf( "Not found\n" );
如果你想要所有的出现:
BYTE bytes[] = { 0, 0, 0, 1 };
int num_bytes = 4;
int index = 0;
int count = 0;
/* There is assigment in loop condition. Found index is assigned to "index" variable */
/* then it is checked if >= 0 */
while ( ( index = FindBytesIndex(buffer + index, dwCounter - index, bytes, num_bytes) ) >= 0 )
{
printf( "Found at index %d\n", index );
++count;
}
if ( count > 0 )
printf( "Found %d occurrences\n", count );
else
printf( "Not found\n" );
您使用的上面显示的算法称为 "naive pattern searching"。如果太慢,您可以 google 更快的算法 "Boyer-Moore"、"Rabin-Karp"、"KMP" ("Knuth-Morris-Pratt").
我想识别二进制文件中的指定序列,如0001。文件打开并读取。 此外,文件的大小显示得很好。不幸的是,我无法制定检测规定序列的算法。我陷入了这个麻烦。有人有什么想法吗? 文件名和进程名等参数由命令提示符提供。 下面列出了代码。
int blockchain(wchar_t *box)
{
int i=0;
DWORD dwCounter=0;
BYTE buffer[BUFFERSIZE]={0};
HANDLE hFile = CreateFile(box, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile) {
wprintf(L"Error! Wrong file name!\n");
return -5;
}
if(FALSE==ReadFile(hFile, &buffer, BUFFERSIZE, &dwCounter, NULL)) {
wprintf(L"Terminal failure: Unable to read from file.\n");
CloseHandle(hFile);
return -5;
} else {
for(i;i<dwCounter;i++) {
if(wcscmp(buffer,L"0001") == 0)
wprintf(L"The data is found");
}
wprintf(L"\nData read from %s (%d bytes): \n", box, dwCounter);
}
CloseHandle(hFile);
return 0;
}
(仅回答因为我还没有代表发表评论。)
您在上面评论中的 memcmp
用法对我来说不太正确,原始问题中 wcscmp
的用法也不正确;你在每次测试后递增 i
,但每次都使用相同的缓冲区指针未修改 - 根据我的阅读,在这两种情况下你在每次通过时测试完全相同的字节( [=13 的最开始=]) 而不是继续加载您加载的数据。此外,对于 memcmp
情况,您使用的是 wchar_t
字符串文字 (L"0001"
);这在内存中的长度为 8 个字节,而不是您评论调用中的 4 个字节,因此比较仅针对前两个零。
此处正确的方法将取决于您处理的数据的性质。您是否试图在 ASCII 编码文件中查找字符序列 0001
,或在 Unicode 文件中查找 0001
(如用户所见),或十六进制字节 0x1
,或一些该表示的其他含义?如果它是 ASCII 文件中的字符序列,您可能正在寻找类似 if (memcmp(buffer + i, "0001", std::min((dwCounter - i), 4) == 0)
的内容来逐字节检查字符序列,遍历缓冲区并比较每次迭代中缓冲区中剩余的字节数.
但是,如果有合理可行的替代方案,我建议不要使用这样的线路。听起来您尝试做的事情也可以包含在问题 How to search in a BYTE array for a pattern? 中,我怀疑该问题的答案也可能比这种逐字节的方法表现得更好。或者,您可以考虑使用正则表达式实现(如果可用)并且您正在处理 character/text 数据,其中目标值可以通过正则表达式合理表达。
来自 https://pp.userapi.com/c849236/v849236424/46ac8/yy8w6ak1Ddc.jpg 我假设你想找到给定的字节序列。
所以看起来标准函数 strstr
无法工作,因为它无法处理 NUL 字节(等于 0)。
从匹配函数开始(你可以在下一个函数中内联它,为了清楚起见,我单独给出):
bool MatchBytes( const BYTE* a, const BYTE* b, int num_bytes )
{
return memcmp( a, b, num_bytes ) == 0;
}
编写查找序列的函数:
int FindBytesIndex(
const BYTE* find_in,
int num_bytes_in_find_in,
const BYTE* to_find,
int num_bytes_to_find )
{
int pos;
for ( pos = 0 ; pos <= num_bytes_in_find_in - num_bytes_to_find ; ++pos )
if ( MatchBytes( find_in + pos, to_find, num_bytes_to_find ) )
return pos;
return -1;
}
或者:
const BYTE* FindBytesPtr(
const BYTE* find_in,
int num_bytes_in_find_in,
const BYTE* to_find,
int num_bytes_to_find )
{
const BYTE* end = find_in + num_bytes_in_find_in - num_bytes_to_find;
for ( ; find_in < end ; ++find_in )
if ( MatchBytes( find_in, to_find, num_bytes_to_find ) )
return find_in;
return NULL;
}
用法:
BYTE bytes[] = { 0, 0, 0, 1 };
int num_bytes = 4;
int index = FindBytesIndex( buffer, dwCounter, bytes, num_bytes );
if ( index >= 0 )
printf( "Found at index %d\n", index );
else
printf( "Not found\n" );
如果你想要所有的出现:
BYTE bytes[] = { 0, 0, 0, 1 };
int num_bytes = 4;
int index = 0;
int count = 0;
/* There is assigment in loop condition. Found index is assigned to "index" variable */
/* then it is checked if >= 0 */
while ( ( index = FindBytesIndex(buffer + index, dwCounter - index, bytes, num_bytes) ) >= 0 )
{
printf( "Found at index %d\n", index );
++count;
}
if ( count > 0 )
printf( "Found %d occurrences\n", count );
else
printf( "Not found\n" );
您使用的上面显示的算法称为 "naive pattern searching"。如果太慢,您可以 google 更快的算法 "Boyer-Moore"、"Rabin-Karp"、"KMP" ("Knuth-Morris-Pratt").