*本文原创作者:Mr极目楚天舒,本文属FreeBuf原创奖励计划,未经许可禁止转载
前一篇文章介绍了软件的整体架构,接下来对被控端进行详细讲解,主要介绍被控端各个功能模块的关键技术以及开发过程中遇到的坑,希望对各位读者有借鉴作用。
被控端工作流程
应用程序初始化阶段初始化工作界面、从地址文件读取反向连接的ip地址和端口作为MyClientThread线程的启动参数。MyClientThread启动后执行GetClientSystemInfo函数获取本机信息并传至控制端显示。而后进入while(1)循环等待接收控制端传来的控制命令。进入switch_case结构解析命令,执行相应函数。将执行结果发送到控制端,继续进入循环等待。
获取计算机信息
GetClientSystemInfo传入一个SYSTEMINIT结构的引用,对该结构的定义在common.h文件中,该结构定义如下:
调用GetComputerName、GetUserName、GetVersionEx、GlobalMemoryStatus来分别获取计算机名、当前用户名、操作系统版本、内存信息。CPU的信息通过查询注册表来获取,通过打开不同的注释(3个中只能打开一个)获取CPU的不同信息,这里我们选择获取CPU的频率信息。
这里专门定义了一个CGetHDSerial类来封装序列号读取相关的操作。CGetHDSerial的成员函数如下:
函数调用关系为:
获取服务
参数为存放SERVICEINFO指针类型的容器。SERVICE数据结构定义为:
这里用到OpenSCManager函数,该函数建立了一个到服务控制管理器的连接,并打开指定的数据库。第一个参数为计算机名,若为NULL则指向本地计算机。第二个参数指定将要打开的服务控制管理数据库的名称,这里为NULL,表示指向本地默认。第三个参数为服务访问控制管理器的权限。执行成功返回一个服务控制管理器数据库的句柄ScManager。
由返回的句柄调用EnumServicesStatus函数枚举当前系统服务
获取进程列表
GetProcessList参数为PROCESSINFO指针类型的容器。PROCESSINFO数据结构在common.h中定义。
首先调用CreateToolhelpSnapshot获得当前系统中所有进程的快照,返回快照句柄。第二步调用Process32First获得第一个进程快照信息info,得到进程PID和进程名称。为了得到当前进程加载模块的完整路径,需要调用OpenProcess来打开对应进程对象。然而通过几次打开失败后发现,原来在默认的情况下进程的一些访问权限是没有被启用的,即使你是Administrator,所以很重要的一步就是提升当前进程的权限(启用这些权限),所以先调用OpenProcessToken打开相关进程的访问令牌(参数自己百度),而后调用EnablePrivilege提升当前进程权限,这样就可以打开进程对象了。第三步,通过while循环获得其他进程的信息。
CGetScreenToBitmap类用来获取当前屏幕画面转化成位图信息。
领取专属 10元无门槛券
私享最新 技术干货