Skip to content

Instantly share code, notes, and snippets.

@mgreen27
Last active May 27, 2019 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgreen27/597579a200d6c20b53203bcd218d9b06 to your computer and use it in GitHub Desktop.
Save mgreen27/597579a200d6c20b53203bcd218d9b06 to your computer and use it in GitHub Desktop.
Get-AMSIEvents
Function Get-AMSIEvents
{
<#
.SYNOPSIS
Get-AMSIEvents collects AMSI events during interval.
Name: Get-AMSIEvents.ps1
Version: 0.1
Date: 2019-05-26
Requirements: Windows 10. Office2019 for VBA
.DESCRIPTION
Get-AMSIEvents collects AMSI events during interval.
Will log all AMSI events including Powershell, vbscript, jscript and VBA.
.EXAMPLE
Get-AMSIEvents
Will Run collection start. When complete results will return variable $AMSIEvents.
.EXAMPLE
Get-AMSIEvents -Path C:\Users\REM\Desktop\2019-05-26AMSITrace.etl
Will parse a precollected AMSI trace Log. When complete results will return variable $AMSIEvents.
.NOTES
Initial AMSI parsing POC from Matt Graeber @Mattifestation
https://gist.github.com/mattifestation/e179218d88b5f100b0edecdec453d9be#file-amsiscriptcontentretrieval-ps1
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $False)][String]$Path
)
Write-Host -ForegroundColor Cyan "`nGet-AMSIEvents"
Write-Host -ForegroundColor White "`tA tool to collect AMSI events leveraging Event Tracing for Windows"
# Set switches
If ($PSBoundParameters.ContainsKey("Path")){
If (Test-Path $Path) {
$tracePath = $Path
Write-Host -ForegroundColor White "Path is $tracePath`n"
}
Else {
Write-Host -ForegroundColor Red "$Path not found"
exit
}
}
Else {
# Test for Elevated privilege if to enable AMSI
If (!(([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))){
Write-Host -ForegroundColor Red "Exiting Get-AMSIEvents: Elevated privilege required."
exit
}
$date = get-date ([DateTime]::UtcNow) -format yyyy-MM-dd
$tracePath = [Environment]::GetFolderPath("Desktop") + "\" + $date + "AMSITrace.etl"
$traceName = "AMSITrace"
If (Test-Path $tracePath) { Remove-item -Path $tracePath -Force }
Write-Host "`tPath: $tracePath`n"
logman start $traceName -p Microsoft-Antimalware-Scan-Interface Event1 -o $tracePath -ets | Out-Null
Write-Host -ForegroundColor Yellow "`tCollecting AMSI Events."
Write-Host "`tRun payloads and " -NoNewline
Pause
logman stop $traceName -ets | Out-Null
}
$OSArchProperty = Get-CimInstance -ClassName Win32_OperatingSystem -Property OSArchitecture
$OSArch = $OSArchProperty.OSArchitecture
$OSPointerSize = 32
if ($OSArch -eq '64-bit') { $OSPointerSize = 64 }
Try {
$ErrorActionPreference = “silentlycontinue”
$AMSIEvents = $null
$AMSIEvents = Get-WinEvent -Path $tracePath -Oldest -FilterXPath '*[System[EventID=1101]]' | ForEach-Object {
if (-not $_.Properties) {
# The AMSI provider is not supplying the contentname property when WSH content is logged resulting
# in Get-WinEvent or Event Viewer being unable to parse the data based on the schema.
# If this bug were not present, retrieving WSH content would be trivial.
$PayloadString = ([Xml] $_.ToXml()).Event.ProcessingErrorData.EventPayload
[Byte[]] $PayloadBytes = ($PayloadString -split '([0-9A-F]{2})' | Where-Object {$_} | ForEach-Object {[Byte] "0x$_"})
$MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$PayloadBytes)
$BinaryReader = New-Object -TypeName IO.BinaryReader -ArgumentList $MemoryStream, ([Text.Encoding]::Unicode)
switch ($OSPointerSize) {
32 { $Session = $BinaryReader.ReadUInt32() }
64 { $Session = $BinaryReader.ReadUInt64() }
}
$ScanStatus = $BinaryReader.ReadByte()
$ScanResult = $BinaryReader.ReadInt32()
$StringBuilder = New-Object -TypeName Text.StringBuilder
do { $CharVal = $BinaryReader.ReadInt16(); $null = $StringBuilder.Append([Char] $CharVal) } while ($CharVal -ne 0)
$AppName = $StringBuilder.ToString()
$null = $StringBuilder.Clear()
$ContentSize = $BinaryReader.ReadInt32()
$OriginalSize = $BinaryReader.ReadInt32()
$ContentRaw = $BinaryReader.ReadBytes($ContentSize)
$Content = [Text.Encoding]::Unicode.GetString($ContentRaw)
$Hash = [BitConverter]::ToString($BinaryReader.ReadBytes(0x20)).Replace('-', '')
[Bool] $ContentFiltered = $BinaryReader.ReadInt32()
$BinaryReader.Close()
[PSCustomObject] @{
Session = $Session
ScanStatus = $ScanStatus
ScanResult = $ScanResult
AppName = $AppName
ContentName = $null
Content = $Content
Hash = $Hash
ContentFiltered = $ContentFiltered
}
} else {
$Session = $_.Properties[0].Value
$ScanStatus = $_.Properties[1].Value
$ScanResult = $_.Properties[2].Value
$AppName = $_.Properties[3].Value
$ContentName = $_.Properties[4].Value
$Content = [Text.Encoding]::Unicode.GetString($_.Properties[7].Value)
$Hash = [BitConverter]::ToString($_.Properties[8].Value).Replace('-', '')
$ContentFiltered = $_.Properties[9].Value
[PSCustomObject] @{
Session = $Session
ScanStatus = $ScanStatus
ScanResult = $ScanResult
AppName = $AppName
ContentName = $ContentName
Content = $Content
Hash = $Hash
ContentFiltered = $ContentFiltered
}
}
}
If ( $AMSIEvents.count -gt 0 ) { return $AMSIEvents }
Else { Write-host -ForegroundColor White "`tNo AMSI events found." }
}
Catch { Write-Host -ForegroundColor Yellow "Looks like there are no events... please try again." }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment