AmsiScanService.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Buffers;
  3. using System.IO;
  4. using static Masuit.Tools.Win32.AntiVirus.AmsiWrapper;
  5. namespace Masuit.Tools.Win32.AntiVirus;
  6. public static class AmsiScanService
  7. {
  8. private const string AppName = "AMSI";
  9. static AmsiScanService()
  10. {
  11. if (!File.Exists(SystemParameter.AmsiDllPath))
  12. {
  13. throw new PlatformNotSupportedException("amsi.dll not found");
  14. }
  15. }
  16. /// <summary>
  17. /// 扫描文件
  18. /// </summary>
  19. /// <param name="filePath"></param>
  20. /// <returns></returns>
  21. public static ScanResult Scan(string filePath)
  22. {
  23. if (!File.Exists(filePath))
  24. {
  25. throw new FileNotFoundException();
  26. }
  27. try
  28. {
  29. AmsiInitialize(AppName, out var amsiContext);
  30. AmsiOpenSession(amsiContext, out var amsiSession);
  31. //读取文件(如文件有可疑,会引发Exception)
  32. var fileData = File.ReadAllBytes(filePath);
  33. return ScanBuffer(amsiContext, amsiSession, fileData, Path.GetFileName(filePath));
  34. }
  35. catch (Exception ex)
  36. {
  37. if (ex.Message.Contains("Operation did not complete successfully because the file contains a virus or potentially unwanted software"))
  38. {
  39. return new ScanResult
  40. {
  41. Result = ResultCode.Detected
  42. };
  43. }
  44. return new ScanResult
  45. {
  46. Result = ResultCode.Exception,
  47. Msg = ex.Message
  48. };
  49. }
  50. }
  51. /// <summary>
  52. /// 扫描文件流
  53. /// </summary>
  54. /// <param name="fileStream"></param>
  55. /// <returns></returns>
  56. public static ScanResult Scan(Stream fileStream)
  57. {
  58. if (fileStream == null)
  59. {
  60. throw new ArgumentNullException(nameof(fileStream));
  61. }
  62. var fileData = ArrayPool<byte>.Shared.Rent((int)fileStream.Length);
  63. try
  64. {
  65. AmsiInitialize(AppName, out var amsiContext);
  66. AmsiOpenSession(amsiContext, out var amsiSession);
  67. _ = fileStream.Read(fileData, 0, (int)fileStream.Length);
  68. return ScanBuffer(amsiContext, amsiSession, fileData, "");
  69. }
  70. catch (Exception ex)
  71. {
  72. if (ex.Message.Contains("Operation did not complete successfully because the file contains a virus or potentially unwanted software"))
  73. {
  74. return new ScanResult
  75. {
  76. Result = ResultCode.Detected
  77. };
  78. }
  79. return new ScanResult
  80. {
  81. Result = ResultCode.Exception,
  82. Msg = ex.Message
  83. };
  84. }
  85. finally
  86. {
  87. ArrayPool<byte>.Shared.Return(fileData);
  88. }
  89. }
  90. /// <summary>
  91. /// 扫描文件
  92. /// </summary>
  93. /// <param name="fileData"></param>
  94. /// <returns></returns>
  95. public static ScanResult Scan(byte[] fileData)
  96. {
  97. if (fileData == null)
  98. {
  99. throw new ArgumentNullException(nameof(fileData));
  100. }
  101. try
  102. {
  103. AmsiInitialize(AppName, out nint amsiContext);
  104. AmsiOpenSession(amsiContext, out nint amsiSession);
  105. return ScanBuffer(amsiContext, amsiSession, fileData, "");
  106. }
  107. catch (Exception ex)
  108. {
  109. if (ex.Message.Contains("Operation did not complete successfully because the file contains a virus or potentially unwanted software"))
  110. {
  111. return new ScanResult
  112. {
  113. Result = ResultCode.Detected
  114. };
  115. }
  116. return new ScanResult
  117. {
  118. Result = ResultCode.Exception,
  119. Msg = ex.Message
  120. };
  121. }
  122. }
  123. /// <summary>
  124. /// 扫描文件Buffer
  125. /// </summary>
  126. /// <param name="amsiContext"></param>
  127. /// <param name="amsiSession"></param>
  128. /// <param name="bufferData"></param>
  129. /// <param name="fileName"></param>
  130. /// <returns></returns>
  131. private static ScanResult ScanBuffer(nint amsiContext, nint amsiSession, byte[] bufferData, string fileName)
  132. {
  133. AmsiScanBuffer(amsiContext, bufferData, (uint)bufferData.Length, fileName, amsiSession, out AmsiResult amsiResult);
  134. var result = ConvertToScanResult(amsiResult);
  135. return result;
  136. }
  137. private static ScanResult ConvertToScanResult(AmsiResult amsiResult)
  138. {
  139. switch (amsiResult)
  140. {
  141. case AmsiResult.AmsiResultClean:
  142. case AmsiResult.AmsiResultNotDetected:
  143. return new ScanResult
  144. {
  145. Result = ResultCode.NotDetected
  146. };
  147. case AmsiResult.AmsiResultDetected:
  148. return new ScanResult
  149. {
  150. Result = ResultCode.Detected
  151. };
  152. default:
  153. return new ScanResult
  154. {
  155. Result = ResultCode.Exception,
  156. Msg = "Blocked behavior,scan not allowed!"
  157. };
  158. }
  159. }
  160. }