|
| 1 | +using System.Runtime.InteropServices; |
| 2 | +#if NET5_0_OR_GREATER |
| 3 | +using System.Runtime.Versioning; |
| 4 | +#endif |
| 5 | + |
| 6 | +namespace ByteGuard.FileValidator.Scanner.Amsi.Integration; |
| 7 | + |
| 8 | +/// <summary> |
| 9 | +/// Dynamically loaded Antimalware Scan Interface from System32. Will only work on Windows clients and servers. |
| 10 | +/// </summary> |
| 11 | +#if NET5_0_OR_GREATER |
| 12 | +[SupportedOSPlatform("windows")] |
| 13 | +#endif |
| 14 | +internal static class Amsi |
| 15 | +{ |
| 16 | + /// <summary> |
| 17 | + /// Initialize the AMSI API. |
| 18 | + /// </summary> |
| 19 | + /// <param name="appName">The name, version, or GUID string of the app calling the AMSI API.</param> |
| 20 | + /// <param name="amsiContext">Out generated AMSI context that must be passed to all subsequent calls to the AMSI API.</param> |
| 21 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 22 | + [DllImport("Amsi.dll", EntryPoint = "AmsiInitialize", CallingConvention = CallingConvention.StdCall)] |
| 23 | + internal static extern int AmsiInitialize([MarshalAs(UnmanagedType.LPWStr)] string appName, out AmsiContextSafeHandle amsiContext); |
| 24 | + |
| 25 | + /// <summary> |
| 26 | + /// Remove the instance of the AMSI API that was originally opened by <see cref="AmsiInitialize"/>. |
| 27 | + /// </summary> |
| 28 | + /// <param name="amsiContext">The context handle that was initially received from <see cref="AmsiInitialize"/>.</param> |
| 29 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 30 | + [DllImport("Amsi.dll", EntryPoint = "AmsiUninitialize", CallingConvention = CallingConvention.StdCall)] |
| 31 | + internal static extern void AmsiUninitialize(IntPtr amsiContext); |
| 32 | + |
| 33 | + /// <summary> |
| 34 | + /// Opens a session within which multiple scan requests can be correlated. |
| 35 | + /// </summary> |
| 36 | + /// <param name="amsiContext">The context handle that was initially received from <see cref="AmsiInitialize"/>.</param> |
| 37 | + /// <param name="session">Out generated AMSI session that must be passed to all subsequent calls to the AMSI API within the session.</param> |
| 38 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 39 | + [DllImport("Amsi.dll", EntryPoint = "AmsiOpenSession", CallingConvention = CallingConvention.StdCall)] |
| 40 | + internal static extern int AmsiOpenSession(AmsiContextSafeHandle amsiContext, out AmsiSessionSafeHandle session); |
| 41 | + |
| 42 | + /// <summary> |
| 43 | + /// Close a session that was opened by <see cref="AmsiOpenSession"/>. |
| 44 | + /// </summary> |
| 45 | + /// <param name="amsiContext">The context handle that was initially received from <see cref="AmsiInitialize"/>.</param> |
| 46 | + /// <param name="session">The session handle that was initially received from <see cref="AmsiOpenSession"/>.</param> |
| 47 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 48 | + [DllImport("Amsi.dll", EntryPoint = "AmsiCloseSession", CallingConvention = CallingConvention.StdCall)] |
| 49 | + internal static extern void AmsiCloseSession(AmsiContextSafeHandle amsiContext, IntPtr session); |
| 50 | + |
| 51 | + /// <summary> |
| 52 | + /// Scans a string for malware. |
| 53 | + /// </summary> |
| 54 | + /// <remarks> |
| 55 | + /// It's recommended to use <see cref="AmsiResultIsMalware"/> to interpret the returning result. |
| 56 | + /// </remarks> |
| 57 | + /// <param name="amsiContext">The context handle that was initially received from <see cref="AmsiInitialize"/>.</param> |
| 58 | + /// <param name="payload">The string to be scanned.</param> |
| 59 | + /// <param name="contentName">The filename, URL, unique script ID, or similar of the content being scanned.</param> |
| 60 | + /// <param name="session">If multiple scan requests are to be correlated within a session, set session to the session handle that was initially received from <see cref="AmsiOpenSession"/>. Otherwise, set session to <c>null</c>.</param> |
| 61 | + /// <param name="result">Out result of the scan (see <see cref="AmsiResult"/>).</param> |
| 62 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 63 | + [DllImport("Amsi.dll", EntryPoint = "AmsiScanString", CallingConvention = CallingConvention.StdCall)] |
| 64 | + internal static extern int AmsiScanString(AmsiContextSafeHandle amsiContext, [In, MarshalAs(UnmanagedType.LPWStr)] string payload, [In, MarshalAs(UnmanagedType.LPWStr)] string contentName, AmsiSessionSafeHandle session, out AmsiResult result); |
| 65 | + |
| 66 | + /// <summary> |
| 67 | + /// Scans a buffer-full of content for malware. |
| 68 | + /// </summary> |
| 69 | + /// <remarks> |
| 70 | + /// It's recommended to use <see cref="AmsiResultIsMalware"/> to interpret the returning result. |
| 71 | + /// </remarks> |
| 72 | + /// <param name="amsiContext">The context handle that was initially received from <see cref="AmsiInitialize"/>.</param> |
| 73 | + /// <param name="buffer">The buffer from which to read the data to be scanned.</param> |
| 74 | + /// <param name="length">The length, in bytes, of the data to be read from buffer.</param> |
| 75 | + /// <param name="contentName">The filename, URL, unique script ID, or similar of the content being scanned.</param> |
| 76 | + /// <param name="session">If multiple scan requests are to be correlated within a session, set session to the session handle that was initially received from <see cref="AmsiOpenSession"/>. Otherwise, set session to <c>null</c>.</param> |
| 77 | + /// <param name="result">Out result of the scan (see <see cref="AmsiResult"/>).</param> |
| 78 | + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] |
| 79 | + [DllImport("Amsi.dll", EntryPoint = "AmsiScanBuffer", CallingConvention = CallingConvention.StdCall)] |
| 80 | + internal static extern int AmsiScanBuffer(AmsiContextSafeHandle amsiContext, byte[] buffer, uint length, [In, MarshalAs(UnmanagedType.LPWStr)] string contentName, AmsiSessionSafeHandle session, out AmsiResult result); |
| 81 | + |
| 82 | + /// <summary> |
| 83 | + /// Determines if the result of a scan indicates that the content should be blocked. |
| 84 | + /// </summary> |
| 85 | + /// <param name="result">Result of a scan from either <see cref="AmsiScanString"/> or <see cref="AmsiScanBuffer"/>.</param> |
| 86 | + /// <returns><c>true</c> if the result is considered a malware detection, <c>false</c> otherwise.</returns> |
| 87 | + internal static bool AmsiResultIsMalware(AmsiResult result) => result >= AmsiResult.AMSI_RESULT_DETECTED; |
| 88 | +} |
0 commit comments