2011-03-07 60 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