PowerShell sans AMSI #24750
Replies: 3 comments 10 replies
|
I need the same patches for WASM Browser, WASI and Android where there is no AMSI or Telemetry is not possible. |
|
Well, this has breathed new life into PowerShell...
Loading ASP.NET run time is as simple as Program.ps1 This works with the standard dotnet runtime irrespective of where it is installed, version or operating system. Then I can simply use New-AspNetForPowerShellWebApplication. |
|
After contemplating the various options, including building my own PowerShell with the patches from rhubarb-geek-nz applied, I've settled on this compromise: & {
if ($PSVersionTable.PSVersion -lt '7.3') { return }
$fi = [psobject].Assembly.GetType('System.Management.Automation.Language.CachedReflectionInfo').GetField('MemberInvocationLoggingOps_LogMemberInvocation', [System.Reflection.BindingFlags]'NonPublic, Static')
if ($null -eq $fi) {
Write-Host '**DeAmsify** Field not found: MemberInvocationLoggingOps_LogMemberInvocation'
return
}
$mi = $fi.GetValue($null)
if ($mi -is [System.Reflection.Emit.DynamicMethod]) {
Write-Host '**DeAmsify** Already dynamic: MemberInvocationLoggingOps_LogMemberInvocation'
return
}
if ($mi -isnot [System.Reflection.MethodInfo] -or $mi.ReturnType -ne [void]) {
Write-Host '**DeAmsify** Invalid MethodInfo: MemberInvocationLoggingOps_LogMemberInvocation'
return
}
$paramTypes = [type[]] ($mi.GetParameters() | Select-Object -ExpandProperty ParameterType)
$dmReplacement = [System.Reflection.Emit.DynamicMethod]::new('', $null, $paramTypes, $true)
$dmReplacement.GetILGenerator().Emit([System.Reflection.Emit.OpCodes]::Ret)
# Target field is readonly, use DynamicMethod to bypass.
$dmSetter = [System.Reflection.Emit.DynamicMethod]::new('', $null, [type[]]@([System.Object]), $true)
$il = $dmSetter.GetILGenerator()
$il.Emit([System.Reflection.Emit.OpCodes]::Ldarg_0)
$il.Emit([System.Reflection.Emit.OpCodes]::Stsfld, $fi)
$il.Emit([System.Reflection.Emit.OpCodes]::Ret)
$dmSetter.Invoke($null, @(, $dmReplacement))
}Unlike a dedicated build, this doesn't get fully rid of AMSI logging. It only mitigates against the worst offender with regards to security and performance, the method invocation logging. It also needs to be the first thing that runs in a PowerShell session (e.g. at the very top of a profile script), otherwise compiled scripts will refer to the original method. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
It has been firmly established that AMSI logging within PowerShell is non-negotiable.
However if you have use cases where you don't want to accept the overhead you may consider trying PowerShell sans AMSI.
This is a fork of PowerShell which removes AMSI logging, Telemetry and version update checking.
It also uses the dotnet shared runtime rather than packaging its own, this means you can use ASP.NET more easily directly from
pwsh.exe.All reactions