.NET virus scanning API

Viewed 61668

I'm building a web application in which I need to scan the user-uploaded files for viruses.

Does anyone with experience in building something like this can provide information on how to get this up and running? I'm guessing antivirus software packages have APIs to access their functionality programatically, but it seems it's not easy to get a hand on the details.

FYI, the application is written in C#.

12 Answers

I would probably just make a system call to run an independent process to do the scan. There are a number of command-line AV engines out there from various vendors.

Take a look at the Microsoft Antivirus API. It makes use of COM, which should be easy enough to interface with from .NET. It refers specifically to Internet Explorer and Microsoft Office, but I don't see why you wouldn't be able to use to to on-demand scan any file.

All modern scanners that run on Windows should understand this API.

Various Virus scanners do have API's. One I have integrated with is Sophos. I am pretty sure Norton has an API also while McAfee doesn't (it used to). What virus software do you want to use? You may want to check out Metascan as it will allow integration with many different scanners, but there is an annual license cost. :-P

I also had this requirement. I used clamAv anti virus which provides on-demand scanning by sending the file to their tcp listening port. You can use nClam nuget package to send files to clamav.

var clam = new ClamClient("localhost", 3310);
var scanResult = clam.ScanFileOnServerAsync("C:\\test.txt"); //any file you would like!
switch (scanResult.Result.Result)
{
    case ClamScanResults.Clean:
        Console.WriteLine("The file is clean!");
        break;
    case ClamScanResults.VirusDetected:
        Console.WriteLine("Virus Found!");
        Console.WriteLine("Virus name: {0}", scanResult.Result.InfectedFiles[0].FileName);
        break;
    case ClamScanResults.Error:
        Console.WriteLine("Woah an error occured! Error: {0}", scanResult.Result.RawResult);
        break;
}

A simple and detailed example is shown here. Note:- The synchronous scan method is not available in the latest nuget. You have to code like I done above

For testing a virus you can use the below string in a txt file

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

I would recommend using this approach:

using System;
using System.Diagnostics;
using Cloudmersive.APIClient.NET.VirusScan.Api;
using Cloudmersive.APIClient.NET.VirusScan.Client;
using Cloudmersive.APIClient.NET.VirusScan.Model;

namespace Example
{
    public class ScanFileAdvancedExample
    {
        public void main()
        {
            // Configure API key authorization: Apikey
            Configuration.Default.AddApiKey("Apikey", "YOUR_API_KEY");
            
            

            var apiInstance = new ScanApi();
            var inputFile = new System.IO.FileStream("C:\\temp\\inputfile", System.IO.FileMode.Open); // System.IO.Stream | Input file to perform the operation on.
            var allowExecutables = true;  // bool? | Set to false to block executable files (program code) from being allowed in the input file.  Default is false (recommended). (optional) 
            var allowInvalidFiles = true;  // bool? | Set to false to block invalid files, such as a PDF file that is not really a valid PDF file, or a Word Document that is not a valid Word Document.  Default is false (recommended). (optional) 
            var allowScripts = true;  // bool? | Set to false to block script files, such as a PHP files, Pythong scripts, and other malicious content or security threats that can be embedded in the file.  Set to true to allow these file types.  Default is false (recommended). (optional) 
            var allowPasswordProtectedFiles = true;  // bool? | Set to false to block password protected and encrypted files, such as encrypted zip and rar files, and other files that seek to circumvent scanning through passwords.  Set to true to allow these file types.  Default is false (recommended). (optional) 
            var restrictFileTypes = restrictFileTypes_example;  // string | Specify a restricted set of file formats to allow as clean as a comma-separated list of file formats, such as .pdf,.docx,.png would allow only PDF, PNG and Word document files.  All files must pass content verification against this list of file formats, if they do not, then the result will be returned as CleanResult=false.  Set restrictFileTypes parameter to null or empty string to disable; default is disabled. (optional) 

            try
            {
                // Advanced Scan a file for viruses
                VirusScanAdvancedResult result = apiInstance.ScanFileAdvanced(inputFile, allowExecutables, allowInvalidFiles, allowScripts, allowPasswordProtectedFiles, restrictFileTypes);
                Debug.WriteLine(result);
            }
            catch (Exception e)
            {
                Debug.Print("Exception when calling ScanApi.ScanFileAdvanced: " + e.Message );
            }
        }
    }
}

Note that this way you can even control whether you filter out non-virus threat payloads such as executables, scripts, encrypted/password-protected files, etc.

This approach has a free tier and can also validate the contents of the files that you upload.

You can try to use DevDragon.io.

It is a web service with an API and .NET client DevDragon.Antivirus.Client you can get from NuGet. Scans are sub 200ms for 1MB file.

More documentation here: https://github.com/Dev-Dragon/Antivirus-Client

Disclosure: I work for them.

We tried two options:

  1. clamav-daemon installed on a tiny linux container + "nClam" .NET library to interact with it. Works fine, but Clam AV misses a lot (a lot!) of viruses, especially dangerous macros hidden in MS Office files. Also ClamAV virus database has to be kept in memory at all times, which uses around 3.5GB of memory, which requires a rather expensive cloud virtual machine.

  2. Ended up using Windows Defender via MpCmdRun.exe CLI api. See answer here

From my experience you can use COM for interfacing with some anti-virus software. But what I would suggest is a bit easier, just parse scan results after scanning. All you need to do is to start the scanner process and point it to file/folder you want to scan, store scan results into file or redirect stdout to your application and parse results.

Related