2011-03-07 43 views
0

我正在寫一個小型的tcp echo服務器來測試Linux上的緩衝區溢出。我有兩個略有不同的服務器代碼版本。當超大尺寸的緩衝區被髮送時,第一個緩衝區將按照預期在讀功能中溢出,導致分段錯誤。對於代碼的第二個版本,我在接受,讀取和寫入函數週圍添加了一個While(1)循環,以便服務器在正常使用時不會退出,但是當同一個緩衝區發送到第二個服務器時,並且服務器根本不會崩潰。我無法弄清楚爲什麼,代碼與while循環相同。任何幫助將非常感激。 :)緩衝區溢出的C代碼問題

服務器1個

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, clilen; 
    char recv[512]; 
    bzero(recv,512); 
    struct sockaddr_in serv_addr, cli_addr; 
    if (argc < 2) exit(1); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) exit(1); 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) exit(1); 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 
    if (newsockfd < 0) exit(1); 
    int n = read(newsockfd,recv,1024); 
    if (n < 0) exit(1); 
    write(newsockfd,recv,n); 
    close(newsockfd); 
    return 0; 
} 

服務器2

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, clilen; 
    char recv[512]; 
    bzero(recv,512); 
    struct sockaddr_in serv_addr, cli_addr; 
    if (argc < 2) exit(1); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) exit(1); 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) exit(1); 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 
    while (1) { 
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 
     if (newsockfd < 0) continue; 
     int n = read(newsockfd,recv,1024); 
     if (n < 0) continue; 
     write(newsockfd,recv,n); 
     close(newsockfd); 
    } 
    return 0; 
} 
+0

讓我直截了當地 - 你有意編寫一個程序來允許任意遠程代碼執行?見:http://en.wikipedia.org/wiki/Backdoor_(computing) – 2011-03-07 04:47:06

+0

是的,這就是要點。我將在受控環境中使用該程序來演示* nix平臺上的漏洞利用開發。 – k1ug3 2011-03-07 05:20:33

回答

1

你無法預測何時存在緩衝區溢出程序會做些什麼。行爲取決於緩衝區後面發生了什麼,以及過長輸入中的內容。這些事情可能取決於程序中不相關的部分(編譯的東西的地址),甚至可能包括從運行變爲運行的加載地址。

2

緩衝區溢出導致堆棧被覆蓋,特別是函數的返回地址。實際的溢出本身並不是導致分段錯誤的原因,而是當你稍後從具有溢出的函數返回時,返回地址已被破壞。 (緩衝區溢出的其他可能段錯誤包括從覆蓋指針訪問內存,或使用已被覆蓋的函數指針等)。

在你的例子中,while循環阻止你到達return語句,所以當你的緩衝區被溢出並且你的返回地址被破壞時,那個返回地址從不被使用,所以segfault不會發生。

如果你想驗證溢出是否發生,我建議你在調試器中觀察,或者打印出serv_addr和cli_addr結構中的值,我認爲這些值會被溢出破壞。

另外,如果您想查看segfault溢出,請將recv調用及其目標緩衝區移入單獨的函數,然後在while(1)循環內調用該函數。當帶有recv的函數返回時,segfault應該發生。

+1

非常感謝,這很好。附:那隻貓看起來像Kerby ... – k1ug3 2011-03-07 04:27:25