我一直在使用 vb.net 开发防病毒软件。病毒扫描程序工作正常,但我正在考虑优化扫描速度的方法(因为大文件需要很长时间)。
我用来检测病毒的算法是通过二进制(转换为十六进制)签名。我想我不必为了查找它是否是病毒而查看整个文件,我认为我应该扫描一个特定的位置和特定数量的字节,而不是扫描整个文件。无论如何,如果有人可以在这个主题上提供任何帮助,请这样做。
提前致谢。
顺便说一句,病毒签名来自 clamAv 防病毒软件的十六进制集合......
我一直在使用 vb.net 开发防病毒软件。病毒扫描程序工作正常,但我正在考虑优化扫描速度的方法(因为大文件需要很长时间)。
我用来检测病毒的算法是通过二进制(转换为十六进制)签名。我想我不必为了查找它是否是病毒而查看整个文件,我认为我应该扫描一个特定的位置和特定数量的字节,而不是扫描整个文件。无论如何,如果有人可以在这个主题上提供任何帮助,请这样做。
提前致谢。
顺便说一句,病毒签名来自 clamAv 防病毒软件的十六进制集合......
那么这一切都取决于,病毒签名的定义是什么?
我建议您解析可执行文件并仅使用code-section。
但是多态病毒以加密形式将恶意代码保存在数据部分中。所以我不是很确定。
你在使用某种 n-gram 技术吗?或者只是挖掘频繁的十六进制代码?
扫描时间是很重要的问题!
一旦我编写了一个更健全的命令行,它就能在不到一秒钟的时间内找到一个文件——在一秒钟内感染大量文件。
该技术是frequent opcode mining.
也许您的模式扫描效率低下。我可以使用这样的代码在大约 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