ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

单文件远控源码从编译到稳定运行:连接、心跳与重连实战

单文件远控源码从编译到稳定运行:连接、心跳与重连实战 简介这是一份面向安全研究与远控技术学习者的gh0st被控端单exe修改版源码针对传统RAT多以dll版或服务启动版分发、易被主动防御拦截的问题作者将服务端整合为单一exe形态并融入动态函数调用等常用免杀思路对主动防御的绕过相对容易适合具备一定C与Windows编程基础、希望研究远控通信与免杀技术的读者参考。资源包共54个文件以28个h头文件与21个cpp源文件为主体另含lib静态库、dsp与dsw工程文件、plg插件及说明txt覆盖音频、视频、键盘、屏幕、文件、注册表、Shell、内核等管理模块压缩包约114KB编译前可能需自行安装SDK。目前已有1250人学习下载。源码结构完整读者可借此梳理gh0st被控端的模块划分与函数调用关系理解单exe化改造与免杀技术的落地方式并作为二次开发或防御研究的对照样本。1. 单文件远控源码到底能跑通什么从一台机器到另一台机器的完整链路很多人第一次接触远程控制类源码脑子里想的是“一个 exe 丢过去就能控制对方”。实际拆过几份单 exe 版远控源码之后你会发现真正决定它能不能跑通的不是界面多花哨而是三件事连接怎么建立、指令怎么下发、文件怎么落地。单 exe 版的价值在于把服务端和客户端压进同一个可执行文件省掉了配置环境、装依赖、分开发包的麻烦适合做内网资产梳理、批量运维演示、以及自己搭一套可控的远程管理实验环境。它不适合拿来做任何未经授权的操作这一点必须先说清楚。这篇文章会按“源码结构 → 编译打包 → 连接配置 → 功能验证 → 踩坑排查”的顺序把一份单 exe 远控源码从拿到手到跑起来的过程拆开讲新手能照着走熟手能直接看参数和边界。2. 源码结构与通信模型先看懂再动手改2.1 单 exe 是怎么把服务端和客户端塞进一个文件的单 exe 版远控源码最常见的做法是“一份代码、两种启动模式”。程序启动时先读命令行参数或配置文件判断当前是以监听模式运行还是以被控模式运行。监听模式绑定端口、等待连接被控模式主动连回指定地址。两者共用同一套网络收发、指令解析、文件传输模块只是入口分支不同。拆开看典型目录结构大致是这样模块作用常见文件入口调度判断运行模式、初始化main.cpp / Program.cs网络层Socket 建立、心跳、重连net.cpp / SocketHelper.cs指令解析把收到的字节流转成具体操作cmd.cpp / CommandParser.cs功能模块屏幕、文件、进程、注册表screen.cpp / FileMgr.cs配置读写保存回连地址、端口、标识config.cpp / Config.cs单 exe 的关键在于配置不能写死在代码里否则换一台机器就得重新编译。常见做法是把配置加密后追加到 exe 末尾或者写进同目录的隐藏配置文件。前者更“单文件”后者更好改。我一般会先确认它用的是哪种因为这直接决定后面怎么改回连地址。2.2 通信协议与心跳机制为什么连上了却很快掉线远控源码的通信层通常有两种裸 TCP 自定义协议或者 HTTP 长轮询。单 exe 版为了体积和依赖多数走裸 TCP。裸 TCP 的问题是没有天然的心跳网络一抖动连接就断所以源码里一般会有一个定时发送心跳包的逻辑。心跳包通常是一个固定字节序列比如0x01开头加时间戳。服务端收到后回一个确认双方各自维护一个“最后活跃时间”。超过阈值没收到心跳就判定断线并触发重连。重连间隔一般设 3 到 5 秒太短会刷日志太长会显得“卡死”。// 心跳发送逻辑示意 void sendHeartbeat(SOCKET sock) { char buf[9]; buf[0] 0x01; // 心跳标识 *(uint32_t*)(buf 1) time(NULL); // 当前时间戳 send(sock, buf, 9, 0); // 发送心跳 } // 接收端判断若 10 秒内无心跳关闭连接并重连这段逻辑里0x01是协议约定的心跳类型时间戳用来判断延迟。参数上要注意的是超时阈值常见设 10 到 30 秒。如果你在内网测试设 10 秒足够跨网段或网络质量差设 30 秒更稳。改这个值的位置一般在网络层的常量定义里搜HEARTBEAT或TIMEOUT就能找到。2.3 配置项怎么改回连地址、端口、标识三件套拿到源码后第一件事不是编译而是找配置。单 exe 版通常把回连地址、端口、客户端标识放在一个结构体里编译前改好或者运行时通过命令行传入。# 常见启动方式监听端 rat.exe --mode server --port 8443 # 被控端指定回连地址和端口 rat.exe --mode client --host 192.168.1.10 --port 8443 --id test01参数说明--mode决定运行模式--port是监听或回连端口--host只在被控模式用--id是这台机器的标识方便在服务端区分。如果源码不支持命令行就得改配置文件或源码里的常量。我一般会先搜192.168或127.0.0.1把默认地址替换掉再搜PORT确认端口。注意改完配置后先在本机双开测试一个监听一个回连确认能连上再上其他机器。直接上真机很容易因为防火墙或端口占用卡住。3. 编译与打包把源码变成能跑的单 exe3.1 编译环境准备与依赖确认单 exe 远控源码常见的技术栈是 CWin32 API Winsock或 C#.NET。C 版一般用 Visual Studio 或 MinGW 编译C# 版用 dotnet 或 Visual Studio。先看源码根目录有没有.sln、.vcxproj或.csproj有就是对应 IDE 工程。# C MinGW 编译示例 g -o rat.exe main.cpp net.cpp cmd.cpp screen.cpp file.cpp \ -lws2_32 -luser32 -lgdi32 -static # C# 发布单文件 dotnet publish -c Release -r win-x64 --self-contained true \ -p:PublishSingleFiletrue -o ./publishC 编译时-lws2_32是 Winsock 库-luser32和-lgdi32是界面和屏幕相关。-static把运行时库静态链接进去避免目标机器缺 DLL。C# 的PublishSingleFile把依赖打进一个 exe--self-contained表示不依赖目标机器装 .NET。参数上-r win-x64指定目标平台32 位机器改成win-x86。3.2 静态链接与体积控制为什么你的 exe 一跑就缺 DLL单 exe 的“单”不只是文件数量还包括不依赖外部运行库。C 如果动态链接了 MSVCRT目标机器没装对应版本就会报缺 DLL。解决办法是编译时加-static或/MT。C# 的 self-contained 发布也会把运行时打进去代价是体积从几百 KB 涨到几十 MB。体积控制上常见做法是编译后加壳或压缩。但加壳容易触发杀软误报这一点后面避坑章节会细说。我一般先保证功能跑通再考虑体积。如果只是内网用几十 MB 完全可接受。3.3 打包后的自检清单编译出 exe 后别急着分发先做四件事本机双开连一次、换一台同网段机器连一次、断网重连一次、传一个文件试一次。这四步能覆盖大部分连接和功能问题。# 自检流程 1. 本机启动监听rat.exe --mode server --port 8443 2. 本机启动被控rat.exe --mode client --host 127.0.0.1 --port 8443 3. 观察服务端是否出现 test 标识 4. 断开被控端网络10 秒后恢复看是否自动重连 5. 从服务端下发文件传输确认接收端落地这五步里第 4 步最容易翻车。很多源码的重连逻辑只在启动时连一次断了就不管了。如果发现不重连去网络层找reconnect或while循环确认重连是不是放在了一个不会退出的循环里。4. 功能验证与参数调优屏幕、文件、进程三块怎么测4.1 屏幕传输帧率、压缩与带宽的平衡屏幕功能是远控里最吃带宽的。单 exe 版通常用 GDI 截屏加 JPEG 压缩帧率设 5 到 15 帧。帧率太高带宽扛不住太低操作延迟明显。// 截屏并压缩示意 HDC hdc GetDC(NULL); int w GetSystemMetrics(SM_CXSCREEN); int h GetSystemMetrics(SM_CYSCREEN); // 截屏到内存位图再编码为 JPEG质量参数 50-70 // 质量越低体积越小但文字会糊参数上JPEG 质量设 50 到 70 比较平衡。分辨率高时可以先缩放再编码比如缩到 1280 宽。如果源码里帧率是写死的搜Sleep或interval把值调到 100 到 200 毫秒之间。4.2 文件传输分块大小与断点续传文件传输常见问题是大文件传到一半断了。好的源码会做分块和校验每块 4KB 到 64KB传完一块回一个确认。// 分块发送示意 const int CHUNK 8192; char buf[CHUNK]; while (file.read(buf, CHUNK)) { send(sock, buf, file.gcount(), 0); // 发送一块 recv(sock, ack, 1, 0); // 等确认 }CHUNK设 8192 是常见值太小握手次数多太大单块失败重传成本高。如果源码没做确认传大文件容易丢块。测试时先用 10MB 左右的压缩包传完对比 MD5。4.3 进程与系统信息权限边界在哪进程列表、系统信息这类功能依赖 API 权限。普通用户权限能看进程列表但结束进程、改注册表需要管理员。测试时先确认被控端是不是以管理员运行否则部分功能会静默失败。功能所需权限失败表现进程列表普通用户正常结束进程管理员无反应或报错文件读写视目录拒绝访问注册表修改管理员静默失败这张表建议在测试时对照勾一遍能省很多“为什么点了没反应”的排查时间。5. 避坑与常见问题杀软、防火墙、重连那些事5.1 编译出来就被杀软删了现象刚编译完的 exe复制到目标机器就被删或隔离。 原因远控类源码的行为特征截屏、键盘钩子、网络回连和恶意软件高度重合杀软按行为查杀。 解决内网测试时把测试目录加白名单不要加壳加壳反而提高误报如果只是学习用虚拟机隔离环境跑。5.2 连不上但端口是通的现象telnet 端口能通但程序就是连不上。 原因协议不匹配或者被控端发的是自定义握手包服务端没识别。 解决抓包看双方第一个包的内容确认握手格式一致检查服务端是不是只接受特定标识的连接。5.3 断线后不重连现象网络恢复后被控端不再连回来。 原因重连逻辑写在初始化里只执行一次或者重连循环被异常退出。 解决把重连放到独立线程或不会退出的循环里加异常捕获确保任何错误都不跳出循环。5.4 屏幕画面卡死或花屏现象画面不动或者颜色错乱。 原因截屏和编码不在同一线程缓冲区被覆盖或者 JPEG 质量设太低。 解决截屏、编码、发送串行化质量调到 60 以上分辨率高时先缩放。5.5 文件传输后大小对不上现象传完的文件比原文件小或大。 原因没做分块确认或者文本模式传输把换行符转换了。 解决用二进制模式打开文件加分块确认传完对比 MD5。注意以上问题里杀软和权限是最常见的两个。测试前先把白名单和权限搞定能省一半时间。6. 进阶技巧把单 exe 改成可配置、可验证的稳定版本单 exe 源码最大的问题是“改一次配置编译一次”。我的习惯是把它改成启动时读同目录的加密配置文件配置不存在就用内置默认值。这样换环境不用重编译也方便批量部署。// 读取同目录配置不存在则用默认 std::string cfgPath exeDir() \\rat.cfg; if (fileExists(cfgPath)) { loadConfig(cfgPath); // 解析 host/port/id } else { useDefaultConfig(); // 内置默认值 }exeDir()取当前 exe 所在目录loadConfig解析配置。配置可以简单异或加密防止明文被一眼看穿。参数上默认值建议设成127.0.0.1:8443避免误连外部地址。验证稳定性我一般跑一个 24 小时循环被控端每 30 秒发一次心跳服务端记录断线次数。断线超过 3 次就说明重连或心跳有问题。这个测试能暴露大部分玄学掉线。还有一个技巧是给 exe 加一个--selftest参数启动后自己连自己一次输出连接、传输、断开的耗时。这样每次编译完先跑自检不用手动双开。从那以后我每次改完网络层都强制走一遍自检和 24 小时循环确认没问题再上真机。希望帮到你。本文还有配套的精品资源点击获取
返回列表