# 动机
在 PowerShell 命令行中执行 PowerShell 脚本时,windows 默认会将执行的内容传送给 AMSI 进行检测,如果检测结果认为执行内容中包含病毒,则拒绝执行,实现安全防护。
AMSI 的官方文档宣称可以对混淆 PowerShell 脚本最终的无混淆结果进行检测,为了知道 AMSI 运行中具体对脚本的哪些内容进行了捕获检测,我们尝试截获输出传给 AMSI 的脚本内容。主要参考了 YouTube 上的一个技术视频进行了实现。
# 具体做法
-
使用
logman
创建和控制事件跟踪进程1
2
3
4
5每一次监控,可以更改名称 AMSITraceTest.etl
开始跟踪
start 开始 -ets 直接向事件跟踪会话发送命令,无需保存或调度
--% 告诉powershell 停止解释内联PS代码的命令行
logman --% start AMSITraceTest -p Microsoft-Antimalware-Scan-Interface (Event1) 0x4 -o AMSITraceTest.etl -ets -
执行 PowerShell 脚本
-
结束跟踪
1
logman stop AMSITraceTest -ets
-
读取事件内容
编写一个
GetAMSI.ps1
, 然后导入. GetAMSI.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32function Get-AMSITraceEvent {
param (
[Parameter(Mandatory)]
[String]
$FilePath
)
Get-WinEvent -Path $FilePath -Oldest -FilterXPath '*[System[EventID = 1101]]' | ForEach-Object {
switch ($_.Properties[2].Value) {
0 { $ScanResult = 'AMSI_RESULT_CLEAN' }
1 { $ScanResult = 'AMSI_RESULT_NOT_DETECTED' }
32768 { $ScanResult = 'AMSI_RESULT_DETECTED' }
default { $ScanResult = $_.Properties[2].Value }
}
$ObjectProperties = [Ordered] @{
TimeCreated = $_.TimeCreated
ProcessId = $_.ProcessId
ThreadId = $_.ThreadId
Session = $_.Properties[0].Value
ScanStatus = $_.Properties[1].Value
ScanResult = $ScanResult
AppName = $_.Properties[3].Value
ContentName = $_.Properties[4].Value
ContentSize = $_.Properties[5].Value
OriginalSize = $_.Properties[6].Value
Content = ([Text.Encoding]::Unicode.GetString($_.Properties[7].Value))
Hash = (($_.Properties[8].Value | % { '{0:X2}' -f $_ }) -join '')
ContentFiltered = $_.Properties[9].Value
}
New-Object -TypeName psobject -Property $ObjectProperties
}
}然后在 powershell 中执行
1
Get-AMSITraceEvent -FilePath ./AMSITraceTest.etl