编写程序实现Windows系统的远程监控。
参考的程序
- gh0st 自己在网上或者github上面查找。
- https://github.com/zibility/Remote
- https://github.com/sin5678/gh0st
- https://yichinzhu.github.io/2017/09/09/build-gh0st/
要求
- 必须实现客户端和服务器端的连接。
- 实现对远程主机的控制。能够查看桌面,操作文件。
- 实现代码,并写出实现技术文档。
实验报告
环境配置与项目导入
首先说明一下这是个用Qt创建的项目,客户端有简单的图形界面,服务端(被控制)则是隐藏了窗口的命令行接口。在需要被控制的电脑上运行服务端,随后在客户端输入该电脑的ip地址,以及其屏幕分辨率,稍等片刻即可连上对方主机。连接后可以按照类似于远程桌面连接后的形式操作对方的电脑,可执行的操作包括但不限于访问桌面文件,执行cmd命令,键盘输入等等
我们已经将编译好的项目连同所必须的链接库放在了bin目录下,直接执行即可。另外项目的导入较为繁琐,故在此特别说明一下:
- 下载必要的组件(Qt引擎、IDE和MinGW编译器)
qt-win-opensource-4.7.4-mingw.exe
qt-creator-opensource-windows-x86_64-4.7.2.exe
MinGW-gcc440_1.zip - 分别安装三个组件,注意,请先安装编译器,安装QtCreator时会要求登录,注册一个账号并登录即可。
- 打开 QtCreator->工具->选项->Kits,以配置环境。
点击Qt Versions
,并将Qt 4.7.4的安装目录下的bin\qmake.exe
选中,点击编译器
,设置新的C编译器的路径为MinGW安装目录下的bin\gcc.exe
,并设置新的C++编译器的路径为MinGW安装目录下的bin\g++.exe
。
配置好后,点击Kit并新建一个配置项,使用先前设置的Qt环境和编译器。
- 找到我们的项目,双击其中的
.pro
文件即可完成导入 - 展开到
main.cpp
,单击构建-运行
,(客户端)界面就能显示出来了
操作演示
软件的使用相当简单,首先,设法在你要控制的电脑上运行cserver.exe
,宿主系统不会给出任何提示,记住这台电脑的ip地址。
接下来,在你的电脑上运行client.exe
,输入被控制电脑的ip,以及其显示器的分辨率(如果输入小于实际分辨率则图像会被压缩),点击connect即可链接对方电脑,待图像显示后方可控制,按照类似于远程桌面连接后的形式操作对方的电脑。
运行截图(自己控制自己的电脑,正在查看桌面和操作浏览器):
代码说明
下面我们对程序源代码的主要内容进行讲解说明,其余的内容以注释形式标出,依赖关系也请参考源码。
cserver目录
main.cpp
int main(int argc, char *argv[])
{
//声明一个Qt应用 a
QApplication a(argc, argv);
//桌面元素
QDesktopWidget* deskWidget = a.desktop();
//获取宿主屏幕信息
QRect screenRect = deskWidget->screenGeometry();
screen_width = screenRect.width();
screen_height = screenRect.height();
//创建控制器
new Controler;
//执行应用
return a.exec();
}
interface.cpp
Interface::Interface(){
}
//将鼠标指针的坐标映射到一个65535*65535的正方形“屏幕”上
QPoint Interface::transformCoordinate(QPoint p)
{
int x = (int)((double)p.x() / screen_width * 65535);
int y = (int)((double)p.y() / screen_height * 65535);
return QPoint(x, y);
}
// 处理鼠标移动事件
void Interface::mouseMoveTo(int x, int y)
{
//坐标映射
QPoint p = transformCoordinate(QPoint(x, y));
//发起鼠标事件(采用绝对坐标|移动鼠标,移动至p.x,p.y, 最后两个参数未被使用)
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE, p.x(), p.y(), 0, 0);
}
//处理鼠标左键按下的事件
void Interface::mouseLeftDown(int x, int y)
{
QPoint p;
//此时坐标值不合理
if(x < 0 || y < 0)
{
//重新取得指针所在位置
p = getCursorPos();
}
else
{
//坐标映射
p = transformCoordinate(QPoint(x, y));
}
//移动鼠标并按下左键
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN, p.x(), p.y(), 0, 0);
}
//处理键盘按下的事件
void Interface::keyPressed(uchar key)
{
keybd_event(key, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
}
controller_.cpp
//初始化控制器
Controller_::Controller_(QObject *parent) :QObject(parent)
{
vec = new QVector<SocketAndThread>;
//建立图像传输的TCP连接
pMapServer = new QTcpServer;
//监听图像传输端口
pMapServer->listen(QHostAddress::Any, MAP_SERVER_PORT);
connect(pMapServer, SIGNAL(newConnection()), this, SLOT(newMapClient()));
//建立命令传输的TCP连接
pCmdServer = new QTcpServer;
//监听命令传输端口
pCmdServer->listen(QHostAddress::Any, CMD_SERVER_PORT);
connect(pCmdServer, SIGNAL(newConnection()), this, SLOT(newCmdClient()));
}
//每当有一个新连接时,启动一个线程单独为之服务
void Controller_::newMapClient()
{
//取出下一个正等待建立的连接
QTcpSocket* clientMapSocket = pMapServer->nextPendingConnection();
//qDebug()<<"new map connection:"<<clientMapSocket->peerAddress().toString()<<endl;
//创建图像传输线程
MapThread* mapThread = new MapThread(clientMapSocket);
connect(clientMapSocket, SIGNAL(disconnected()), this, SLOT(someSocketDisconnected()));
//记录当前的套接字和线程信息
SocketAndThread st = {
clientMapSocket, mapThread};
//将当前线程加入<套接字和线程>向量中
vec->append(st);
//启动线程
mapThread->start();
}
void Controller_::newCmdClient()
{
//取出下一个正等待建立的连接
QTcpSocket* clientCmdSocket = pCmdServer->nextPendingConnection();
//qDebug()<<"new cmd connection:"<<clientCmdSocket->peerAddress().toString()<<endl;
//创建命令传输线程
CmdThread* cmdThread = new CmdThread(clientCmdSocket);
connect(clientCmdSocket, SIGNAL(disconnected()), this, SLOT(someSocketDisconnected()));
//记录当前的套接字和线程信息
SocketAndThread st = {
clientCmdSocket, cmdThread};
//将当前线程加入<套接字和线程>向量中
vec->append(st);
//启动线程
mapThread->start()