# step_veh_64_shellcode_loader **Repository Path**: cutecuteyu/step_veh_64_shellcode_loader ## Basic Information - **Project Name**: step_veh_64_shellcode_loader - **Description**: 一个基于 Windows 异常处理机制的 64 位 Shellcode 加载器,支持 XOR 加密和动态内存保护。 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-14 - **Last Updated**: 2026-02-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Shellcode Loader (64-bit) > Reference: https://github.com/Ymjie/ShellStepVEH > Main modifications: Support for 64-bit, raw shellcode input, and encrypted content processing A 64-bit shellcode loader based on Windows exception handling mechanism, supporting XOR encryption and dynamic memory protection. ## Project Overview This project implements a complete shellcode loading framework with the following main features: - **XOR Encryption/Decryption**: Uses a simple XOR algorithm to encrypt shellcode, bypassing static signature detection - **Exception Handling Mechanism**: Utilizes Windows VEH (Vectored Exception Handler) for single-step tracing and memory protection - **Instruction Parsing**: Supports ModR/M and SIB parsing for x86/x64 instructions for memory access analysis - **Modular Design**: Code is decoupled into multiple independent modules for easy maintenance and extension ## File Structure ``` . ├── main.cpp # Program entry point (approx. 58 lines) ├── registers.hpp # 64-bit register structure definitions ├── instruction.hpp/.cpp # x86/x64 instruction parsing module ├── exception_handler.hpp/.cpp # Exception handling module ├── enc_shellcode.hpp # Encrypted shellcode (auto-generated) ├── encrypt_shellcode.cpp # Shellcode encryption tool ├── shellcode.cpp # Raw shellcode (example) └── README.md # This file ``` ## Compilation Instructions ### Environment Requirements - Windows operating system (64-bit) - MinGW-w64 or MSVC compiler - C++17 standard support ### Compilation Steps #### 1. Compile the encryption tool ```bash g++ encrypt_shellcode.cpp -o encrypt_shellcode.exe -std=c++17 ``` #### 2. Generate encrypted shellcode ```bash .\encrypt_shellcode.exe ``` After running, an `enc_shellcode.hpp` file will be generated, containing: - `XOR_KEY`: Encryption key (default 0x1C) - `SHELLCODE_SIZE`: Shellcode size - `ENCRYPTED_SHELLCODE[]`: Encrypted shellcode array #### 3. Compile the main program ```bash g++ main.cpp instruction.cpp exception_handler.cpp -o main.exe -std=c++17 -Wall ``` ### Compilation Options - `-std=c++17`: Use C++17 standard - `-Wall`: Enable all warnings - `-O2`: Optional, enable optimization (recommended for release builds) ## Usage Instructions ### Basic Usage Workflow 1. **Prepare Shellcode** - Place raw shellcode into the `buf[]` array in `shellcode.cpp` - Or use the default shellcode in `encrypt_shellcode.cpp` 2. **Encrypt Shellcode** ```bash .\encrypt_shellcode.exe ``` 3. **Compile and Run** ```bash g++ main.cpp instruction.cpp exception_handler.cpp -o main.exe -std=c++17 .\main.exe ``` ### Replacing Shellcode 1. Modify the `buf[]` array in `encrypt_shellcode.cpp`: ```cpp unsigned char buf[] = "\xfc\x48\x83..."; // Your shellcode ``` 2. Re-run the encryption tool to generate a new header file 3. Recompile the main program ## Code Architecture Details ### 1. Register Definition Module (registers.hpp) ```cpp typedef struct { DWORD64 rax, rcx, rdx, rbx; DWORD64 rsp, rbp, rsi, rdi; DWORD64 r8, r9, r10, r11; DWORD64 r12, r13, r14, r15; DWORD64 rip; } Registers64; ``` Defines the complete x64 register set for saving and restoring CPU state during exception handling. ### 2. Instruction Parsing Module (instruction.hpp/cpp) #### Core Functions - **ModR/M Parsing**: Parses the ModR/M byte of x86/x64 instructions ```cpp void parse_modrm(uint8_t modrm, uint8_t* mod, uint8_t* reg, uint8_t* rm); ``` - **SIB Parsing**: Parses the Scale-Index-Base byte ```cpp void parse_sib(uint8_t sib, uint8_t* scale, uint8_t* index, uint8_t* base); ``` - **Memory Address Calculation**: Calculates target memory address based on instruction ```cpp DWORD64 calculate_memory_address(...); ``` - **Instruction Analysis**: Identifies memory-accessing instructions like MOV, LEA ```cpp DWORD64 analyze_instruction(uint8_t* opcode, const Registers64* regs); ``` #### Supported Instruction Types - String manipulation instructions (MOVSB, MOVSW, MOVSD, MOVSQ) - Two-byte opcodes (0F xx) - General instructions with ModR/M - REX prefix (64-bit mode) ### 3. Exception Handling Module (exception_handler.hpp/cpp) #### Global State Variables ```cpp extern unsigned char* g_shellcode; // Shellcode base address extern SIZE_T g_shellcodeSize; // Shellcode size extern DWORD64 g_previousRip; // Previous instruction address extern bool g_inShellcode; // Whether in shellcode range extern Registers64 g_regs; // Register state ``` #### Core Functions **Initialize Exception Handling** ```cpp void initExceptionHandler(unsigned char* shellcode, SIZE_T size); ``` **Install/Uninstall Exception Handler** ```cpp bool installExceptionHandler(); void uninstallExceptionHandler(); ``` **Exception Handler Callback** ```cpp LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo); ``` #### Exception Handling Flow 1. **STATUS_ACCESS_VIOLATION** (Access Violation) - Detect if execution is within shellcode range - Modify memory protection attribute to `PAGE_EXECUTE_READWRITE` - Set single-step flag (EFlags |= 0x100) - Continue execution 2. **EXCEPTION_SINGLE_STEP** (Single Step Exception) - If inside shellcode: continue single-step tracing - If outside shellcode: set memory to `PAGE_NOACCESS` 3. **External Access Detection** - Detect if any code attempts to read shellcode memory - Temporarily modify protection attributes to allow access ### 4. Main Program (main.cpp) #### Execution Flow ``` ┌─────────────────────────────────────┐ │ 1. Allocate read-write memory (RW) │ │ VirtualAlloc(..., PAGE_READWRITE)│ ├─────────────────────────────────────┤ │ 2. Copy encrypted shellcode │ │ memcpy(shellcode, ENCRYPTED_...) │ ├─────────────────────────────────────┤ │ 3. XOR decryption │ │ xorDecrypt(shellcode, size, key) │ ├─────────────────────────────────────┤ │ 4. Install exception handler │ │ AddVectoredExceptionHandler(...) │ ├─────────────────────────────────────┤ │ 5. Execute shellcode │ │ shellcodeFunc() │ ├─────────────────────────────────────┤ │ 6. Cleanup resources │ │ RemoveVectoredExceptionHandler │ │ VirtualFree │ └─────────────────────────────────────┘ ``` ## Technical Principles ### 1. XOR Encryption XOR encryption is a symmetric encryption algorithm using the same key for encryption and decryption: ``` Encryption: cipher = plain ^ key Decryption: plain = cipher ^ key ``` Advantages: - Simple implementation, fast speed - Same code for encryption and decryption - Does not change data length ### 2. Exception Handling Mechanism #### VEH (Vectored Exception Handler) Windows provides a structured exception handling mechanism allowing programs to register global exception handling functions: ```cpp PVOID AddVectoredExceptionHandler( ULONG First, // 1 = called first PVECTORED_EXCEPTION_HANDLER Handler // handler function ); ``` #### Single-Step Execution Implemented by setting the TF (Trap Flag) bit of the EFLAGS register: ```cpp ExceptionInfo->ContextRecord->EFlags |= 0x100; ``` Triggers `EXCEPTION_SINGLE_STEP` exception after each instruction execution. #### Memory Protection Attributes - `PAGE_READWRITE` (RW): Readable and writable, not executable - `PAGE_EXECUTE_READWRITE` (RWX): Readable, writable, and executable - `PAGE_NOACCESS`: Not accessible ### 3. x86/x64 Instruction Format #### ModR/M Byte Structure ``` 7 6 5 4 3 2 1 0 +-----+------+------+ | Mod | Reg | R/M | +-----+------+------+ ``` - **Mod** (2 bits): Addressing mode - 00: Indirect addressing (no displacement) - 01: Indirect addressing (8-bit displacement) - 10: Indirect addressing (32-bit displacement) - 11: Register direct addressing - **Reg** (3 bits): Register number or opcode extension - **R/M** (3 bits): Register/memory operand #### SIB Byte Structure ``` 7 6 5 4 3 2 1 0 +-----+------+------+ |Scale| Index| Base | +-----+------+------+ ``` Used for complex memory addressing calculation: ``` Address = Base + (Index << Scale) + Displacement ``` ## Security Notes ### 1. Detection Evasion - **Static Analysis**: XOR encryption prevents shellcode from existing in plaintext in the file - **Dynamic Analysis**: Exception handling mechanism increases debugging difficulty - **Memory Scanning**: Frequent modification of memory protection attributes interferes with memory scanning ### 2. Limitations - XOR encryption has low strength and can be easily cracked - Exception handling has performance overhead - Some EDR products may monitor exception handlers ### 3. Improvement Suggestions - Use stronger encryption algorithms (AES, RC4, etc.) - Add anti-debugging techniques - Implement code obfuscation - Use indirect system calls ## Debugging Tips ### 1. Using WinDbg ```bash windbg -g main.exe ``` ### 2. Setting Breakpoints ``` bp main!main bp main!ExceptionHandler ``` ### 3. Viewing Exception Information ``` !analyze -v .exr -1 ``` ### 4. Common Errors | Error | Cause | Solution | |-------|-------|----------| | Access Violation | Shellcode attempts to access invalid memory | Check if shellcode is complete | | Illegal Instruction | Shellcode corrupted or architecture mismatch | Confirm it is 64-bit shellcode | | Exception Loop | Exception handling logic error | Check EFlags settings | ## License This project is for educational and research purposes only. Please do not use it for illegal purposes. ## References 1. [Intel 64 and IA-32 Architectures Software Developer's Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html) 2. [Windows VEH Documentation](https://docs.microsoft.com/en-us/windows/win32/debug/vectored-exception-handling) 3. [x86-64 Instruction Encoding](https://wiki.osdev.org/X86-64_Instruction_Encoding)