
简介PcShare源码是一份可远程管理计算机的经典远控程序适合C开发者、安全爱好者及运维人员学习参考。该资源为PcShare2005历史版本基于VC6.0环境编译源码无需修改即可直接通过便于实际运行与二次分析。压缩包共403个文件大小仅1006KB包含121个h头文件、98个cpp源文件、60个ico图标、30个bmp位图以及dsw/dsp工程文件、rc资源脚本、cur光标等全面覆盖界面资源、核心逻辑与编译配置目录结构紧凑。已有948人下载学习。通过研读源码可系统理解远程控制软件的整体架构与实现机制包括屏幕监控、键盘记录、鼠标控制、注册表管理、文件传输等典型功能借助VC6.0直接编译特性还能快速搭建实验环境并开展代码级调试与安全分析。对于研究远控原理或学习经典C项目这是一份难得的实战素材。1. 项目概述一个时期的经典远控源码最近在整理资料的时候翻到了PcShare的源码包顺手在VC6.0环境下编译了一遍一次通过。作为Windows远控领域里流传最广的经典项目之一PcShare的价值一直没有被充分挖掘——很多人只把它当作一个“老古董”看待实际上它的代码结构、通信协议设计、界面布局思路即便是放在今天依然有很强的参考意义。PcShare是一款基于C/S架构的Windows远程控制软件服务端部署在被控机器上客户端负责发起连接和下发指令。源码使用VC6.0工程管理纯Win32 API编写的界面和核心逻辑不依赖MFC、不依赖第三方库开箱即编译。这一点放在那个年代难能可贵放在今天更是一种“教科书级”的轻量实现。这次分享适合三类人第一类是刚接触Win32网络编程的初学者可以从头到尾读一遍代码理解一个完整的远控系统是怎么串联起来的第二类是研究老代码的老开发想看看当年的技术选型和协议设计思路第三类是想做安全研究、想做免杀对抗、想做红队工具开发的安全从业者——PcShare的代码结构和通信模型非常适合作为二次开发的底子。有一点要提前说清楚远控技术本身是中性技能代码公开已有十几年学习它的目的是理解原理、提升编程能力而不是拿去做违规的事。本文的编译和分析全部在本地虚拟机环境进行讨论范围限定在源码结构和工程实现层面。2. 技术选型解析为什么VC6.0能成为经典搭配2.1 VC6.0在当年的地位与现状VC6.0是微软1998年发布的开发环境配套的编译器是MSVC 6.0C标准支持停留在C98之前的水准对模板、STL的支持都不完整。很多人不理解为什么一个号称“经典远控”的项目偏偏选这个老掉牙的IDE答案其实很直接PcShare的发布年代正是VC6.0的鼎盛期当时大量的安全工具、黑客软件、系统辅助工具都是用它写的。VC6.0编译出的程序体积小、无运行时依赖静态链接CRT的情况下、在Windows 98到Windows 7的系统上兼容性极好。对远控这种需要部署到大量不明环境中的软件来说兼容性就是生命线。另一个重要原因是当时的源码作者普遍不需要复杂的高级语言特性一个对话框程序挂几个线程用Socket API收发数据用定时器驱动UI刷新——这些VC6.0已经搓搓有余。所以选VC6.0并不是落后而是在当时条件下的最优解。2.2 用现在的眼光重新审视这个选择如果你今天重新编译这个项目依然完全可以选择VC6.0但我个人建议在保持源码不变的前提下采用“两条腿走路”的策略VC6.0保证原汁原味的编译通过同时用Visual Studio 2015及以上版本尝试兼容编译收获往往更大。因为VS2015之后的编译器对C标准支持更完整对代码的检查更严格原本在VC6.0下被忽略的语法警告在VS下会变成错误——比如for循环作用域内声明变量PcShare源码里大量使用这种写法在VC6.0下没问题在VS2015下就编译不过。这个坑后面在编译章节会详细说。我当时做对比编译的时候发现PcShare的代码质量其实相当不错全局变量管理集中、功能模块划分清晰、消息处理逻辑完整。要不是文件头注释写得少这代码拿去当教学范例都合格。2.3 远控软件的核心能力拆解远控软件的价值不在于“能连上”而在于“连上之后能干什么”。PcShare的功能列表如下远程Shell在客户端窗口内打开cmd.exe管道重定向输入输出实现命令行交互远程文件管理列出目录、上传、下载、删除、重命名支持断点续传远程屏幕查看定时截屏压缩传输客户端显示位图键盘记录钩子或轮询方式记录按键保存在服务端本地进程管理枚举进程、结束进程、查看进程路径注册表操作读写删注册表项服务管理启动、停止、删除系统服务系统信息收集操作系统版本、CPU、内存、磁盘等基础信息从代码结构上看这些功能分布在独立的处理模块中通过统一的通讯层收发指令和数据。这个设计在今天来看仍然是合理的通讯层保持简洁业务功能彼此解耦新功能只需新增一个命令号与对应处理函数。3. 环境准备与源码编译实录3.1 搭建VC6.0编译环境首先需要准备VC6.0中文版或英文版安装包推荐在虚拟机中安装Windows XP或Windows 2000系统进行编译兼容性最好。如果你非要在Windows 10上直接装VC6.0也不是不行但有几个地方要处理VC6.0的IDE在Win10下可能无法正常显示字体需要通过“兼容性”选项卡设置以Windows XP SP3模式运行VC6.0自带的SP5补丁必须安装否则编译器可能有内存分配问题源码存放路径不要有中文和空格建议直接放在C:\PcShare安装完成后打开PcShare.dsw工作区文件通常能看到两个工程Client控制端和Server被控端。注意PcShare源码包里有多个版本有的版本把两个工程放在同一个工作区有的分开。本次编译使用的版本是包含完整源码的最终版两个工程都在同一个dsw内。3.2 编译前的工程配置检查打开VC6.0后先别急着按F7编译有几个配置必须确认菜单Project - Settings - C/CCategory选Preprocessor确认Preprocessor definitions中包含WIN32和_WIN32_WINNT0x0501这个是保证程序能在XP以上系统运行的关键工程需链接ws2_32.lib如果你的源码包自带相关设置就不需要动如果编译报unresolved external symbol错误多半是少了这个库检查Link标签页确保Object/library modules中包含kernel32.lib、user32.lib、gdi32.lib、ws2_32.libPcShare源码包通常已经配置好了这一切直接在VC6.0里打开编译即可。我这次用的就是原版配置零改动编译通过。3.3 实际编译流程与输出验证编译步骤Build - Rebuild All。先编译Client工程再编译Server工程。如果是第一次编译整个过程大约需要一到两分钟主要耗时在资源文件的编译上。编译顺利的话输出窗口大致这样--------------------Configuration: Client - Win32 Release-------------------- Compiling... StdAfx.cpp Compiling... ... Linking... Client.exe - 0 error(s), 0 warning(s) --------------------Configuration: Server - Win32 Release-------------------- Compiling... ... Linking... Server.exe - 0 error(s), 0 warning(s)看到这个输出就说明源码完全通过了VC6.0的编译验证。输出目录一般在工程目录下的Release子文件夹生成了两个关键文件Client.exe控制端约200多KB和Server.exe服务端约100多KB。这里有一个容易被忽略的点Server.exe如果启用了加壳或压缩选项体积会变小但反而容易被杀毒软件报毒。PcShare原版不带壳直接编译出来的程序在测试机上运行是稳定的但现在的杀毒软件对新编译的老代码依旧会报风险因为行为特征太典型了。做测试时记得把样本目录加入白名单。3.4 完整复现一次远控连接流程编译完成后建议立即做一次完整的连接测试来验证程序可用性。我是在虚拟机里完成这一步的准备两台虚拟机一台Windows XP作为控制端运行Client.exe一台Windows XP作为被控端运行Server.exe网络模式设为NAT在被控端运行Server.exe程序默认监听端口等待连接在控制端打开Client.exe在IP输入框中填写被控端的IP地址点击连接连接成功后被控端的屏幕内容会出现在控制端的预览窗口中左侧功能面板从灰色变为可操作状态如果连接失败检查网络连通性——在控制端cmd里ping一下被控端的IP。PcShare默认端口在源码中写死可以搜索bind和listen附近的代码确认具体端口号不同版本端口不一样。整个验证流程建议放在虚拟机里做不用真实机器避免安全软件拦截和潜在的合规风险。测试完成后关闭虚拟机Server.exe不会开机自启源码版本没有做自启动除非你自己写。4. 源码核心模块与实现原理深度拆解4.1 整体代码架构地图打开源码工程后先从文件列表建立全局认知。PcShare源码的文件构成大致如下StdAfx.h/cpp预编译头文件包含Windows公共头文件MainDlg.cpp控制端的主对话框逻辑所有命令的入口Server.cpp/ServerDlg.cpp服务端主程序与主对话框SocketThread.cpp网络通讯线程处理收发数据FileManager.cpp文件管理功能的实现ScreenWatch.cpp屏幕监控功能实现CmdShell.cpp远程命令行实现KeyRecord.cpp键盘记录实现RegEdit.cpp注册表操作实现Common.cpp/h公共函数与数据结构定义Protocol.h自定义通信协议结构体定义从文件命名可以看出作者把每个功能独立放到一个cpp文件里代码风格直白利落几乎没有过度设计。这个结构的好处是新功能可以直接新增一个cpp文件在通信层注册命令号在界面层添加按钮剩下的事就是业务逻辑本身。4.2 通信协议设计一次指令的完整生命周期PcShare的通信协议属于自定义二进制协议没有使用HTTP或现有应用层协议。协议的精髓在于统一的“封包头数据体”结构。一次指令的完整流程是这样的用户在控制端点击“远程命令行”按钮主对话框构造一个消息结构体填充指令类型、会话ID、参数字段通过Socket发送到服务端。服务端的通讯线程收到数据后根据指令类型分发到对应的处理模块处理完成后把执行结果封装成同样的结构返回给控制端。控制端收到结果更新UI展示给操作者。这种“命令号参数结构体”的协议模型最大的优势是扩展性极强。新增功能时只需要在协议头文件中定义一个命令号以及对应的请求和响应结构体在主分发函数中增加一个case分支即可完成接入。后来很多商业远控和开源远控都延续了这种设计思路。4.3 远程Shell的实现管道重定向的核心思想远程Shell是远控最经典的功能PcShare的实现方式直观且高效服务端创建一个匿名管道将cmd.exe进程的标准输入输出句柄重定向到这个管道上客户端发送的在屏幕上敲的命令写入管道输入cmd.exe的执行结果从管道输出读取经过网络传回客户端显示。核心流程拆开看CreatePipe创建管道一个用于读输出一个用于写输入创建cmd.exe进程时通过STARTUPINFO结构体的hStdInput、hStdOutput、hStdError指向管道句柄服务端启动一个线程循环读取管道输出有数据就通过网络发送收到客户端发来的命令字符串通过WriteFile写入管道输入这个方案的好处是代码量极少却能获得一个完整功能的cmd窗口不需要自己实现命令解析和交互逻辑。这是一种典型的“不要重复造轮子”的思想把活儿外包给系统自带的shell自己只做管道的数据搬运工。注意事项管道缓冲区的处理是个细节如果一次性写入大量数据管道可能阻塞所以要用异步方式读取或起独立线程。PcShare源码里用了双线程读写分离这也是要仔细看的地方。4.4 屏幕监控实现数据压缩与实时刷新的平衡屏幕监控功能对实时性要求高PcShare采用定时截屏差异传输的策略。这里有一个容易被忽略的优化点PcShare并不是每次把整张屏幕的位图都传过去而是只传变化区域。实现原理服务端定时抓取屏幕图像和前一次图像做像素级对比把发生变化的矩形区域标记出来只对这些区域进行编码和传输。客户端收到后在本地维护的屏幕副本上更新对应区域再显示在窗口里。这样网络开销大幅下降即使带宽有限也能保证基本的流畅度。这套思路放在今天依然是远程桌面类软件的核心优化点只是现代工具把变化检测做得更精细脏矩形、HEVC编码等。PcShare作为早期实现已经把这个理念落地了。4.5 服务端自启动与隐藏的常规手法分析源码里对Server端的隐蔽运行做了处理这也是远控类程序区别于普通软件的标志性设计。服务端运行后无窗口、无托盘图标注册系统服务或写入注册表启动项实现开机自启。在源码中可以搜索注册表操作相关的函数能看到类似下面这样的关键操作RegOpenKeyEx(HKEY_LOCAL_MACHINE, SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run, ... RegSetValueEx(... ... 程序路径 ...)这是通过注册表Run键实现开机启动和当前一些红队工具的做法一致。PcShare还支持以服务方式注册让进程在System权限下运行。作为学习对象这些代码对于理解Windows的自启动机制非常有帮助但请务必控制在虚拟机和自有机器的范围内测试不要部署到任何不拥有授权的环境中。4.6 键盘记录模块的事件捕获与存储策略键盘记录的实现方式有两种全局钩子WH_KEYBOARD_LL和轮询GetAsyncKeyState。PcShare用的是轮询方式原因很实际全局钩子依赖DLL注入在98/2000时代容易触发兼容性问题轮询则简单粗暴不依赖系统钩子机制稳定性更好。轮询的实现逻辑启动一个后台线程循环检测256个虚拟键码的状态判断按键是否按下一旦按下就把对应字符写入日志日志可以保存在内存中等待客户端读取也可以直接写本地文件。PcShare默认将记录保存在服务端本地客户端连接后通过指令读取。这种方式有明显的局限——它只能记录按键不能记录输入到哪个窗口。但这在当年已经是实用的能力了。站在技术学习角度理解这种基础的按键捕获模型后续再去看钩子方案的实现就会顺畅很多。5. 编译运行中的疑难杂症与排查方法5.1 编译报错与解决办法速查VC6.0编译老源码时最常见的错误和我的排查经验整理如下错误现象原因分析解决办法fatal error C1010: unexpected end of file某个cpp文件缺少#include stdafx.h把预编译头设置改为“不使用预编译头”或补上includeerror LNK2001: unresolved external symbol WSAStartup没有链接Winsock库Project Settings - Link添加ws2_32.liberror C2065: HINTERNET : undeclared identifier缺少WinInet相关头文件在StdAfx.h中增加#include wininet.hwarning C4996: strcpy was declared deprecatedCRT函数安全检查VS2005才有VC6.0不受影响若在VS下编译可定义_CRT_SECURE_NO_WARNINGSerror C2146: syntax error : missing ; before identifier通常是因为某个头文件被循环包含检查头文件包含关系添加条件编译保护PcShare源码本身干净按原配置走基本不出问题但如果你在VS2015等新环境里强行编译上面的错误清单就非常有用了。5.2 运行时崩溃与功能异常的定位方法编译通过只是第一步运行起来遇到的问题往往更棘手。我在测试PcShare时遇到过两个典型的运行时问题第一个是连接成功但文件管理列表加载不出来排查后发现是服务端的工作目录不可写导致文件列表缓存写入失败。解决办法是确保以管理员权限运行Server.exe或把程序放到有写权限的目录。第二个是屏幕监控显示黑屏这是因为Windows XP系统在通过远程终端服务或安全桌面会话时截屏API抓不到活动会话的画面。解决办法是直接在本机登录被控端测试不要通过远程桌面去看或者用管理员账号登录。这类问题的排查思路很通用远控类程序行为受系统会话、权限、防火墙三重影响遇到现象先确认这三个前提条件再做代码层面的分析。5.3 杀毒软件白名单配置与安全边界PcShare编译出来的程序特征码和远控行为都太典型现在任何主流杀毒软件都会拦截。如果你在测试机上测试必须把编译输出目录加入杀软白名单否则程序一运行就被查杀根本没机会看到效果。这里要强调安全边界PcShare源码自带基础的隐藏行为和自启动逻辑这类代码如果被恶意利用会造成严重的安全事件。作为技术学习材料应该始终在虚拟机中测试并使用自己的电脑做授权验证。任何人都不应将此类源码部署到未授权的系统中这是从业者的基本底线。6. 从阅读源码到自主开发的经验总结6.1 这个项目最值得学习的编程范式把PcShare的源码完整读下来后我认为它最值得学习的不是具体功能的实现细节而是“独立程序员的工程组织能力”。一个人完成控制端、服务端、协议设计、界面开发、测试调试靠的不是复杂工具链而是清晰的模块划分和一致性的编码习惯。通信层、业务层、界面层虽然在一个程序里相互纠缠但作者用文件边界做了隔离——看SocketThread.cpp就专注网络收发看FileManager就专注文件操作不会出现把业务逻辑塞进网络线程的情况。这个习惯放在多人大项目中更重要。另外代码中对全局数据的集中管理也值得学习所有共享状态都放在一个公共结构体中线程间用简单方式同步虽然没有用到什么高级锁但可以保证在低并发场景下的正确性。这种务实的设计恰恰是很多初学者写网络程序时最容易忽略的。6.2 从经典远控源码延伸的技术学习路径如果你读完PcShare源码想要继续深入我建议按以下路径进阶第一站重写通信层。把基于Socket的同步收发改成IOCP或完成端口模型理解高并发网络的底层机制。第二站重写界面。把Win32传统界面迁移到自绘控件研究双缓冲绘图、动态布局和主题换肤。第三站重写协议。引入加密层AES或TLS解决明文传输带来的安全问题。第四站研究现代远控框架看看新工具如何解决NAT穿透、会话管理、多路复用、插件系统等PcShare没有深度涉及的问题。这个思路不仅适用于远控方向任何网络C/S架构项目的演进逻辑都是类似的基础协议清晰了上层功能可以无限叠加。6.3 最后的几句实在话最近几年我越来越少见到有人愿意静下心来读老源码了。PcShare这种项目论代码优雅不如现代C工程论功能完善不如商业软件但它代表了一个时代里个人开发者能力上限的缩影一个人一台电脑几万行C代码做出了完整的商业级远控系统。对刚入门的开发者来说与其在框架的海洋里挑花眼不如找一个这样体量适中、结构清晰的源码读透。读懂一个完整项目的运行逻辑胜过浮光掠影看二十个教程。编译通过只是起点真正把代码内化成自己的能力才是这趟折腾最大的收获。本文还有配套的精品资源点击获取