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

Fixed segment_injector.rb x64 shellcode #13979

Merged
merged 3 commits into from
Aug 21, 2020
Merged

Fixed segment_injector.rb x64 shellcode #13979

merged 3 commits into from
Aug 21, 2020

Conversation

Michael-ZecOps
Copy link
Contributor

During an evaluation of our ZecOps Crash Analysis solution, one of our partners brought to our attention an interesting crash. He claimed that he followed this guide: Backdooring While Preserving Functionality, but the backdoored app crashed right away. Looking at the crash, we quickly spotted the problem: due to an unaligned stack pointer, the process crashed on an SMID instruction (movaps). For a short explanation, see: https://stackoverflow.com/a/5540149

While composing the pull request, I found another problem - the call to CreateThread wasn't done properly. Not only the stack pointer was unaligned and no shadow stack was reserved, but also the two zeros pushed on the stack weren't the actual parameters 5 and 6. The fact that this code even worked is pure accident, probably because the Windows loader happens to set the proper locations on the stack to zero. In any case, that's fixed as well.

I did a quick check, the new shellcode should work properly, but I'm not 100% sure about the syntax, I didn't check it with the tooling. As one smart researcher once said:

Reverse shell generated by msfvenom. Can you believe I had to download Kali Linux for this shit?

:)

Copy link
Contributor

@OJ OJ left a comment

Choose a reason for hiding this comment

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

As one smart researcher once said

Smart, but couldn't install MSF without Kali? 👍

Reverse shell generated by msfvenom. Can you believe I had to download Kali Linux for this shit?

I've not used Kali for any reason for 6 years. So, no, I don't believe that anyone has to "download Kali for this shit". Installing MSF is trivial on stacks of different operating systems.

Anyway, thanks for the submission. I've added a few comments for clarification to various parts of the code. Cheers!

lib/msf/core/exe/segment_injector.rb Show resolved Hide resolved
lib/msf/core/exe/segment_injector.rb Show resolved Hide resolved
lib/msf/core/exe/segment_injector.rb Outdated Show resolved Hide resolved
mov r9, 0
xor ecx, ecx
mov qword ptr [rsp+28h], rcx
mov qword ptr [rsp+20h], rcx
Copy link
Contributor

Choose a reason for hiding this comment

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

I'll admit that this change confuses me a little. I would expect to see two 0 values at [rsp] and [rsp+8] to represent parameters 5 and 6. But that's not what this is doing.

Can you please explain why you're writing zeros to the shadow space rather than at the top of the stack?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why you're writing zeros to the shadow space

That's exactly what the previous code did, and this fixes it. Here's one of the Google Images results for "shadow stack x64", feel free to read more about it: https://modexp.files.wordpress.com/2017/01/x64_hs.png?w=640

Copy link
Contributor

Choose a reason for hiding this comment

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

I can confirm some x86_64 calling conventions I have used put params 5+ on the stack where they would have been under an all-stack (x86-style) convention. The MS docs on calling convention support this as well:

The x64 Application Binary Interface (ABI) uses a four-register fast-call calling convention by default. Space is allocated on the call stack as a shadow store for callees to save those registers. ... Any parameters beyond the first four must be stored on the stack after the shadow store before the call.

@Michael-ZecOps
Copy link
Contributor Author

Regarding the msfvenom quote, it's not about Kali, but more about the fact that tooling can be annoying. And I believe that what was meant in "download Kali for this shit" was:
Download Kali for the shitty 10-seconds keyboard smash to generate the shellcode.
And not:
Download Kali for the shitty framework (if she'd think it's shitty, she wouldn't be using it, right?).

In any case, I hope nobody's offended. I personally think you're doing a great and important job of making security more accessible, and as a result making people more aware.

@smcintyre-r7 smcintyre-r7 self-assigned this Aug 21, 2020
@smcintyre-r7
Copy link
Contributor

Alright so I was able to reproduce the issue this is fixing. Following the guide: Backdooring While Preserving Functionality wasn't really enough. The key is using a 64-bit payload and 64-bit template file where as the guide uses 32-bit and then injects an x64 payload so you can't follow it verbatim.

I used a 64-bit copy of Putty and was able to reproduce this on my first try. Having said that, once I started testing this fix, I found that the latest commit (5877c79) seems to break the mfsvenom command while the previous one (f043e4b) works.

Error on commit 5877c79
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
Found 3 compatible encoders
Attempting to encode payload with 1 iterations of generic/none
generic/none failed with Encoding failed due to a bad character (index=7, char=0x00)
Attempting to encode payload with 1 iterations of x64/xor
x64/xor succeeded with size 551 (iteration=0)
x64/xor chosen with final size 551
Error: Unresolved relocations:
checksum 
FFFFFFFFFFFFFFF0h "\"<unk>\"" line 5

@smcintyre-r7 smcintyre-r7 merged commit 5877c79 into rapid7:master Aug 21, 2020
@smcintyre-r7
Copy link
Contributor

Alright the issue was easy enough for me to fix in commit f69facc. There was a syntax issue with metasm and the alignment was getting ruined again by the followup sub rsp, 38h instruction. With that fix in place I was consistently able to generate a working x64 payload with this technique. I got this merged in so thanks @Michael-ZecOps !

@smcintyre-r7
Copy link
Contributor

smcintyre-r7 commented Aug 21, 2020

Release Notes

Fixed an issue with the 64-bit segment injector logic used by 64-bit PE templates. The injector now properly handles the arguments and stack alignment.

@Michael-ZecOps Michael-ZecOps deleted the patch-1 branch August 23, 2020 10:07
@pbarry-r7 pbarry-r7 added the rn-fix release notes fix label Sep 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug library rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants