Gh0st远控源码编译与剖析:从IOCP模型到恶意软件行为分析 简介2025 年首次发布的 Gh0st 远控源码工程基于 Visual Studio 2019 构建定位为完整可编译的远程控制软件项目适合安全研究人员、网络管理员以及具备 C 基础的开发者学习远控软件设计与实现。压缩包共 198 个文件大小约 9.6MB主要包含 60 个头文件、48 个 C 源文件、17 个图标与位图资源以及解决方案和项目配置文件可完整还原编译环境并查看界面资源设计。已有 64 人浏览学习。源码工程覆盖文件传输、视频监控、音频捕捉、远程协助等常见功能模块同时涉及多协议通信与安全加密机制通过阅读代码可理解远控软件的核心工作流程、网络通信设计和界面交互逻辑。项目主分支代码组织清晰便于二次开发与功能扩展对想深入研究远控原理或进行安全防御研究的读者都很有参考价值。1. Gh0st 远控源码2025 年还翻出这份代码到底在看什么先说结论这不是拿来即用的黑客工具而是一份几乎可以当教科书读的老牌远控源码。Gh0st 是 2008 年左右开源的经典远控项目C/S 架构、IOCP 完成端口模型、模块化插件设计代码风格干净协议清晰至今仍是很多安全研究员分析远控行为、蓝队做流量特征提取、红队做内部渗透测试教学的首选样本。用 VS2019 打开这份代码你会发现它几乎不依赖第三方库编译出来就是一个完整的控制端和客户端——屏幕监控、文件管理、键盘记录、远程 Shell、系统管理该有的模块全都在。它适合谁三类人最值得下载一是做恶意软件分析的安全工程师需要一份能看懂、能编译、能跑起来观察行为的远控样本二是做红队攻防演练的渗透测试人员在授权范围内用它理解老牌远控的通信机制和免杀演变三是刚入门 Windows 网络编程的开发者想研究 IOCP 模型和 Socket 通信实战Gh0st 的代码比很多教程写得好。至于普通网友拿来“监控别人电脑”那是误用也是违法行为本文所有分析都默认在授权实验环境、虚拟机隔离网段内进行。下面进入正题把这份源码的模块结构、编译步骤和坑一次讲透。2. 源码模块拆解先看懂 Gh0st 的 C/S 骨架和 IOCP 模型再谈编译2.1 控制端与客户端的工程划分两个项目、一套协议解压源码后第一件事不是急着编译而是先看目录结构。Gh0st 源码通常包含Server控制端也叫管理端和Client被控端两个独立工程再加一个公共的协议头文件。控制端是 MFC 界面程序负责下发指令、接收回传数据被控端是 Windows 服务程序安装后常驻后台主动反向连接控制端。核心通信协议都定义在Protocol.h或类似命名文件里是一组命令字与结构体的映射。比如常见的命令码0x01开关屏幕、0x02屏幕控制、0x03文件管理、0x04语音监听、0x05系统管理、0x06键盘记录。每个命令都带一个CMD_前缀的结构体里面是命令参数和命令长度。这块建议逐行读因为你后面做免杀改造或者二次开发改协议字段就是从这里下手。// Protocol.h 中的典型命令结构示例性质与源码略有出入 #pragma pack(push, 1) typedef struct { int CommandId; // 命令字如 CMD_FILE_TRANSFER int DataLength; // 后续数据长度 char DataBuffer[1]; // 变长数据起始位置 } CMD_HEADER, *PCMD_HEADER; #pragma pack(pop)这段代码是典型的变长结构体设计。DataBuffer[1]是占位符实际使用时通过malloc(sizeof(CMD_HEADER) DataLength - 1)分配整块内存然后从DataBuffer开始填充数据。#pragma pack(push, 1)是强制内存按 1 字节对齐保证结构体在不同编译选项下大小一致——远控通信最怕协议头大小不一致导致双方解析错位、直接断连。我一般建议改这个文件里的任何一个字段都要同步修改控制端和被控端的定义并重新编译验证。再看 IOCP 模型。Gh0st 的服务端被控端和客户端控制端都用了完成端口这是 Windows 下最高效的网络模型之一。核心逻辑在IOCPServer.cpp/IOCPClient.cpp里线程池 投递接收请求 完成回调处理。理解这个模型的关键在于它不是每个连接开一个线程而是少数几个工作线程轮流处理成千上万个 Socket 的完成通知。这也是 Gh0st 当时性能优于同期远控的重要原因。2.2 六大功能模块逐个过屏幕、文件、键盘、Shell、语音、系统管理Gh0st 的功能全在这六个模块类里。建议按这个顺序读由浅入深模块类名对应功能核心实现要点CScreenManager屏幕监控与远程控制截屏、差分传输、鼠标键盘事件注入CFileManager文件管理枚举目录、上传下载、删除重命名CKeyBoardManager键盘记录低级键盘钩子记录按键日志CRemoteShell远程 Shell匿名管道 CreateProcesscmd 交互CSpeechManager语音监听录音设备捕获音频流回传CSystemManager系统管理进程、服务、注册表、窗口管理挑两个最容易被低估的说。CScreenManager里的屏幕差分算法值得细看——它不是每次都传整屏位图而是计算前后两帧的差异区域再做 JPEG 压缩。理解这块对优化带宽很有帮助比如你内网测试时觉得画面卡可以尝试把差异块阈值调大、压缩质量调低。另一个是CRemoteShell它用 CreateProcess 启动 cmd.exe然后把标准输入输出重定向到匿名管道主线程持续读取管道输出并加密后回传控制端。很多新手在这里翻车原因是管道句柄的继承属性没设对子进程拿不到句柄Shell 一片黑。模块图控制端MFC→ 指令封装 → IOCP 发送 → 被控端 IOCP 接收 → 分发到对应 Manager 类 → 执行系统调用 → 结果回传。整条链路每个环节都有对应的加密和压缩处理默认是简单的 XOR 加密加压缩后面可以自己替换成 AES。2.3 内存中的常驻与安装逻辑被控端启动流程被控端不是双击运行这么简单。它编译出来是一个普通 exe但运行时会有安装流程复制自身到C:\Windows\System32\目录、改名、写入注册表启动项或注册成服务、然后删除原始文件。源码里这段逻辑通常在CInstall或InitInstance相关文件中。启动时序是检查是否已安装 → 读取配置控制端 IP、端口、上线间隔→ 拷贝自身到系统目录 → 写注册表/服务 → 创建互斥体防多开 → 启动 IOCP 服务线程 → 循环尝试连接控制端。里面有个细节值得学习连接控制端失败后不是立即重试而是用Sleep加随机延迟避免暴风式扫描把目标机器资源耗尽。这段逻辑你如果用Process Monitor观察能在注册表和文件系统Activity里看到清晰的轨迹。互斥体Mutex的命名也很有讲究Gh0st 源码里通常会生成一个带机器特征的互斥体名防止同一台机器重复运行多个实例同时也能用来判断是否已经被感染。理解这个逻辑之后你在做蓝队排查时可以用Handle.exe查可疑进程持有的互斥体名来定位远控进程。3. VS2019 编译全流程环境配置、工程升级、字符集与工具集的四个坑3.1 源码用 VS2019 打开前先解决工程格式兼容这份源码年代久远工程文件大概率是 VS2008 / VS2010 格式.sln里的版本号写着10.00或更低。VS2019 打开时会有一次性的工程升级提示一般点“确定”即可VS 会自动把.vcproj转成.vcxproj。但有一个前置步骤容易被忽略先把整个目录复制一份做备份并且保证解压路径不含中文和空格。原因是升级过程会改工程文件万一编译出问题你想回退原版还在而路径含中文时 VS 的cl.exe偶尔会抽风报奇怪的找不到头文件。打开后建议第一步去“解决方案管理器”里确认两个项目的“属性 → 配置属性 → 常规 → 平台工具集”已经变成Visual Studio 2019 (v142)。如果没变手动改掉否则会报 MSB8020 错误。# 编译前建议检查的工程属性项VS2019 界面操作路径 项目右键 → 属性 → 配置属性 1. 常规 → 平台工具集 Visual Studio 2019 (v142) 2. 常规 → 字符集 使用多字节字符集 3. C/C → 语言 → 符合模式 否 4. C/C → 预处理器 → 预处理器定义 WIN32;_WINDOWS;NDEBUG这四个配置缺一不可。平台工具集决定编译器的具体版本多字节字符集是因为老代码里大量用了char*和CString混用Unicode 字符集下类型转换会报错符合模式是避免for循环变量作用域等 C11 标准检查把老代码判死刑预处理定义这块要注意如果源码里需要调试输出把NDEBUG换成_DEBUG但生产环境编译远控一般都用 Release NDEBUG。3.2 Release x86 编译一次过很难但报错都有规律Gh0st 源码目标平台是 32 位VS2019 默认生成平台是Win32。在工具栏的解决方案平台里选择Release - Win32或x86取决于工程配置别用 x64——很多老代码假设指针是 4 字节硬编译 x64 会出一堆C4311指针截断警告甚至直接报错。我踩过这个坑当时图省事直接编 x64结果CFileManager里一个DWORD_PTR传参直接数据溢出文件传输断流。老实换回 Win32 之后一次过。编译时先编控制端Server 工程再编被控端Client 工程。顺序上有讲究控制端编译成功说明公共头文件和协议定义没问题被控端的错误只会在独立的实现文件里。如果两个同时编译报一堆乱错优先检查公共头文件是不是被工程引用漏了——常见做法是在两个工程里分别添加Header Files筛选器把同一个Protocol.h引进去。编译过程中最高频的报错是C4996xxx: The POSIX name for this item is deprecated。原因是老代码用了strcpy、sprintf、fopen等 CRT 函数VS2019 默认报错。解决方法是二选一项目属性里加预处理器定义_CRT_SECURE_NO_WARNINGS或者代码文件头部加#pragma warning(disable:4996)。我习惯用前者一处设置全工程生效省心。3.3 生成文件的文件清单编译完你该拿到哪些东西编译成功后在工程输出目录通常是Release文件夹下会生成两个关键文件Server\Release\Server.exe # 控制端MFC 程序有窗口界面 Client\Release\hlpbnst.exe # 被控端名字可能被作者改过无窗口后台程序被控端 exe 的名字不一定叫 Client源码里可能在Resource.h中定义了一个“伪装名”比如hlpbnst.exe、spoolsv.exe这种仿系统进程的名字。编译时这个名字通过#define MAIN_PROGRAM_NAME之类的宏控制。如果你做实验需要区分自己编译的样本和公网样本建议改掉这个名字避免混淆。编译完后先别急着双击。被控端是远控程序你一旦在物理机上运行它它就会尝试把自身安装进系统目录并连接配置好的控制端——如果你配置的 IP 是外网或局域网内真实机器这会带来风险。正确做法是准备两台虚拟机或者一台虚拟机 宿主机防火墙放行指定端口且控制端 IP 写内网测试地址。这个坑下面专门用一节说。4. 配置参数与动态上线控制端 IP、端口、上线时间的正确设置4.1 被控端参数藏在哪不是配置文件是 C 宏Gh0st 这类老远控有个共性被控端要连接的 IP、端口、上线间隔不是运行时读配置文件而是编译期写死在代码里通常集中在某个GlobalDefine.h或Config.h头文件中。之所以这么设计一方面是为了减少文件特征——运行目录少一个配置文件就少一个被查杀的线索另一方面是防止使用者在样本里直接改配置增加分析门槛。核心参数通常是这样一组宏// GlobalDefine.h 中的关键配置宏 #define HOST_ADDR 192.168.126.130 // 控制端 IP内网测试用虚拟 IP #define HOST_PORT 81 // 控制端监听端口避开 80/443 减少干扰 #define DELAY_TIME 5000 // 重连间隔 5000ms #define RUN_ON_STARTUP 1 // 是否开机自启1开启参数说明HOST_ADDR是控制端监听的 IPIPv4 字符串形式HOST_PORT是控制端开放的服务端口建议测试时用1024以上的端口避开常见 Web 和 FTP 端口避免跟业务冲突DELAY_TIME是被控端连接失败后的等待毫秒数太短会被控端疯狂重连浪费 CPU太长控制端上线响应慢内网测试 30005000 是合理区间RUN_ON_STARTUP控制是否注册自启动测试时建议设0否则每次重启虚拟机都要先杀进程再清理注册表血泪经验。4.2 控制端防火墙与监听你以为是代码 bug其实是网络策略控制端作为服务端需要监听一个 TCP 端口等待被控端反向连接。如果你按上面配置了HOST_PORT 81Windows 防火墙默认会拦截入站连接。我第一次跑的时候双击控制端完全没反应被控端那边日志显示连接被拒绝查了半天才发现是防火墙拦了 81 端口。# 以管理员身份在控制端机器上执行放行指定 TCP 端口 netsh advfirewall firewall add rule nameGh0st Test Port dirin actionallow protocolTCP localport81规则名称自定dirin表示入站规则protocolTCP指定协议localport改成你源代码里设置的端口。执行完可以用netstat -ano | findstr :81确认端口进入监听状态。注意如果你控制端机器本身在 NAT 后面比如家用路由器还需要在路由器上做端口映射否则被控端无法从外部连接——但内网测试完全不需要虚拟机和宿主机之间走 VMware NAT 网卡就能通信。4.3 被控端上线验证三步确认是否活了编译完、配置好、放行端口之后怎么确认被控端“上线”了按以下三步走缺一步都容易误判。第一步被控端虚拟机里用命令行运行hlpbnst.exe -install或直接双击取决于安装逻辑。如果进程一闪而过然后消失了多半是“安装模式”——它已经复制自身到系统目录并尝试连接控制端了。此时用任务管理器查hlpbnst.exe是否驻留。第二步回到控制端看主界面下方的在线主机列表是否出现新的条目。如果列表空白立即到被控端抓网络包netstat -ano | findstr 81看是否有SYN_SENT状态——有则说明端口不通或防火墙拦截无则说明被控端根本没发起连接。第三步用 Wireshark 在被控端上抓包过滤tcp.port 81。看到三次握手完成并伴有后续数据包说明上线成功。这一步我一直保留着因为它能同时验证加密通信是否正常——如果流量里全是明文说明你改的加密开关没生效往后控制指令一把梭很容易被 IDS 直接报警。5. 避坑要点编译、运行、杀软三方面的常见问题与排查5.1 编译期fatal error C1189: #error : Please use the /MD switch现象编译到某个 cpp 文件时报 C1189 致命错误提示要用 /MD 开关停止编译。原因Gh0st 源码部分文件里用了_AFXDLL或 MFC 动态库相关宏要求运行库必须用多线程调试 DLL/MD但工程默认是静态链接 /MT两者冲突。解决项目属性 → C/C → 代码生成 → 运行库改为“多线程 DLL (/MD)”如果是 Debug 就选“多线程调试 DLL (/MDd)”。注意控制端和被控端两个工程要分别改。从那以后我每次用 VS 打开老 MFC 工程第一步就检查运行库设置。5.2 运行期被控端双击后消失进程列表里也找不到现象双击被控端 exe进程闪一下就没任务管理器查不到控制端列表无上线。原因八成是进程在“安装模式”下跑完退出了。Gh0st 的安装逻辑通常是第一次运行时把自己复制到系统目录写入注册表 Run 键然后立即退出之后每次开机由注册表项启动。它在当前目录运行时不驻留所以“双击没反应”反而是正常现象。解决重启被控端虚拟机观察重启后进程是否出现在系统进程列表里或者先用命令行手动运行并带调试参数如果源码里实现了-debug之类的开关再看输出。另外注意如果你之前测试过残留了同名进程用taskkill /f /im hlpbnst.exe清掉再测。5.3 杀软处理编译产物被当场查杀无法运行现象VS2019 编译完成输出目录里的 exe 刚生成就被 Windows Defender 或其他杀软隔离连复制到虚拟机都做不到。原因Gh0st 是老样本特征码早就被各大杀软收录编译出的代码哪怕一行没改PE 文件里的功能特征如远程 Shell 管道、注册表自启动、屏幕截取 API 调用序列也足以触发启发式引擎。解决你是在做安全研究不是做免杀逃逸最稳妥的办法是把整个测试目录加入杀软白名单并把虚拟机网络设为隔离网段。具体操作Windows 安全中心 → 病毒和威胁防护 → 排除项 → 添加文件夹选中源码和输出目录。如果你确实需要研究免杀注意这是合规红线内的话题只建议用签名、加壳等常规思路理解原理不要针对具体杀软做对抗性测试更不要用于实际攻击。5.4 网络层控制端上线列表出现但反复闪断现象被控端好不容易上线几秒后又掉线控制端列表里主机状态一直“在线/离线”闪烁。原因最常见的是被控端到控制端的网络链路有超时比如虚拟机网络模式用了 NAT 但控制端防火墙策略对空闲连接做了 RST或者 IOCP 代码里默认心跳超时太短源码里SOCKET_TIMEOUT宏定义通常几十秒只要中间有一次心跳应答超时就直接断开。解决先看两端系统时间是否一致时间偏差大的会导致加密序列号校验失败如果原作者做了时间戳防重放然后在被控端抓包看是否有周期性 RST 包。我遇到过一次是 VMware 虚拟机网卡高级选项里的“CPU 虚拟化加速”没开导致网络栈延迟抖动关掉加速后掉线频率直线下降——这个属于玄学但确实发生过。5.5 数据回传乱码或文件传到一半断掉现象屏幕监控画面花屏、文件传输传到 50% 提示失败。原因大概率是协议头结构体对齐方式不一致导致的解析偏移。控制端在 VS2019 下的#pragma pack(1)生效但被控端如果用不同编译器或不同pack值编译两边读DataLength的偏移错位数据流就乱了。解决确认两端的CMD_HEADER结构体sizeof完全一致在两端各加一行printf(%d, sizeof(CMD_HEADER))跑一遍对比。另外文件传输断流也可能是中途被控端主动掉线属于 5.4 节的衍生问题。6. 进阶验证与行为侧写用自己编译的样本训练蓝队检测思路编译跑通只是第一步这份源码更大的价值在于——你用它做行为侧写可以摸清一类远控的共性特征以后在蓝队层面看到类似流量或行为能快速定位。具体做法分三层静态特征侧写、动态行为侧写、流量特征侧写。静态侧写最简单用DIEDetect It Easy或CFF Explorer看编译产物的 PE 头、导入表和节区表。Gh0st 的导入表非常典型它会引入SetWindowsHookExA键盘钩子、WSAAsyncSelect或WSARecv网络异步、RegSetValueExA注册表自启动、CreateProcessAsUserA远程进程创建等敏感 API一串组合下来基本可以直接判定恶意属性。你在做 malware 报告时把导入表截图放到报告里分析师的结论会非常有说服力。动态侧写用 Procmon 加 Wireshark。Procmon 监控被控端启动后的文件和注册表操作System32目录写入、Run 键创建、services.exe相关操作Wireshark 抓包看流量规律——Gh0st 上线后通常有一个固定间隔的心跳包Payload 长度和间隔时间都很规律这可以作为 Snort 规则的匹配特征。把这些行为录下来写成检测规则才是这份源码最正统、最安全的用法——你学的是防守方如何识别不是进攻方如何利用。我自己的习惯是把这份源码当成“会呼吸的恶意软件标本”每次做内网安全测试前都先在隔离环境里编译一份、跑一遍、抓一遍包把行为和流量特征记进知识库。从那以后我再看任何疑似远控的样本第一反应不是慌而是先看它的通信端口、心跳间隔、注册表自启位置这三板斧——大部分远控万变不离其宗。希望这份 Gh0st 源码也能帮你的安全研究之路少一点黑匣子、多一点确定性希望帮到你。本文还有配套的精品资源点击获取