-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Fix Linux Stageless Payload to be Shellcodes #19799
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
base: master
Are you sure you want to change the base?
Conversation
b3f3b8c to
128ac84
Compare
|
This makes a lot of sense- my only complaint is that we need to comment the asm a lot more, especially when you're doing shenanigans. 😆 |
|
Also, what are you using to test this? Do you have a elf that supports injection, or are you only testing by creating an elf stager from the shellcode? |
I generated ELF file using |
modules/payloads/singles/linux/aarch64/meterpreter_reverse_http.rb
Outdated
Show resolved
Hide resolved
2025792 to
56c4506
Compare
bwatters-r7
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor cheat sheet additions
x64 |
AARCH64 |
ARMLE |
MIPSLEThis fails with segfault. I'm running it on a router, so I cannot get GDB installed, but gdb server works. Linux version: EDIT |
5192b65 to
0407bb7
Compare
It's causing segfault on this instruction: So the issue is with Meterpreter itself - on qemu, it seems to be working though. UPDATE: |
f66a5aa to
725fd05
Compare
smcintyre-r7
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good, just left a couple of comments. I'll look at what still needs to be tested to get those over the line next.
| app << appends_map.fetch(name) if datastore[name] | ||
| end | ||
| if ds['PayloadLinuxMinKernel'] == '2.6' && (!pre.empty? || !app.empty?) && !staged? | ||
| fail_with(Msf::Module::Failure::BadConfig, 'Prepend options only work with PayloadLinuxMinKernel = 3.17.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| fail_with(Msf::Module::Failure::BadConfig, 'Prepend options only work with PayloadLinuxMinKernel = 3.17.') | |
| fail_with(Msf::Module::Failure::BadConfig, 'Prepend options only work with PayloadLinuxMinKernel >= 3.17.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your suggestion but since the PyaloadLinuxMinKernel is an ENUM type isn't it more correct to use the =? since they have to set exactly that value from the enum
| if ds['PayloadLinuxMinKernel'] == '3.17' | ||
| return in_memory_load(payload) + payload | ||
| end<% end %> | ||
| payload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know this was templatized, that's great! I'd recommend these changes.
- Using
Rex::Versionshould help future proof things by ensuring that we can adjust the number later on. - Move the clause that's executed when the version is < 3.17 to the branch. This will clean things up as we add additional code in the future since the kernel isn't getting any younger. Basically when we require something else after 3.17, we'll add it to the end of the function instead of further burying it in the conditional.
| if ds['PayloadLinuxMinKernel'] == '3.17' | |
| return in_memory_load(payload) + payload | |
| end<% end %> | |
| payload | |
| if Rex::Version.new(ds['PayloadLinuxMinKernel']) < Rex::Version.new('3.17') | |
| return payload | |
| end | |
| in_memory_load(payload) + payload<% else %> | |
| payload | |
| <% end %> | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I didn't catch why you need the dynamic version checking here, can you explain why do you think this number will change in the future? like if we implement another technique?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like if we implement another technique?
Exactly this. In 10 years when kernel 8 comes out and we're looking to do something requiring kernel version 4.something, we'll have to go through and update all these things. It's better to do it now while we know where all the changes need to be made.
|
To get this landed, it looks like these are all the architectures where the in-memory loader needs to be tested: HOW TO TEST IT
TO BE DROPPED @dledda-r7
|
|
@smcintyre-r7, as per our discussion on slack. This morning i double checked the Binary with
|
|
If it's a Meterpreter issue then, I should be able to test the stageless shell payloads |
|
No you can't because this Fix was specifically for stageless meterpreter as they are the only ELF we deliver that needs to be transformed to shellcodes the stageless shells are just shellcode and doesn't need any in memory loader |
This PR Fixes the issue of linux stageless meterpreter.
Issue: #19670
Issue Description
The stageless linux meterpreters are ELF files that cannot be used as standard stageless shellcode payload.
Staged vs Stageless Linux Meterpreter
Staged
The Linux staged meterpreter is divided in 3 component
e_entryof the ELFThis version of the ELF is generated when we build mettle using the following tool: elf2bin
Stageless
The stageless mettle payload is the ELF file (standard elf) with the patched args.
Code Handling Staged vs Stageless
Mettle main.c
Solution
For each architecture, a shellcode implementing this technique was made.
NOTE: This technique works only with Kernel >= 3.17
Instead of delivering the ELF only, the raw shellcode will be composed by the
in-memory-loaderarch specific shellcode and the elf file at the end of it.Super thanks to @msutovsky-r7
What architectures fix this pr:
linux/x86linux/x64linux/armlelinux/armbe(emulated)linux/aarch64linux/mipslinux/mipsel(to check device avaiability)linux/mips64(find target with kernel 3.17 / updated one of the targets)linux/ppc( to be removed)linux/ppc64le(emulated)linux/ppce500v2linux/zarch(emulated)What is inside the PR and How to test it
<arch>/in_memory_loader.rbinclude the architecture specific shellcode to be prepended to the ELF binary.<arch>/prepends.rbmixin for the missing architectures.2.6or to3.17kernels.2.6.meterpreter_reverse.erbtemplate for payload generation.What to test
MeterpreterLinuxMinKernelis2.6+is the same as beforeMeterpreterLinuxMinKernelis3.17is using the correct ELF template and is executed on a compatible target.MeterpreterLinuxMinKernelis3.17otherwise a warning is showed.