【发布时间】:2020-07-12 21:26:28
【问题描述】:
我正在尝试使用 C# 创建一个 MD5 恶意软件扫描程序。使用普通的dictionary comparison 有一个致命的缺陷,存在跨目录具有相同哈希值的重复文件,因此,相同的 key (md5) 将代表很多 文件目录与。我尝试切换到 KeyValuePair,但由于经验不足,我仍然无法弄清楚如何将 lambda 坐标输出插入 KeyValuePair(在下面的代码中由 Idon'tknowwhatshouldbehere 表示)。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Text;
using System.Web;
using static System.Net.WebRequestMethods;
namespace RiskRemover
{
class Program
{
private static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
var currDir = Directory.GetCurrentDirectory();
Console.WriteLine("Stage 1: Update");
HttpWebRequest updRq = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/drive/v3/files/15WR2yTVJzgwg2pn64IhxFUbfy2BmmsdL?alt=media&key=APIKey");
updRq.Referer = "referrer";
HttpWebResponse updRqF = (HttpWebResponse)updRq.GetResponse();
using (Stream output = System.IO.File.OpenWrite("virushashesL.txt"))
using (Stream input = updRqF.GetResponseStream())
{
input.CopyTo(output);
}
bool dbExist = System.IO.File.Exists($"{currDir}\\virushashesL.txt");
if (!dbExist)
{
Console.WriteLine("Database Doesn't exist, Terminating...");
return;
}
var lineCount = System.IO.File.ReadLines($"{currDir}\\virushashesL.txt").Count();
Console.WriteLine(" ");
Console.WriteLine($"Database Hash Count: {lineCount}");
Console.WriteLine(" ");
Console.Write("Press any key to continue...");
Console.Clear();
Console.Write("Scan Path:");
string pathScan = @Console.ReadLine();
Console.Clear();
Console.WriteLine("Stage 2: MD5 Hashing");
var data = GetHasList(@pathScan, false).Select(x => $"\"{x.fileName}\" {x.hash}");
System.IO.File.WriteAllLines("output.txt", data);
Console.Clear();
Console.WriteLine("Stage 3: Comparing MD5 hashes to DB");
KeyValuePair<string, string> dic = new KeyValuePair<string, string>();
dic = System.IO.File.ReadAllLines("output.txt")
.Select(l => l.Split(new[] { '<' }))
.Idon'tknowwhatshouldbehere(s => s[1].Trim().Substring(0, 10), s => s[0].Trim());
List<string> lines = System.IO.File.ReadAllLines("virushashesL.txt").ToList();
foreach (var line in lines)
{
bool malicious = dic.ContainsKey(line);
if (malicious)
{
string malPath = dic[line];
System.IO.File.Delete(malPath);
}
}
Console.Clear();
sw.Stop();
Console.Write($"Done in {sw.Elapsed}...");
Console.ReadKey();
return;
}
public static IEnumerable<(string fileName, string hash)> GetHasList(string path, bool isRelative)
{
foreach (var file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
{
string hash;
using (var md5 = MD5.Create())
using (var stream = System.IO.File.OpenRead(file))
hash = BitConverter.ToString(md5.ComputeHash(stream)).ToLower();
hash = hash.Replace("-", "");
if (isRelative)
yield return (file.Remove(0, path.TrimEnd('/').Length + 1), hash);
else
yield return ($"{file}<", hash);
}
}
}
}
示例输出.txt
"D:\EvaxHybrid\Downloads\CS8\insdir\CSMediaLibParser.dll<" a384ff0a72a89028fc5edc894309ce81
"D:\EvaxHybrid\Downloads\CS8\insdir\CSMediaLibTools.dll<" 62cd2374d3a2bbeb888a078dc20e6b18
...
示例 virushashesL.txt
2d3f18345c
2d427ec2c7
...
【问题讨论】:
-
请通过tour 了解 Stack Overflow 的工作原理,并阅读How to Ask 以了解如何提高问题的质量。然后edit你的问题包含你拥有的源代码作为minimal reproducible example,它可以被其他人编译和测试。目前还不太清楚您想要做什么或 MD5 与您正在做什么相关。还要解释什么是“文件目录”。您的
output.txt中的文件路径中有一个<。这是故意的还是那个字符的含义是什么? -
@Progman 编译需要完整的源代码。我想要做的是将恶意 MD5 与指定目录和子目录中的所有文件的 MD5 进行比较,并删除任何恶意文件。 (恶意软件的 MD5 为 10 个字符长,文件的 MD5 为全长) 至于“
-
GetHasList()方法(方法名称中缺少s?)返回一个由fileName和hash分隔的元组。但是您将它们放在一个字符串中,稍后,使用Split()将它们再次拆分。为什么将它们放在一个字符串中并再次拆分它们?为什么不让他们分开呢?甚至可能返回一个IDictionary,它将文件路径映射到哈希。基于此,您可能会执行.Any()或.Where()之类的操作来查找给定哈希的文件。或者你可以用GroupBy()“交换”字典,见stackoverflow.com/questions/13410590/…