为什么这个简单的C程序被检测为病毒?

19

我编写了这个程序:

#include <stdio.h>

main()
{
  int n;
  n=1;
  while (n>0)
  {
    puts("Write a number: ");
    scanf(" %d",&n);
    printf("This is the number you wrote: %d\n", n);
  }

}

显然没有任何语法错误或编译错误。它已经编译且构建完美。

现在,如果我更改这行:

puts("Write a number: ");

使用这个:

printf("Write a number: ");

编译没有错误,但当编译后的对象启动时,立即停止,并弹出反病毒警告,说它发现了特洛伊木马。在得出任何结论之前,我建立了几次,并在收到相同消息后在virustotal.com上扫描了它,并获得了这个结果。

虽然从目的上来说,putsprintf更正确,但仍然应该可以正常工作。

问题出在哪里?

我正在使用AVG防病毒软件和Pelles C编译器。


10
此问题似乎不属于主题,因为它涉及到反病毒软件中的一个漏洞。 - Kuba hasn't forgotten Monica
7
AVG有问题。这就是问题所在。或者你已经被感染了。 - Kuba hasn't forgotten Monica
6
在作者提供的链接中,许多杀毒工具都将其标记为病毒。这不仅仅是AVG。 - user2864740
3
如果使用不同的编译器,会发生相同的事情吗? - Christian Ternus
2
AVG 喜欢将自己检测为病毒。 - Dave Rager
显示剩余13条评论
3个回答

6

这显然是误报。生成的机器代码恰好与恶意软件数据库中的代码相似,与使用puts()无关。


当然与puts有关。编译后,puts生成的代码可以在恶意软件数据库中被识别。但是我明白你的意思。无论如何,它应该能够工作,但实际上并没有,这才是重点。 - K09P

5

杀毒软件通过病毒签名来工作,这些签名基本上是病毒软件中已知的可执行代码模式。

一些野生病毒与你编写的printf版本的代码有相似的模式(我搜索了所有标记你为病毒的人,不幸的是他们没有公布他们的签名文件在检查什么)。由于你永远不应该使用单个参数调用printf,许多杀毒软件提供商可能将其作为其签名过程的一部分。

你有两个选择:不要使用单个参数调用printf(无论如何都不应该这样做),或者将您的程序提交为虚警给杀毒软件供应商,并更新他们的签名以排除您的程序虚警。


3
OP这样使用printf有什么问题吗?这里的printf参数是一个字符串字面值。我没看出有什么问题。 - Raja
@Raja 它的问题在于它会导致杀毒软件出现误报。如果有不会出现误报的替代方案(puts),我会使用那个替代方案。 - Scott Chamberlain
2
是的,我明白了那一部分 - 但为什么这会有危险(或者这怎么成为病毒签名的?) - Raja
@Raja 像我说的那样,我试图找到任何错误的解释以查看它们匹配的内容,但我找不到。我不知道它们匹配的是什么,但编译后的代码匹配了它们。 - Scott Chamberlain
@Raja 代码在不知道 scanf(" %d",&n); 成功执行的情况下打印了 n,这将导致未定义行为。 - chux - Reinstate Monica

1

printf()存在未受控制的格式化字符串安全风险

应该使用puts()。

同时发现:

请参阅C语言中printf()和puts()有什么区别?中的评论。

关于使用printf而不是puts的注意事项:永远不要使用printf(variable)来打印字符串。使用puts(variable)或printf("%s', variable)。使用变量格式字符串存在安全风险:如果变量可以被攻击者写入,他们可以通过使用格式字符串攻击程序。- Zan Lynx Dec 1 '12 at 9:05


12
所有这些格式字符串都不是不受控制的--无论它有多正确,在这里都不相关。 - jthill
我知道它们之间的差别。但我仍不认为这有多大意义...谢谢! - K09P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接