我需要在二进制文件中搜索二进制模式,我该怎么做呢?
我尝试使用"strstr()"函数并将文件和模式转换为字符串,但它不起作用。
(模式也是一个二进制文件)这是它所尝试的:
void isinfected(FILE *file, FILE *sign, char filename[], char filepath[])
{
char* fil,* vir;
int filelen, signlen;
fseek(file, 0, SEEK_END);
fseek(sign, 0, SEEK_END);
filelen = ftell(file);
signlen = ftell(sign);
fil = (char *)malloc(sizeof(char) * filelen);
if (!fil)
{
printf("unseccesful malloc!n");
}
vir = (char *)malloc(sizeof(char) * signlen);
if (!vir)
{
printf("unseccesful malloc!n");
}
fseek(file, 0, SEEK_CUR);
fseek(sign, 0, SEEK_CUR);
fread(fil, 1, filelen, file);
fread(vir, 1, signlen, sign);
if (strstr(vir, fil) != NULL)
log(filename, "infected",filepath );
else
log(filename, "not infected", filepath);
free(vir);
free(fil);
}
对于任何二进制处理,您应该永远不要使用strXX
函数之一,因为这些函数只(并且唯一地)用于c风格的零终止字符串。您的代码失败了,因为strXX
函数无法看到它们遇到的第一个二进制0。
由于您对strstr
的基本想法似乎是正确的(并且只有失败,因为它仅适用于零终止字符串),您可以将其替换为memmem
,这在任意数据上也是如此。由于memmem
是一个GNU C扩展(参见memmemm作为GNU扩展有什么特殊的原因吗?),它可能在您的系统上不可用,您需要编写代码来做同样的事情。
对于memmem
的一个非常基本的实现,您可以使用memchr
来扫描第一个二进制字符,如果发现了什么,然后使用memcmp
:
void * my_memmem(const void *big, size_t big_len, const void *little, size_t little_len)
{
void *iterator;
if (big_len < little_len)
return NULL;
iterator = (void *)big;
while (1)
{
iterator = memchr (iterator, ((unsigned char *)little)[0], big_len - (iterator-big));
if (iterator == NULL)
return NULL;
if (iterator && !memcmp (iterator, little, little_len))
return iterator;
iterator++;
}
}
可能有更好的实现,但除非memmem
是程序中的一个重要函数,否则它将很好地完成工作。
基本思想是检查vir
是否与fil
的开头匹配。如果没有,则再次检查,从fil
的第二个字节开始,重复检查,直到找到匹配项或到达fil
的末尾。(这基本上是strstr
的一个简单实现所做的,除了strstr
将0字节视为特殊情况。)
int i;
for (i = 0; i < filelen - signlen; ++i) {
if (memcmp(vir, fil + i, signlen) == 0) {
return true; // vir exists in fil found
}
}
return false; // vir is not in file
这是"蛮力"方法。如果你的文件很长,它会变得很慢。有一些先进的搜索算法可以使搜索速度更快,但这是一个很好的起点。