一個遠端系統控制檯的小工具

SonicDX發表於2006-11-10

 

    因為工作需要很多的遠端管理,一些現有的工具已經不能滿足實際要求。所以就 有了製作一個小型遠端控制檯的想法。

   其實,它的工作原理很簡單。主要有兩部分組成,一個是對Cmd.exe 的標準輸入和輸出的重定向,另外有一個TCP連線來把本機的資訊傳送給遠端的主機。

   以為手上有兩個能實現上述功能的開原始碼,所以我的工作就是把它們揉在一起。但要求是Socket和ReStdInOut必須分離,Socket要不能使用MFC(為了方便把邏輯移植到Linux或者和.Net連線),服務段程式必須是控制檯(為了把它最終變成一個NT服務)。

    Socket類是一個在網上找到的一輕量級WinSocket封裝,因為覺得它寫的比我原來自己的封裝要好,而且最終要的是它已經儘可能使用的是標準C++庫(用的是Std::String,不是MFC::CString),給以後的移植方便了不少。

  參考 C++ Socket Class for Windows

  該類使用非常的方便

A simple Client

The following simple client connects to www.google.ch and get its front-website.
#include "Socket.h"

#include 
<iostream>

using namespace std;

int main() {

  
try {
    SocketClient s(
"www.google.com"80);

    s.SendLine(
"GET / HTTP/1.0");
    s.SendLine(
"Host: www.google.com");
    s.SendLine(
"");

    
while (1{
      
string l = s.ReceiveLine();
      
if (l.empty()) break;
      cout 
<< l;
      cout.flush();
    }


  }
 
  
catch (const char* s) {
    cerr 
<< s << endl;
  }
 
  
catch (String s) {
    cerr 
<< s << endl;
  }
 
  
catch (...) {
    cerr 
<< "unhandled exception ";
  }


  
return 0;
}

A simple echo Server

The following simple Server opens a port on 2000 and waits for incoming connections. Each connection is answered with the same line as was written (echoed).

 

/* 
   EchoServer.cpp

   Copyright (C) 2002-2004 René Nyffenegger

   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:

   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.

   3. This notice may not be removed or altered from any source distribution.

   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/



#include 
"Socket.h"
#include 
<process.h>
#include 
<string>

unsigned __stdcall Answer(
void* a) {
  Socket
* s = (Socket*) a;

  
while (1{
    std::
string r = s->ReceiveLine();
    
if (r.empty()) break;
    s
->SendLine(r);
  }


  delete s;

  
return 0;
}


int main(int argc, char* argv[]) {
  SocketServer 
in(2000,5);

  
while (1{
    Socket
* s=in.Accept();

    unsigned ret;
    _beginthreadex(
0,0,Answer,(void*) s,0,&ret);
  }

 
  
return 0;
}

標準輸入輸入的重定向 用了一個CodeProjet 的專案

QuickWin - Turn a console application into a Windows program

專案裡的CRedirect類個人感覺非常好用,只需從他繼承一個自己的類,並且重寫4個虛擬函式

virtual void OnChildStarted(LPCSTR lpszCmdLine);
virtual void OnChildStdOutWrite(LPCSTR lpszOutput);
virtual void OnChildStdErrWrite(LPCSTR lpszOutput);
virtual void OnChildTerminate();

就輕鬆實現了標準輸入輸出的重定向。

其實核心技術都不是我自己寫的,但是得益於開源的力量,在瞭解了他們的原始碼有我覺得完全可能把它們結合成一個新的應用。

我的方法是

 1、Server初始化一個TCP Listener,等待客戶端接入。

2、客戶端接入服務段。

3、服務段連線客戶端後,開啟一個cmd.exe的程式,並重導向它的標準輸入、輸出和錯誤流。(這裡可以改進一下,使用API:CreateProcessWithLogonW或API:CreateProcessWithTokenW,是cmd.exe跑在制定的使用者下,因為如果當前程式是NT服務的話,預設在System帳戶下,我問需要找到當前的登陸使用者,用它的程式跑Cmd.exe

4、 用ReDir類的WriteStdIn和StdOut事件,反覆輸入和到處從Socket.ReandLine和Socket.SendLine的內容,以實現遠端控制檯的目的.

5、當客戶端用Exit結束cmd.exe時,服務段關閉連線自動退出。[你也改為繼續等待下個連線]

介面:(因為用的是Visual Studio 2005製作,執行需要MFC8的RunTime DLL)

先啟動服務程式:

接著使用 Telnet localhost 2000 連線服務,會得到一下狀態

你就可以向使用自己的本地控制檯一樣操作那臺機器了。

連續兩次exit指令 關閉連線、退出服務。

下載原始碼

注意:我故意沒有隱藏開啟的cmd.exe程式,可以開原始碼裡OpenChildProcess了第二個引數為0就可隱藏了。

整個製作時間:3小時。(開源真好:))

問題:沒有過濾掉輸出重複的命令

 

相關文章