-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathWinDefender.cs
82 lines (72 loc) · 2.1 KB
/
WinDefender.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Jitbit.Utils
{
public class WinDefender
{
private static bool _isDefenderAvailable;
private static string _defenderPath;
private static SemaphoreSlim _lock = new SemaphoreSlim(5); //limit to 5 concurrent checks at a time
//static ctor
static WinDefender()
{
if (OperatingSystem.IsWindows())
{
_defenderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Windows Defender", "MpCmdRun.exe");
_isDefenderAvailable = File.Exists(_defenderPath);
}
else
_isDefenderAvailable = false;
}
public static async Task<bool> IsVirus(byte[] file, CancellationToken cancellationToken = default)
{
if (!_isDefenderAvailable) return false;
string path = Path.GetTempFileName();
await File.WriteAllBytesAsync(path, file, cancellationToken); //save temp file
if (cancellationToken.IsCancellationRequested) return false;
try
{
return await IsVirus(path, cancellationToken);
}
finally
{
File.Delete(path); //cleanup temp file
}
}
public static async Task<bool> IsVirus(string path, CancellationToken cancellationToken = default)
{
await _lock.WaitAsync(cancellationToken);
try
{
using (var process = Process.Start(_defenderPath, $"-Scan -ScanType 3 -File \"{path}\" -DisableRemediation"))
{
if (process == null)
{
_isDefenderAvailable = false; //disable future attempts
throw new InvalidOperationException("Failed to start MpCmdRun.exe");
}
try
{
await process.WaitForExitAsync().WaitAsync(TimeSpan.FromMilliseconds(2500), cancellationToken);
}
catch (TimeoutException ex) //timeout
{
throw new TimeoutException("Timeout waiting for MpCmdRun.exe to return", ex);
}
finally
{
process.Kill(); //always kill the process, it's fine if it's already exited, but if we were timed out or cancelled via token - let's kill it
}
return process.ExitCode == 2;
}
}
finally
{
_lock.Release();
}
}
}
}