扫描二进制文件以查找病毒签名

Scanning binary files for a virus signature

我正在尝试扫描二进制文件中的病毒签名(不使用 strstr()),并打印是否找到签名。但是代码不起作用。我读取了函数之外的文件。

不幸的是,即使我尝试扫描病毒签名本身,代码也不起作用。

int searchForSignature(FILE* file_to_search, FILE* virus) {
    int v_size = 0;
    int f_size = 0;


    fseek(virus, 0L, SEEK_END);
    v_size = ftell(virus);
    fseek(virus, 0, SEEK_SET);
    fseek(file_to_search, 0L, SEEK_END);
    f_size = ftell(file_to_search);
    fseek(file_to_search, 0, SEEK_SET);

    printf("VIRUS SIZE: %d FILE SIZE: %d\n", v_size, f_size);

    if (v_size > f_size)
    {
        printf("VIRUS NOT FOUND\n");
        return 1;
    }

    int counter = 0;  char ch = ' '; char ch2 = ' ';
    while ((ch = (char)fgetc(file_to_search)) != EOF)
    {
        printf("%d\n", counter);
        if (counter == v_size)
        {
            printf("VIRUS FOUND\n");
            return 0;
        }
        else
        {
            ch2 = (char)fgetc(virus);
            if (ch == ch2)
            {
                counter++;
            }
            else
            {
                counter = 0;
            }
        }
    }

    printf("VIRUS NOT FOUND\n");
    return 1;
}

我如何读取函数外的文件:

FILE* virus_file = NULL;
virus_file = fopen("example file path", "rb");
if (virus_file == NULL)
{
    printf("Error opening file");
    return 1;
}

FILE* file_to_scan = NULL;
file_to_scan = fopen("example file path 2", "rb");
if (file_to_scan == NULL)
{
    printf("Error opening file");
    return 1;
}

至少这些问题:

来不及成功

counter == v_size 可能在 counter++; 之后为真。对于下一个循环的 if (counter == v_size),文件中可能不存在另一个字符。而是在递增后立即测试 counter == v_size

不重置

如果只找到部分匹配,匹配测试不应该在下一个源文件字符上继续,而是回到比较的开始,然后前进1。

考虑:

search file: "aaac"
virus:       "aac"

搜索搜索文件 在“aa(a)...”(第 3 个 'a')上失败,但需要在“a(a)”上继续(第二个'a').

病毒文件需要rewind()匹配失败。我建议将整个病毒签名读入分配的内存(例如:unsigned char *virus = malloc(v_size); 而不是从文件中 re-reading。

信息丢失

int fgetc() returns 257 个不同的值:0-255 和 EOF。将该结果保存在 char 中会丢失信息。使用 int ch = fgetc(...)int ch2 = fgetc(...).

这可以解释 OP 的“代码不工作,即使我尝试扫描病毒签名本身。”因为其中一个病毒字节在转换为 char.

时错误匹配 EOF

不需要转换来解决这个问题。

类型长度错误

ftell(virus)returns一个long。将结果保存在 int 中可能会丢失信息。此处代码也缺少错误检查。

不需要的代码

if (v_size > f_size) 块不需要。


备选

// Pseudo code
Read virus into an allocated buffer.
Read a chunk of test file into a test buffer at least 2x virus size.
Walk test buffer (1 char at a time) trying `memcmp()`. 
  Stop if match found,
  until remaining test buffer not full enough for a possible match.
Move remaining test buffer to start and re-fill as able.
If not able to re-fill at all, we are done - no match.

这是 O(test_size * virus_size)。更复杂的“行走”是 O(test_size + virus_size).