MalwareScan.AMSI

Scans for viruses and other malware in Windows 10+ and Server 2016+ by wrapping the AMSI interface


Keywords
amsi, package, virus-scanner
License
MIT
Install
Install-Package MalwareScan.AMSI -Version 1.1.0

Documentation

Anti Malware scanning in Windows

Provides a wrapper around the AMSI Interface that was introduced in Windows 10/Server 2016 to allow applications to scan content for viruses.

Installation

Install-Package MalwareScan.AMSI

Azure App Services, Functions etc

For some odd reason, Microsoft do not enable a virus scanner on the VMs that run Azure Web Apps - they only have virus scanners on the underlying infrastructure. Please follow the link and vote it up.
This means that you cannot use AMSI on Azure App Services and, presumably, Functions.
It works perfectly fine on VMs and Cloud Services (just make sure you set the os family to 5 or above for cloud services).

WARNING On Windows Server, w3p.exe (the IIS host process) is excluded from virus scanning so AMSI will always return "clean" for any virus if you are running it from within IIS. This seems to be a change that was introduced quietly at some point in 2020 - but not sure. You may find that your virus scanning has quietly stopped working. See the docs on how to change this behaviour. Also consider automatically calling TestIfItIsWorking.

Usage

Initialiase an instance of the MalwareScanner:

   var scanner = new MalwareScanner("MyApplications Viruscanner");

You can - and probably should - keep an instance of this class around as a singleton. There is some base initialisation that is scoped to the lifetime of the object and you can avoid doing that initialisation multiple time. The code is threadsafe so you can scan multiple streams in parallel with the same instance.

Alternatively, you can just create instances as needed; the initialisation is Lazy, so don't worry about creating instances of the object that aren't used.

To scan a stream, call

   var result = scanner.HasVirus(stream, filename);

Alternatively, you can pass in a byte array. If passing in a stream, be aware of some of the limitations of streams. If you are passing in a MemoryStream or a FileStream or similar then everything is fine. But some streams are forward-only, such as the request stream in a web application (if you are reading it directly). This means that they can only be read once, meaning that if you pass such a stream to the scanner, you won't be able to read the stream afterwards. If you read the stream first, then the scanner can't read it; in that scenario the scanner will just see empty content so will return false (i.e. "no virus found").

Test if the scanner is working

The AMSI interface is only available in Windows 10+ and in Server 2016. Furthermore, if no malware scanner is installed, the scanner may happily tell you it didn't find a virus or it may throw an exception. It is a good idea to call the TestIfItIsWorking method on application startup and check the result. The test method will scan a known test virus string (the EICAR string) to confirm that everything is working correctly. If the virus scanning is not working, the result will return an error message and possibly an underlying exception in the result. TestIfItIsWorking should never throw an exception itself.
Note that any positive virus scan, including the test one, will cause windows defender to log the detection and on a desktop will pop up a message, so don't call this too often.

References