You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

111 lines
3.8 KiB

#nullable enable
using IPA.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace IPA.AntiMalware
{
internal class WindowsWin32AntiMalware : IAntiMalware, IDisposable
{
internal static WindowsWin32AntiMalware? TryInitialize()
{
try
{
return new();
}
catch (Exception e)
{
Logger.AntiMalware.Warn("Could not initialize Win32-based antimalware engine:");
Logger.AntiMalware.Warn(e);
return null;
}
}
private readonly IntPtr handle;
private bool disposedValue;
private WindowsWin32AntiMalware()
{
AmsiInitialize(AmsiConstants.AppName, out handle);
}
private static ScanResult ScanResultFromAmsiResult(AmsiResult result)
=> result switch
{
AmsiResult.Clean => ScanResult.KnownSafe,
AmsiResult.NotDetected => ScanResult.NotDetected,
AmsiResult.Detected => ScanResult.Detected,
_ => ScanResult.MaybeMalware
};
public ScanResult ScanFile(FileInfo file)
{
var data = File.ReadAllBytes(file.FullName);
return ScanData(data, file.FullName);
}
public ScanResult ScanData(byte[] data, string? contentName = null)
{
contentName ??= $"unknown_data_{Guid.NewGuid()}";
AmsiScanBuffer(handle, data, (uint)data.Length, contentName, IntPtr.Zero, out var result);
Logger.AntiMalware.Trace($"Scanned data named '{contentName}' and got '{result}'");
return ScanResultFromAmsiResult(result);
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// we have no disposable managed state
}
AmsiUninitialize(handle);
disposedValue = true;
}
}
~WindowsWin32AntiMalware()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
[DllImport("amsi", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true)]
#if !NET35
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
#endif
private static extern void AmsiInitialize([MarshalAs(UnmanagedType.LPWStr)] string appName, [Out] out IntPtr handle);
[DllImport("amsi", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true)]
#if !NET35
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
#endif
private static extern void AmsiUninitialize(IntPtr handle);
[DllImport("amsi", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true)]
#if !NET35
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
#endif
private static extern void AmsiScanBuffer(IntPtr context,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer, uint length,
[MarshalAs(UnmanagedType.LPWStr)] string contentName,
IntPtr session,
[Out] out AmsiResult result);
}
}