#C++我的武器库系列#之远控核心技术实现

一、概要介绍      

        近期较忙,未能及时更新博客,Python告一段落后,开始基于C++的武器库核心技术实现,本期基于C++MFC,利用socket,通过非阻塞的方式实现client与server端的通信,通过client向server发起指令获取相关信息。

     服务器端函数逻辑: socket()->bind()->accept()->send()/recv()->closesocket();

     客户端函数逻辑:socket()->connet()->send()/recv()->closesocket();

二、系统核心代码-服务端


// UMDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "UM.h"
#include "UMDlg.h"
#include "afxdialogex.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();


// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
	
END_MESSAGE_MAP()


// CUMDlg 对话框




CUMDlg::CUMDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CUMDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CUMDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CUMDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_MESSAGE(UM_SERVER, OnSock)
	ON_WM_CLOSE()
END_MESSAGE_MAP()


// CUMDlg 消息处理程序

BOOL CUMDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	//----------------------------初始化-------------------------
	//WSDATA wsaData;
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);//初始化
	listenSocket =  socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //创建套接字;SOCK_STREAM:流套接字 SOCK_DGRAM:数据包套接字;SOCK_RAM:原始协议套接字;TCP形式
	WSAAsyncSelect(listenSocket,GetSafeHwnd(),UM_SERVER,FD_ACCEPT); //非阻塞模式 1:接收消息窗口;2:消息;3:通知码;
	//对socket_in结构体进行填充。包括地址、端口等信息
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr =ADDR_ANY; //inet_addr("192.168.1.102");  //将点分10进制IP,转换成无符号long类型  也可以设置ADDR_ANY; 逆函数 inet_ntor
	addr.sin_port = htons(5555);//主机字节转换成网络字节,在端口方面,x86为小尾方式  TCP/IP为大尾方式,所以需要转换。大尾与小尾区别为字节存储顺序相反
	bind(listenSocket,(SOCKADDR *)&addr,sizeof(addr)); //绑定IP地址和端口,并处于监听状态
	listen(listenSocket,1);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
//处理通知码
LRESULT CUMDlg::OnSock(WPARAM wParam, LPARAM lParam)
{
	if(WSAGETSELECTERROR(lParam)){
	  return 1;
	}
	switch(WSAGETSELECTEVENT(lParam)){
		
	case FD_ACCEPT:
		{
			sockaddr_in clientAddr;
			int nSize = sizeof(clientAddr);
			clientSocket = accept(listenSocket,(SOCKADDR *)&clientAddr,&nSize); //建立
			WSAAsyncSelect(clientSocket,GetSafeHwnd(),UM_SERVER,FD_READ|FD_CLOSE); //非阻塞模式 1:接收消息窗口;2:消息;3:通知码;
			strMsg.Format("请求的地址是%s:%d",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
			DATA_MSG dataMsg;
			dataMsg.bType = TEXTMSG;
			dataMsg.bClass = 0;
			lstrcpy(dataMsg.szValue,HELPMSG);
			send(clientSocket,(const char *)&dataMsg,sizeof(dataMsg),0); //发送
			break;
		}
	case FD_READ:
		{
			char szBuf[MAXBYTE] = {0};
			recv(clientSocket,szBuf,MAXBYTE,0); //接收
			DispatchMsg(szBuf);
			strMsg = "对方发来指令";
			strMsg += szBuf;
			break;
		}
	case FD_CLOSE:
		{
			closesocket(clientSocket);
			strMsg = "对方关闭连接";
			break;
		}
	}
	InsertMsg();
	return 1;
}

//匹配对应的操作命令
void CUMDlg::DispatchMsg(char* szBuf)
{
	DATA_MSG  dataMsg;
	ZeroMemory((void *)&dataMsg,sizeof(dataMsg)); 
	if(!strcmp(szBuf,"help")){ 
		dataMsg.bType = TEXTMSG;
		dataMsg.bClass = 0;
		lstrcpy(dataMsg.szValue,HELPMSG);
	}
	else if(!strcmp(szBuf,"getsysinfo")){
	    SYS_INFO SysInfo;
        GetSysInfo(&SysInfo);
        dataMsg.bType = BINARYMSG;
        dataMsg.bClass = SYSINFO;
		SysInfo.szComputerName;
		CString cName= SysInfo.szComputerName;
		CString uName= SysInfo.szUserName;
		  
		lstrcpy(dataMsg.szValue,"主机名:"+cName+"  用户:"+uName);
		//memcpy((void *)dataMsg.szValue, &SysInfo.szUserName, sizeof(dataMsg));
		//memcpy((void *)dataMsg.szValue,(char *) &SysInfo,sizeof(dataMsg));

	}
	send(clientSocket,(const char *)&dataMsg,sizeof(dataMsg),0); //发送
}

//获取系统信息
void  CUMDlg::GetSysInfo(PSYS_INFO SysInfo)
{
	unsigned long nSize = 0;
    SysInfo->OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&SysInfo->OsVer);
    nSize = NAME_LEN;
    GetComputerName(SysInfo->szComputerName, &nSize);
    nSize = NAME_LEN;
    GetUserName(SysInfo->szUserName, &nSize);
	//MessageBox(SysInfo->szUserName);
}


//输出信息
void CUMDlg::InsertMsg()
{
    CString strMsgNew;
    GetDlgItemText(IDC_EDIT1, strMsgNew);//获取内容
    strMsg += "\r\n";
    strMsg += "----------------------------------------\r\n";
    strMsg += strMsgNew;
    SetDlgItemText(IDC_EDIT1, strMsg); //填充内容
    strMsg = "";
}
void CUMDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
    // 关闭监听套接字,并释放Winsock库
    closesocket(clientSocket);
    closesocket(listenSocket);
    WSACleanup();
	CDialogEx::OnClose();
}

void CUMDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CUMDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CUMDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CUMDlg::OnEnChangeEdit1()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
}

三、系统核心代码-客户端


// UMCLIENTDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "UMCLIENT.h"
#include "UMCLIENTDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CUMCLIENTDlg 对话框




CUMCLIENTDlg::CUMCLIENTDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CUMCLIENTDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CUMCLIENTDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CUMCLIENTDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CUMCLIENTDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CUMCLIENTDlg::OnBnClickedButton2)
	ON_MESSAGE(UM_CLIENT, OnSock)
END_MESSAGE_MAP()


// CUMCLIENTDlg 消息处理程序

BOOL CUMCLIENTDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CUMCLIENTDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CUMCLIENTDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CUMCLIENTDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


//连接
void CUMCLIENTDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	char szBtnName[10] = {0};
	GetDlgItemText(IDC_BUTTON1,szBtnName,10);
	if(!lstrcmp(szBtnName,"断开连接")){
		SetDlgItemText(IDC_BUTTON1,"连接");
		(GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE)); //内容区域
		(GetDlgItem(IDC_EDIT4)->EnableWindow(FALSE)); //命令区域
		(GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE)); //发送按钮
		closesocket(mSocket);
		strMsg = "主动断开连接";
		InsertMsg();
		return;
	}
	char szIpAddr[MAXBYTE] = {0};
	GetDlgItemText(IDC_EDIT1,szIpAddr,MAXBYTE); //获取IP
	mSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //创建套接字;SOCK_STREAM:流套接字 SOCK_DGRAM:数据包套接字;SOCK_RAM:原始协议套接字;TCP形式
	WSAAsyncSelect(mSocket,GetSafeHwnd(),UM_CLIENT,FD_READ|FD_CONNECT|FD_CLOSE); //非阻塞模式 1:接收消息窗口;2:消息;3:通知码;
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = inet_addr(szIpAddr);  //将点分10进制IP,转换成无符号long类型  也可以设置ADDR_ANY; 逆函数 inet_ntor
	addr.sin_port = htons(5555);//主机字节转换成网络字节,在端口方面,x86为小尾方式  TCP/IP为大尾方式,所以需要转换。大尾与小尾区别为字节存储顺序相反
	connect(mSocket,(SOCKADDR *)&addr,sizeof(addr)); //连接
}

//发送命令
void CUMCLIENTDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	char szBuf[MAXBYTE] = {0};
	GetDlgItemText(IDC_EDIT4,szBuf,MAXBYTE); //获取命令
	send(mSocket,szBuf,MAXBYTE,0); //发送命令
}

//响应通知码
LRESULT CUMCLIENTDlg::OnSock(WPARAM wParam, LPARAM lParam)
{
	if(WSAGETSELECTERROR(lParam)){
	  return 1;
	}
	switch(WSAGETSELECTEVENT(lParam)){
	
	//处理 FD_ACCEPT
	case FD_CONNECT:
		{
			(GetDlgItem(IDC_EDIT2)->EnableWindow(TRUE)); //内容区域
			(GetDlgItem(IDC_EDIT4)->EnableWindow(TRUE)); //命令区域
			(GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE)); //发送按钮
			SetDlgItemText(IDC_BUTTON1,"断开连接");
			strMsg = "连接成功";
			break;
		}
	case FD_READ:
		{
			DATA_MSG dataMsg;
			recv(mSocket,(char *) &dataMsg,sizeof(dataMsg),0); //接收
			DispatchMsg((char *)&dataMsg);
			break;
		}
	case FD_CLOSE:
		{
			(GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE)); //内容区域
			(GetDlgItem(IDC_EDIT4)->EnableWindow(FALSE)); //命令区域
			(GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE)); //发送按钮
			closesocket(mSocket);
			strMsg = "对方断开连接";
			break;
		}
	}
	InsertMsg();//输出到前台
	return 1;
}

//匹配消息
void CUMCLIENTDlg::DispatchMsg(char* szBuf)
{
	DATA_MSG DataMsg;
	memcpy((void*)&DataMsg, (const void *)szBuf, sizeof(DATA_MSG));
	if(DataMsg.bType = TEXTMSG){ //帮助信息
		strMsg = DataMsg.szValue;
	}
	else {
		if(DataMsg.bClass == SYSINFO){ //系统信息
			ParseSysInfo((PSYS_INFO )&DataMsg.szValue);
		}
	}
}



//解析系统信息
void CUMCLIENTDlg::ParseSysInfo(PSYS_INFO sysInfo)
{
	if ( sysInfo->OsVer.dwPlatformId == VER_PLATFORM_WIN32_NT )
    {
        if ( sysInfo->OsVer.dwMajorVersion == 5 && sysInfo->OsVer.dwMinorVersion == 1 )
        {
            strMsg.Format("对方系统信息:\r\n\t Windows %s", sysInfo->OsVer.szCSDVersion);
        }
        else if ( sysInfo->OsVer.dwMajorVersion == 5 && sysInfo->OsVer.dwMinorVersion == 0)
        {
            strMsg.Format("对方系统信息:\r\n\t Windows 2K");
        }
    }
    else
    {
        strMsg.Format("对方系统信息:\r\n\t Other System \r\n");
    }
    
    strMsg += "\r\n";
    strMsg += "\t Computer Name is ";
    strMsg += sysInfo->szComputerName;
    strMsg += "\r\n";
    strMsg += "\t User Name is ";
    strMsg += sysInfo->szUserName;
}

void CUMCLIENTDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
    closesocket(mSocket);
    WSACleanup();
	
	CUMCLIENTDlg::OnClose();
}

//输出信息
void CUMCLIENTDlg::InsertMsg()
{
    CString strMsgNew;
    GetDlgItemText(IDC_EDIT2, strMsgNew);//获取内容
    strMsg += "\r\n";
    strMsg += "----------------------------------------\r\n";
    strMsg += strMsgNew;
    SetDlgItemText(IDC_EDIT2, strMsg); //填充内容
    strMsg = "";
}

       需要注意的是,在X86架构下,数值存储方式默认是小尾方式字节顺序(内存高位地址存放高位字节数据),TCP/IP数值存储方式默认是大尾方式字节顺序(内存高位地址存放低位字节数据)。

四、后期优化

在深度层面:1.利用系统漏洞或者U盘病毒进行传播,以反弹方式与client进行交互。2.扫描端口,进行端口复用。

在广度层面:1.支持执行CMD命令;1.支持获取远程文件信息,实现文件目录浏览、文件下载、文件加密等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

登峰造Geek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值