如何使用 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").