最近学习SOCKET编程 , 在主机和虚拟机间实验了简单的远控(强制关机、取消关机、截图)。
整体思路 : 很简单,就是建立C/S两端 , 通过TCP连接传输指令和图片信息 , 模拟远程控制的效果 , 此处未涉及过防火墙等知识 , 只是简单的模拟TCP 原理 , 大牛请无视~
更改IP\子网掩码\网关在同一网段
控制机 (虚拟机):192.168.43.249
靶机(主机) :192.168.43.153
弹出WIN10的关机窗口(截图不完整,但显然不是WIN7界面)
控制方代码:
// 远控(控制方).cpp : 定义控制台应用程序的入口点。
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")
//接收图片
void recvfile(SOCKET sock)
{
//标识截图名称
static int id = 0;
//文件名
char filename[50];
int err = 0;
//构建一个文件名,区分文件
sprintf(filename, "prt_%d.png", id++);
//创建文件
ofstream ofile(filename, ios_base::binary);
while (true)
{
char filebuff[1024] = { 0 };
//接收一次文件
err = recv(sock, filebuff, 1024, 0);
//如果接收==0
if (err == 0)
{
printf("recv error\n");
return;
}
//如果小于1024,说明文件传输结束
else if (err < 1024)
{
ofile.write(filebuff, err);
ofile.close();
break;
}
//如果刚好1024,直接写入文件.
else
{
ofile.write(filebuff, 1024);
}
}
}
int main()
{
//1.初始化环境
WSADATA wds = { 0 };
int err;
//参数1.请求的版本号2.2 参数2.WSADATA结构体
err = WSAStartup(MAKEWORD(2, 2), &wds);
if (err != 0)
{
printf("WSAStartup error\n");
return 1;
}
//检测是否2.2版本
if ((HIBYTE(wds.wVersion) != 2)
|| (LOBYTE(wds.wVersion) != 2))
{
printf("WSAStartup error\n");
return 1;
}
//2.创建套接字 参数1.IP协议,参数2.流式类型,参数3.TCP协议
SOCKET Csock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Csock == INVALID_SOCKET)
{
printf("socket error\n ");
return 1;
}
//3.发起链接
sockaddr_in Saddr = { 0 };
Saddr.sin_addr.S_un.S_addr = inet_addr("192.168.43.153"); //链接的IP地址
Saddr.sin_family = AF_INET; //使用IP协议
Saddr.sin_port = htons(1234); //端口
//发起链接 参数1.客户套接字,参数2.服务端地址,参数3.结构体大小
err = connect(Csock, (sockaddr*)&Saddr, sizeof(Saddr));
if (err == SOCKET_ERROR)
{
printf("connect error\n");
return 1;
}
while (true)
{
char buff[1024] = {0};
gets(buff);
printf("shutdown 关机\n");
printf("noshutdown 取消关机\n");
printf("prtscreen 截图\n");
//如果输入quit退出程序
if (strcmp(buff,"quit")==0)
{
break;
}//如果截图消息
else if (strcmp(buff,"prtscreen")==0)
{
//发送截图消息
err = send(Csock, buff, 1024, 0);
if (err==SOCKET_ERROR)
{
printf("send error\n");
break;
}
Sleep(100);
//获取文件数据
recvfile(Csock);
}
//其他命令直接发送
else {
send(Csock, buff, 1024, 0);
}
}
//5.关闭socket
closesocket(Csock);
//6.清理环境
WSACleanup();
return 0;
}
受控方代码 :
// 远程控制(受控方).cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")
//截屏保存
bool prtsc()
{
//模拟键盘点击
keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
Sleep(300);
keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
Sleep(1000);
//打开剪切板
OpenClipboard(NULL);
//获取剪切板数据
HBITMAP hbitmap=(HBITMAP)GetClipboardData(CF_BITMAP);
if (hbitmap != NULL)
{
CImage img;
img.Attach(hbitmap); //附加图片
img.Save(L"1.png"); //保存图片
img.Detach(); //卸下图片
CloseClipboard(); //关闭剪切板
return true;
}
CloseClipboard();
return false;
}
//读取png文件
char *readFile(int &len)
{
ifstream infile("1.png", ios_base::binary);
//获取文件大小
infile.seekg(0, ios_base::end);
len = infile.tellg();
infile.seekg(0, ios_base::beg);
//开辟缓冲区
char *filebuff = new char[len];
//读取文件
infile.read(filebuff, len);
infile.close();
//返回文件内容
return filebuff;
}
//执行命令
void recvcmd(SOCKET sock, char *szcmd)
{
if (strcmp(szcmd,"shutdown")==0)
{
//执行cmd命令关机
system("shutdown -s -t 300");
return;
}
//取消关机
else if(strcmp(szcmd,"noshutdown")==0)
{
system("shutdown -a");
return ;
}
//屏幕监控
else if (strcmp(szcmd,"prtscreen")==0)
{
//截图
if (prtsc())
{
char *pfile;
int len;
//读取文件
pfile=readFile(len);
send(sock, pfile, len, 0);
delete[] pfile;
}
}
}
int main()
{
//1.初始化环境
WSADATA wds = { 0 };
int err;
//参数1.请求的版本号2.2 参数2.WSADATA结构体
err = WSAStartup(MAKEWORD(2, 2), &wds);
if (err != 0)
{
printf("WSAStartup error\n");
return 1;
}
//检测是否2.2版本
if (
(HIBYTE(wds.wVersion) != 2)
|| (LOBYTE(wds.wVersion) != 2)
)
{
printf("WSAStartup error\n");
return 1;
}
//2.创建套接字 参数1.IP协议,参数2.流式类型,参数3.TCP协议
SOCKET Ssock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Ssock == INVALID_SOCKET)
{
printf("socket error\n ");
return 1;
}
//3.绑定socket
sockaddr_in Saddr = { 0 };
Saddr.sin_addr.S_un.S_addr = inet_addr("192.168.43.153"); //链接的IP地址
Saddr.sin_family = AF_INET; //使用IP协议
Saddr.sin_port = htons(1234); //端口
//参数1.服务端的套接字,参数2.服务端的地址信息,参数3.结构体大小
err = bind(Ssock, (sockaddr*)&Saddr, sizeof(Saddr));
if (err == SOCKET_ERROR)
{
printf("bind error\n");
return 1;
}
//4.监听socket
err = listen(Ssock, SOMAXCONN);
if (err == SOCKET_ERROR)
{
printf("listen error\n");
return 1;
}
//5.等待客户端链接
sockaddr_in Caddr = { 0 };
int Csize = sizeof(Caddr);
//返回 客户套接字, 参数1.服务端的套接字,参数2客户端的地址,参数3结构体的大小
SOCKET ClientSock = accept(Ssock, (sockaddr*)&Caddr, &Csize);
while (true)
{
//接收数据
char buff[1024] = {0};
err = recv(ClientSock, buff, 1024, 0);
if (err==0)
{
break;
}
//执行quit退出循环
if (strcmp(buff,"quit")==0)
{
break;
}
printf(buff);
//执行控制方发送的命令
recvcmd(ClientSock, buff);
}
//5.关闭socket
closesocket(Ssock);
//6.清理环境
WSACleanup();
return 0;
}