1

我一直在使用 vb.net 开发防病毒软件。病毒扫描程序工作正常,但我正在考虑优化扫描速度的方法(因为大文件需要很长时间)。

我用来检测病毒的算法是通过二进制(转换为十六进制)签名。我想我不必为了查找它是否是病毒而查看整个文件,我认为我应该扫描一个特定的位置和特定数量的字节,而不是扫描整个文件。无论如何,如果有人可以在这个主题上提供任何帮助,请这样做。

提前致谢。

顺便说一句,病毒签名来自 clamAv 防病毒软件的十六进制集合......

4

2 回答 2

1

那么这一切都取决于,病毒签名的定义是什么?
我建议您解析可执行文件并仅使用code-section
但是多态病毒以加密形式将恶意代码保存在数据部分中。所以我不是很确定。
你在使用某种 n-gram 技术吗?或者只是挖掘频繁的十六进制代码?
扫描时间是很重要的问题!
一旦我编写了一个更健全的命令行,它就能在不到一秒钟的时间内找到一个文件——在一秒钟内感染大量文件。
该技术是frequent opcode mining.

于 2012-10-06T17:13:50.150 回答
0

也许您的模式扫描效率低下。我可以使用这样的代码在大约 1/20 秒内扫描 7 MB 文件中的模式。请注意,如果您真的想使用这样的代码,则必须进行更正。当您意识到您没有查看匹配项时,您不能总是将 MatchedLength 设置回 0,但它确实适用于这种特定模式。您必须对模式进行预处理,以便在找不到匹配项时知道要重置的内容,但这不会为算法增加大量时间。我可以努力正确完成算法,但如果您的问题只是关于性能,我现在不会这样做。我只是在演示如果操作正确,可以快速扫描大文件。

Sub Main(ByVal args As String())
  If args.Length < 1 Then Return
  Dim startTime As Long = Stopwatch.GetTimestamp()
  Dim pattern As Byte()
  pattern = System.Text.Encoding.UTF8.GetBytes("SFMB")
  Dim bufferSize As Integer = 4096
  Using reader As New System.IO.FileStream(args(0), IO.FileMode.Open, _
     Security.AccessControl.FileSystemRights.Read, IO.FileShare.Read, bufferSize, IO.FileOptions.SequentialScan)
     Dim buffer(bufferSize - 1) As Byte
     Dim readLength = reader.Read(buffer, 0, bufferSize)
     Dim matchedLength As Integer = 0
     Dim searchPos As Integer = 0
     Dim fileOffset As Integer = 0
     Do While readLength > 0
        For searchPos = 0 To readLength - 1
           If pattern(matchedLength) = buffer(searchPos) Then
              matchedLength += 1
           Else
              matchedLength = 0
           End If
           If matchedLength = pattern.Length Then
              Console.WriteLine("Found pattern at position {0}", fileOffset + searchPos - matchedLength + 1)
              matchedLength = 0
           End If
        Next
        fileOffset += readLength
        readLength = reader.Read(buffer, 0, bufferSize)
     Loop
  End Using
  Dim endTime As Long = Stopwatch.GetTimestamp()
  Console.WriteLine("Search took {0} seconds", (endTime - startTime) / Stopwatch.Frequency)
End Sub

编辑

以下是关于如何一次匹配多个模式的一些想法。这只是我的想法,我还没有尝试编译代码:

创建一个类以包含有关模式状态的信息:

Class PatternInfo
   Public pattern As Byte()
   Public matchedBytes As integer
End Class

声明一个变量来跟踪您需要检查的所有模式,并按模式的第一个字节对它们进行索引以便快速查找:

Dim patternIndex As Dictionary(Of Byte, IEnumerable(Of PatternInfo))

检查当前可能匹配的所有模式,看看下一个字节是否也匹配这些模式;如果没有,请停止在该位置查看该模式:

Dim activePatterns As New LinkedList(Of PatternInfo)
Dim newPatterns As IEnumerable(Of PatternInfo)

For Each activePattern in activePatterns.ToArray
   If activePattern.pattern(matchedBytes) = buffer(searchPos) Then
      activePattern.matchedBytes += 1
      If activePattern.matchedBytes >= activePattern.pattern.Length Then
         Console.WriteLine("Found pattern at position {0}", searchPos - matchedBytes + 1)
      End If
   Else
      activePatterns.Remove(activePattern)
   End If
Next

查看当前字节是否看起来像您要搜索的新模式的开始;如果是这样,请将其添加到活动模式列表中:

If patternIndex.TryGetValue(buffer(searchPos), newPatterns) Then
   For Each newPattern in newPatterns
      activePatterns.Add(New PatternInfo() With { _
         .pattern = newPattern.pattern, .matchedBytes = 1 }
   Next
End If
于 2011-03-16T13:00:07.460 回答