Я пытаюсь сканировать сигнатуру вируса в двоичном файле (без использования 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;
}
А как насчет минимальный воспроизводимый пример?
Отвечает ли это на ваш вопрос? fgetc не идентифицирует EOF
<O/T> никогда не используйте строковые функции (например, strstr
) при работе с двоичными данными. Строковые функции останавливаются, когда видят 0. В двоичных данных 0 абсолютно допустим. Я не смотрел внимательно на ваш код, но если вы ищете точную последовательность байтов, вам, вероятно, понадобится memcmp
Но почему нет memmem
?
Обратите внимание, что fgetc
возвращает int
, потому что EOF
равно -1. Когда вы приводите результат к char
, байт данных законный 0xFF будет имитировать [ранний] EOF. Удалите приведение (char)
и используйте int ch;
Приведение возвращаемого значения fgetc
к char
фактически заставляет код запускать помедленнее на некоторых/большинстве процессоров.
По крайней мере эти проблемы
Успех слишком поздно
counter == v_size
может быть правдой сразу после counter++;
. В файле может не быть другого символа для следующего цикла if (counter == v_size)
. Вместо этого проверьте counter == v_size
сразу после увеличения.
Без сброса
Если найдено только частичное совпадение, проверка соответствия не должна возобновляться для следующего символа исходного файла, а должна вернуться к началу сравнения, а затем перейти на 1.
Рассмотреть возможность:
search file: "aaac"
virus: "aac"
Поиск файл поиска завершается ошибкой на "aa(a)..." (3-й "a"), но должен быть возобновлен на "a(a)" (2-й "a").
Вирусный файл должен rewind()
при неудачном совпадении. Я рекомендую читать всю сигнатуру вируса в выделенную память (например: unsigned char *virus = malloc(v_size);
вместо повторного чтения из файла.
Потеря информации
int fgetc()
возвращает 257 различных значений: 0-255 и EOF
. Сохранение этого результата в char
приводит к потере информации. Используйте int ch = fgetc(...)
, int ch2 = fgetc(...)
.
Это может объяснить, что «код OP не работает, даже когда я пытаюсь сканировать саму сигнатуру вируса». так как один из байтов вируса ошибочно соответствует EOF
при преобразовании в char
.
Приведения не нужны, чтобы решить эту проблему.
Неправильная длина типа
ftell(virus)
возвращает 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 (размер_теста * размер_вируса). Более сложная «прогулка» — это O(test_size + virus_size).
Я считаю, что v_size > f_size
предназначен для ярлыка - если вирус больше, чем файл, файл не может его содержать. Это может быть не обязательно, но позволяет избежать сравнения байтов, когда это может привести только к сбою.
@Dave Meehan, согласен с тем, почему OP сделал это, но это остается бесполезным. Это стоит fseek(file_to_search, 0L, SEEK_END);
, что может быть довольно дорого.
Можете ли вы уточнить, что «не работает» в этом коде?