zoukankan      html  css  js  c++  java
  • VC++分析数据包实现分析http协议


    超文本传送协议 (HTTP-Hypertext transfer protocol) 是分布式,协作式,超媒体系统应用之间的通信协议。是万维网(world wide web)交换信息的基础。
      它允许将超文本标记语言 (HTML) 文档从 Web 服务器传送到 Web 浏览器。HTML 是一种用于创建文档的标记语言,这些文档包含到相关信息的链接。您可以单击一个链接来访问其它文档、图像或多媒体对象,并获得关于链接项的附加信息。
        
      HTTP工作在TCP/IP协议体系中的TCP协议上。
      客户机和服务器必须都支持 HTTP,才能在万维网上发送和接收 HTML 文档并进行交互。
      现在WWW中使用的是HTTP/1.1,它是由RFCs(Requests for comments)在1990年6月制定。目前交由IETF(Internet Engineering Task Force) 和W3C(World Wide Web)负责修改。但最终还是由RFCs对外发布。


     HTTP协议的主要特点可概括如下:
      1、支持客户/服务器模式。  http 协议 简介
      2、 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
      3、灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
      4、无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
      5、无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
      另一方面,在服务器不需要先前信息时它的应答就较快


      HTTP/1.1协议中共定义了八种方法(有时也叫“动作”)来表明Request-URI指定的资源的不同操作方式:
      OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。 
      HEAD 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。 
      GET 向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在web app.中。其中一个原因是GET可能会被网络蜘蛛等随意访问。 
      POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 
      PUT 向指定资源位置上传其最新内容。 
      DELETE 请求服务器删除Request-URI所标识的资源。 
      TRACE 回显服务器收到的请求,主要用于测试或诊断。 
      CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 
      方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed);当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。 
      HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。









    #include "nids.h"   
    char ascii_string[10000];   
    char *char_to_ascii(char ch)   
    {   
        char *string;   
        ascii_string[0] = 0;   
        string = ascii_string;   
        if (isgraph(ch))   
        {   
            *string++ = ch;   
        }   
        else if (ch == ' ')   
        {   
            *string++ = ch;   
        }   
        else if (ch == '\n' || ch == '\r')   
        {   
            *string++ = ch;   
        }   
        else   
        {   
            *string++ = '.';   
        }   
        *string = 0;   
        return ascii_string;   
    }   
    /*  
    =======================================================================================================================  
    下面的函数是对浏览器接收的数据进行分析  
    =======================================================================================================================  
     */   
    void parse_client_data(char content[], int number)   
    {   
        char temp[1024];   
        char str1[1024];   
        char str2[1024];   
        char str3[1024];   
        int i;   
        int k;   
        int j;   
        char entity_content[1024];   
        if (content[0] != 'H' && content[1] != 'T' && content[2] != 'T' && content[3] != 'P')   
        {   
            printf("实体内容为(续):\n");   
            for (i = 0; i < number; i++)   
            {   
                printf("%s", char_to_ascii(content[i]));   
            }   
            printf("\n");   
        }   
        else   
        {   
            for (i = 0; i < strlen(content); i++)   
            {   
                if (content[i] != '\n')   
                {   
                    k++;   
                    continue;   
                }   
                for (j = 0; j < k; j++)   
                    temp[j] = content[j + i - k];   
                temp[j] = '\0';   
                if (strstr(temp, "HTTP"))   
                {   
                    printf("状态行为:");   
                    printf("%s\n", temp);   
                    sscanf(temp, "%s %s %s", str1, str2);   
                    printf("HTTP协议为:%s\n", str1);   
                    printf("状态代码为:%s\n", str2);   
                }   
                if (strstr(temp, "Date"))   
                {   
                    printf("当前的时间为(Date):%s\n", temp + strlen("Date:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Server"))   
                {   
                    printf("服务器为(Server):%s\n", temp + strlen("Server:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Cache-Control"))   
                {   
                    printf("缓存机制为(Cache-Control):%s\n", temp + strlen("Cache-Control:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Expires"))   
                {   
                    printf("资源期限为(Expires):%s\n", temp + strlen("Expires:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Last-Modified"))   
                {   
                    printf("最后一次修改的时间为(Last-Modified):%s\n", temp + strlen("Last-Modified:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "ETag"))   
                {   
                    printf("Etag为(ETag):%s\n", temp + strlen("Etag:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Accept-Ranges"))   
                {   
                    printf("Accept-Ranges(Accept-Ranges):%s\n", temp + strlen("Accept-Ranges:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Content-Length"))   
                {   
                    printf("内容长度为(Content-Length):%s\n", temp + strlen("Content-Length:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Connection"))   
                {   
                    printf("连接状态为(Connection):%s\n", temp + strlen("Connection:"));   
                    printf("%s\n", temp);   
                }   
                if (strstr(temp, "Content-Type"))   
                {   
                    printf("内容类型为(Content-Type):%s\n", temp + strlen("Content-Type:"));   
                    printf("%s\n", temp);   
                }   
                /* 获取实体内容 */   
                if ((content[i] == '\n') && (content[i + 1] == '\r'))   
                {   
                    if (i + 3 == strlen(content))   
                    {   
                        printf("无实体内容\n");   
                        break;   
                    }   
                    for (j = 0; j < number - i - 3; j++)   
                        entity_content[j] = content[i + 3+j];   
                    entity_content[j] = '\0';   
                    printf("实体内容为:\n");   
                    for (i = 0; i < j; i++)   
                    {   
                        printf("%s", char_to_ascii(entity_content[i]));   
                    }   
                    printf("\n");   
                    break;   
                }   
                k = 0;   
            }   
        }   
    }   
    /*  
    =======================================================================================================================  
    下面的函数是对WEB服务器接收到的数据进行分析  
    =======================================================================================================================  
     */   
    void parse_server_data(char content[], int number)   
    {   
        char temp[1024];   
        char str1[1024];   
        char str2[1024];   
        char str3[1024];   
        int i;   
        int k;   
        int j;   
        char entity_content[1024];   
        for (i = 0; i < strlen(content); i++)   
        {   
            if (content[i] != '\n')   
            {   
                k++;   
                continue;   
            }   
            for (j = 0; j < k; j++)   
                temp[j] = content[j + i - k];   
            temp[j] = '\0';   
            if (strstr(temp, "GET"))   
            {   
                printf("请求行为:");   
                printf("%s\n", temp);   
                sscanf(temp, "%s %s %s", str1, str2, str3);   
                printf("使用的命令为:%s\n", str1);   
                printf("获得的资源为:%s\n", str2);   
                printf("HTTP协议类型为:%s\n", str3);   
            }   
            if (strstr(temp, "Accept:"))   
            {   
                printf("接收的文件包括(Accept:):%s\n", temp + strlen("Accept:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Referer"))   
            {   
                printf("转移地址为(Referer):%s\n", temp + strlen("Referer:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Accept-Language"))   
            {   
                printf("使用的语言为(Accept-Language):%s\n", temp + strlen("Accept-Language:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Accept-Encoding"))   
            {   
                printf("接收的编码方式为(Accept-Encoding):%s\n", temp + strlen("Accept-Encoding:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "If-Modified-Since"))   
            {   
                printf("上次修改时间为(If-Modified-Since):%s\n", temp + strlen("If-Modified-Since:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "If-None-Match"))   
            {   
                printf("If-None-Match为(If-Modified-Since):%s\n", temp + strlen("If-None-Match:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "User-Agent"))   
            {   
                printf("用户的浏览器信息为(User-Agent):%s\n", temp + strlen("User-Agent:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Host"))   
            {   
                printf("访问的主机为(Host):%s\n", temp + strlen("Host:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Connection"))   
            {   
                printf("连接状态为(Connection):%s\n", temp + strlen("Connection:"));   
                printf("%s\n", temp);   
            }   
            if (strstr(temp, "Cookie"))   
            {   
                printf("Cookie为(Cookie):%s\n", temp + strlen("Cookie:"));   
                printf("%s\n", temp);   
            }   
            /* 获取实体内容 */   
            if ((content[i] == '\n') && (content[i + 1] == '\r') && (content[i + 2] == '\n'))   
            {   
                if (i + 3 == strlen(content))   
                {   
                    printf("无实体内容\n");   
                    break;   
                }   
                for (j = 0; j < strlen(content) - i - 3; j++)   
                    entity_content[j] = content[i + 3+j];   
                entity_content[j] = '\0';   
                printf("实体内容为:\n");   
                printf("%s", entity_content);   
                printf("\n");   
                break;   
            }   
            k = 0;   
        }   
    }   
    /*  
    =======================================================================================================================  
    下面是回调函数,实现对HTTP协议的分析  
    =======================================================================================================================  
     */   
    void http_protocol_callback(struct tcp_stream *tcp_http_connection, void **param)   
    {   
        char address_content[1024];   
        char content[65535];   
        char content_urgent[65535];   
        struct tuple4 ip_and_port = tcp_http_connection->addr;   
        strcpy(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));   
        sprintf(address_content + strlen(address_content), " : %i", ip_and_port.source);   
        strcat(address_content, " <----> ");   
        strcat(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));   
        sprintf(address_content + strlen(address_content), " : %i", ip_and_port.dest);   
        strcat(address_content, "\n");   
        if (tcp_http_connection->nids_state == NIDS_JUST_EST)   
        {   
            if (tcp_http_connection->addr.dest != 80)   
             /* 只捕获HTTP协议数据包 */   
            {   
                return ;   
            }   
            tcp_http_connection->client.collect++; /* 浏览器接收数据 */   
            tcp_http_connection->server.collect++; /* WEB服务器端接收数据 */   
            printf("\n\n\n==============================================\n");   
            printf("%s 建立连接...\n", address_content);   
            return ;   
        }   
        if (tcp_http_connection->nids_state == NIDS_CLOSE)   
        {   
            printf("--------------------------------\n");   
            printf("%s连接正常关闭...\n", address_content);   
            /* 连接正常关闭 */   
            return ;   
        }   
        if (tcp_http_connection->nids_state == NIDS_RESET)   
        {   
            printf("--------------------------------\n");   
            printf("%s连接被RST关闭...\n", address_content);   
            /* 连接被RST关闭 */   
            return ;   
        }   
        if (tcp_http_connection->nids_state == NIDS_DATA)   
        {   
            struct half_stream *hlf;   
            if (tcp_http_connection->client.count_new)   
             /* 浏览器接收数据 */   
            {   
                hlf = &tcp_http_connection->client;   
                /* hlft表示浏览器接收的数据 */   
                strcpy(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));   
                sprintf(address_content + strlen(address_content), ":%i", ip_and_port.source);   
                strcat(address_content, " <---- ");   
                strcat(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));   
                sprintf(address_content + strlen(address_content), ":%i", ip_and_port.dest);   
                strcat(address_content, "\n");   
                printf("\n");   
                printf("%s", address_content);   
                printf("浏览器接收数据...\n");   
                printf("\n");   
                memcpy(content, hlf->data, hlf->count_new);   
                content[hlf->count_new] = '\0';   
                parse_client_data(content, hlf->count_new);   
                /* 分析浏览器接收的数据 */   
            }   
            else   
            {   
                hlf = &tcp_http_connection->server;   
                /* hlf表示Web服务器的TCP连接端 */   
                strcpy(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));   
                sprintf(address_content + strlen(address_content), " : %i", ip_and_port.source);   
                strcat(address_content, " ----> ");   
                strcat(address_content, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));   
                sprintf(address_content + strlen(address_content), ":%i", ip_and_port.dest);   
                strcat(address_content, "\n");   
                printf("\n");   
                printf("%s", address_content);   
                printf("服务器接收数据...\n");   
                printf("\n");   
                memcpy(content, hlf->data, hlf->count_new);   
                content[hlf->count_new] = '\0';   
                parse_server_data(content, hlf->count_new);   
                /* 分析WEB服务器接收的数据 */   
            }   
        }   
        return ;   
    }   
    /*  
    =======================================================================================================================  
    主函数  
    =======================================================================================================================  
     */   
    void main()   
    {   
        if (!nids_init())   
         /* Libnids初始化 */   
        {   
            printf("出现错误:%s\n", nids_errbuf);   
            exit(1);   
        }   
        nids_register_tcp(http_protocol_callback);   
        /* 注册回调函数 */   
        nids_run(); /* 进入循环捕获数据包状态 */   
    }   
    


  • 相关阅读:
    FPGA学习之基本结构
    凸优化和机器学习
    第6篇如何访问pod
    吉日嘎拉DotNet.BusinessV4.2中的一处bug,及我的修复和扩展
    吉日嘎拉C#快速开发平台V4.0到V4.2升级记
    布隆过滤器简介及实现-----源自数学之美
    poj [1753]
    Zookeeper Hello World
    获取用户真实IP,php实现
    mysql中engine=innodb和engine=myisam的区别
  • 原文地址:https://www.cnblogs.com/new0801/p/6177692.html
Copyright © 2011-2022 走看看