2009-08-18 78 views
2

我正在組合一個端口掃描程序作爲學習練習。我的問題是我試圖在TCP頭中設置最大段大小選項(MSS)。我看了一下tcp.h,但是我很難弄清楚如何設置它。我希望會有這樣一個選項:在tcp頭文件中設置最大段大小

tcp_header->mss(32000);

類似的東西上面是tcp.h中而不是在正確的結構。不可否認,我對於讀取結構定義仍然相當陌生,而且我從tcp.h中得不到多少意義,所以最後我試圖在TCP標頭末尾加上必要的字節:

struct tcphdr *CreateTcpHeader() 
{ 
    struct tcphdr *tcp_header; 

    tcp_header = (struct tcphdr *)malloc(sizeof(struct tcphdr)+4*sizeof(int)); 


    tcp_header->source = htons(SRC_PORT); 
    tcp_header->dest = htons(DST_PORT); 
    tcp_header->seq = htonl(0);    
    tcp_header->ack_seq = htonl(0);   
    tcp_header->res1 = 0; 
    tcp_header->doff = (sizeof(struct tcphdr))/4; 
    tcp_header->syn = 1; 
    tcp_header->window = htons(4096); 
    tcp_header->check = 0; /* Will calculate the checksum with pseudo-header later */ 
    tcp_header->urg_ptr = 0; 


    /*memcpy the mss data onto the end of the tcp header. */ 
    int mssCode = 2; 
    int mssLength = 4; 
    uint16_t mss = htonl(32000); 
    int offset = sizeof(struct tcphdr); 
    memcpy((tcp_header+offset), &mssCode, 1); 
    memcpy((tcp_header+offset+1), &mssLength, 1); 
    memcpy((tcp_header+offset+2), &mss, 2); 

    return (tcp_header); 
} 

但是在我寫完之後很明顯這不是一個真正的解決方案,再加上它仍然不起作用:P那麼還有更好的方法嗎?

+0

你如何使用這個頭?你使用libnet發送它嗎? – Jonathan 2009-08-18 20:30:39

+0

我只是使用原始套接字。雖然即使使用新的mss選項,儘管它與nmap的實際相同,但我的數據包仍然被忽略。任何想法的人? – CalumMcCall 2009-08-18 22:38:26

+0

根據你正在學習的東西 - C或網絡,你可能想看看http://www.secdev.org/projects/scapy/ – 2009-08-19 15:17:32

回答

5

tcp.h中的struct tcphdr定義了TCP報頭的強制部分。 (請查看TCP header,您可以將struct tcphdr中的定義與您在頭中出現的實際位相匹配。)C中的結構體具有恆定大小,但TCP允許可選數據。頭長度字段(doff的結構)是標題,包括期權的總長度,所以你需要添加一個字佔MSS選項:

tcp_header->doff = (sizeof(struct tcphdr))/4 + 1; 

讓我們定義爲一個結構MSS選項:

struct tcp_option_mss { 
    uint8_t kind; /* 2 */ 
    uint8_t len; /* 4 */ 
    uint16_t mss; 
} __attribute__((packed)); 

現在你可以填充結構,以正確的順序:

/*memcpy the mss data onto the end of the tcp header. */ 
struct tcp_option_mss mss; 
mss.kind = 2; 
mss.len = 4; 
mss.mss = htons(32000); 

讓我們走一步,併爲您的PA的單一結構cket,讓編譯器 幫助我們:

struct tcphdr_mss { 
    struct tcphdr tcp_header; 
    struct tcp_option_mss mss; 
}; 

(您可能需要在末尾添加結束選項列表的選項,NOP選項來填充選項列表爲8個字節)

現在我們可以把所有的拼在一起:

struct tcphdr *CreateTcpHeader() 
{ 
    struct tcphdr_mss *tcp_header; 

    tcp_header = malloc(sizeof(struct tcphdr_mss)); 

    tcp_header->tcp_header.source = htons(SRC_PORT); 
    tcp_header->tcp_header.dest = htons(DST_PORT); 
    tcp_header->tcp_header.seq = htonl(0);    
    tcp_header->tcp_header.ack_seq = htonl(0);   
    tcp_header->tcp_header.res1 = 0; 
    tcp_header->tcp_header.doff = (sizeof(struct tcphdr_mss))/4; 
    tcp_header->tcp_header.syn = 1; 
    tcp_header->tcp_header.window = htons(4096); 
    tcp_header->tcp_header.check = 0; /* Will calculate the checksum with pseudo-header later */ 
    tcp_header->tcp_header.urg_ptr = 0; 

    tcp_header->mss.kind = 2; 
    tcp_header->mss.len = 2; 
    tcp_header->mss.mss = htons(32000); 

    return (tcp_header); 
} 
+0

啊這一切現在都有道理。謝謝一堆。 – CalumMcCall 2009-08-18 21:24:04