Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/msf/core/exploit/exe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ def generate_payload_exe_service(opts = {})
#Ensure opts[:arch] is an array
opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array

if opts[:arch] && opts[:arch].index(ARCH_X64)
if opts[:arch] && opts[:arch].index(ARCH_AARCH64)
exe = Msf::Util::EXE.to_winaarch64pe(framework, pl, opts)
elsif opts[:arch] && opts[:arch].index(ARCH_X64)
exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts)
else
exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts)
Expand Down
11 changes: 11 additions & 0 deletions lib/msf/util/exe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,20 @@ def to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
to_win32pe_service(framework, code, exeopts)
when ARCH_X64
to_win64pe_service(framework, code, exeopts)
when ARCH_AARCH64
# No dedicated AArch64 service template exists yet; the loader
# template still runs when dropped as a "service" binary (the SCM
# start request just times out, as with any non-service exe).
to_winaarch64pe(framework, code, exeopts)
end
when 'exe-small'
case arch
when ARCH_X86, nil
to_win32pe_old(framework, code, exeopts)
when ARCH_X64
to_win64pe(framework, code, exeopts)
when ARCH_AARCH64
to_winaarch64pe(framework, code, exeopts)
end
when 'exe-only'
case arch
Expand All @@ -165,6 +172,8 @@ def to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
exe = to_win32pe(framework, code, exeopts)
when ARCH_X64
exe = to_win64pe(framework, code, exeopts)
when ARCH_AARCH64
exe = to_winaarch64pe(framework, code, exeopts)
end
exeopts[:uac] = true
Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
Expand All @@ -174,6 +183,8 @@ def to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
exe = to_win32pe(framework, code, exeopts)
when ARCH_X64
exe = to_win64pe(framework, code, exeopts)
when ARCH_AARCH64
exe = to_winaarch64pe(framework, code, exeopts)
end
Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
when 'elf'
Expand Down
19 changes: 19 additions & 0 deletions lib/msf/util/exe/windows/aarch64.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ def self.included(base)
end

module ClassMethods
# The size, in bytes, of the fixed `payload[]` buffer declared in
# data/templates/src/pe/exe/template_aarch64_windows.c (SCSIZE). Shellcode
# longer than this would overwrite adjacent bytes in the compiled template.
WINAARCH64_PAYLOAD_SPACE = 8192

# Construct a Windows AArch64 PE executable with the given shellcode.
#
# Unlike the x86/x64 templates, there is currently no dedicated "service"
# or "dll" AArch64 template, so this loader-style template (which copies
# the payload into RWX memory and runs it in a new thread) is reused
# wherever an AArch64 PE is requested, including when a caller asked for
# an exe-service. That is safe for psexec-style delivery: Windows still
# spawns the process when the SCM start request times out because the
# binary doesn't speak the service control protocol.
# to_winaarch64pe
#
# @param framework [Msf::Framework] The Metasploit framework instance.
Expand All @@ -26,6 +39,12 @@ def to_winaarch64pe(framework, code, opts = {})

# Find the tag and inject the payload
bo = find_payload_tag(pe, 'Invalid Windows AArch64 template: missing "PAYLOAD:" tag')

if code.length > WINAARCH64_PAYLOAD_SPACE
raise RuntimeError, "The Windows AArch64 EXE generator has a max size of " \
"#{WINAARCH64_PAYLOAD_SPACE} bytes, please fix the calling module"
end

pe[bo, code.length] = code.dup
pe
end
Expand Down
16 changes: 12 additions & 4 deletions modules/exploits/windows/smb/psexec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,16 @@ def initialize(info = {})
},
'Platform' => 'win',
'Targets' => [
[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
# PowerShell isn't offered for AArch64: the PowerShell shellcode-injection
# wrapper (rex-powershell) only knows how to spawn x86/x64 powershell.exe,
# so it can't be used to run AArch64 shellcode.
[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64, ARCH_AARCH64] } ],
[ 'PowerShell', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'Native upload', { # upload a service executable
'Arch' => [ARCH_X86, ARCH_X64],
'Arch' => [ARCH_X86, ARCH_X64, ARCH_AARCH64],
'Payload' => { 'Space' => 2 ** 30 } # service executables place the payload within a segment, 1GiB is a practical max in many cases
} ],
[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64, ARCH_AARCH64] } ],
Comment on lines 74 to +78
[ 'Command', { 'Arch' => [ARCH_CMD], 'Payload' => { 'Space' => 8191 } } ]
],
'DefaultTarget' => 0,
Expand Down Expand Up @@ -145,7 +148,12 @@ def exploit

case target.name
when 'Automatic'
if powershell_installed?(smbshare, datastore['PSH_PATH'])
# The PowerShell delivery path can only launch x86/x64 powershell.exe, so
# an AArch64 payload has to go straight to the native upload technique.
if payload_instance.arch.include?(ARCH_AARCH64)
print_status('Selecting native target')
native_upload_with_workaround(smbshare)
elsif powershell_installed?(smbshare, datastore['PSH_PATH'])
print_status('Selecting PowerShell target')
execute_powershell_payload
else
Expand Down
Loading