【问题标题】:problem in create packet using struct in c在c中使用struct创建数据包的问题
【发布时间】:2020-01-07 13:30:15
【问题描述】:

我写了一个监听443端口并接收ssl数据包的c程序:

#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <stdio.h>

 #define MAX_SIZE 10000

struct ssl_header {
  uint8_t type;
  uint16_t   version;
  uint16_t   length;
};

struct handshake {
  struct ssl_header hdr;
  uint8_t type;
  unsigned int length[3]; 
  unsigned int ssl_version[2];
  char random[32];
};

void *message_processing(int sockfd){
    char *buff = calloc(MAX_SIZE + 1, sizeof (char));
    struct handshake *pkt;       
    pkt = calloc (1, sizeof (struct handshake));               

    while (1) {
        int len_of_read_data = read( sockfd, buff, MAX_SIZE);

        if (len_of_read_data > 0) {
          memcpy(pkt, buff, sizeof (struct handshake) );
          FILE* file = fopen("logfile", "a"); 
          fprintf (file, "*********************************\n");
          fprintf (file, "type1 : %u\n", pkt->hdr.type );
          fprintf(file, "version1 : %u\n", pkt->hdr.version);
          fprintf(file, "len1 : %u\n", pkt->hdr.length);
          fprintf(file, "type2 : %u\n", pkt->type);
          fprintf(file, "len2 : %u%u%u\n", pkt->length[0],pkt->length[1], pkt->length[2] );
          fprintf(file, "version2 : %u.%u\n", pkt->ssl_version[0], pkt->ssl_version[1]);
          fprintf(file, "random : %s\n", pkt->random);
          fclose(file);
        }
    }
}

int main () {
    struct sockaddr_in serv_addr;
    int sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
    int trueval = 1;
    setsockopt(sock_descriptor, SOL_SOCKET, SO_REUSEPORT | SO_REUSEADDR, (char *)&trueval, sizeof(trueval));

    bzero((char *) &serv_addr, sizeof (serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(443);

    bind(sock_descriptor, (struct sockaddr *) &serv_addr, sizeof (serv_addr));
    listen(sock_descriptor, 50);

    while (1) {
            struct sockaddr_in cli_addr;
            socklen_t clilen;
            clilen = sizeof(cli_addr);

            int client_socket  = accept(sock_descriptor, (struct sockaddr *) &cli_addr, &clilen);

            message_processing(client_socket);
            pthread_t pid;
            pthread_create(&pid, NULL, (void *) message_processing, &client_socket);
            pthread_join(pid, NULL);
         }
}

我从这个链接创建结构:http://blog.fourthbit.com/2014/12/23/traffic-analysis-of-an-ssl-slash-tls-session/

当我运行程序并使用 curl -I https://127.0.0.1:443 --insecure 连接到它时,它会收到一些数据。 问题是当我在 logfile 文件中打印该数据时,我得到的这些值都是不正确的,除了 type1

*********************************
type1 : 22
version1 : 513
len1 : 256
type2 : 0
len2 : 31543142363974688046409855404
version2 : 4270624758.750651113
random : �&,�X�I�Y��|}

我是 c 中的新手,特别是 struct 中的新手,我不确定当我创建结构或尝试打印字段时是否会出现问题。 任何人都可以帮助找出问题所在。

【问题讨论】:

  • 你考虑过endianness吗?
  • 还要考虑int的大小,不固定。
  • 3 字节整数?您是否考虑过结构的填充和内存布局?你知道int length[3] 的意思是一个由 3 个整数变量组成的数组,而不是一个 3 个字节的整数变量,不是吗?
  • 我建议不要将接收缓冲区复制到块中的结构,因为结构字段可以与单词对齐。将每个字段从缓冲区复制并转换为结构。一个无符号整数长度 [3] 有 3 个 sizeof(int) 是不同的 3 个字节的长度。您必须从缓冲区中提取 3 个字节并转换为 int。
  • unsigned int length[3]; 是三个unsigned int 元素,每个元素是一个unsigned int 表示它的大小,如果sizeof(unsigned int) * 3 典型的32 位unsigned int 表示它是12 个字节,而不是三个!

标签: c struct printing


【解决方案1】:

您有错误的数据类型和结构填充的问题。

从您的链接中,TLS 标头包含:

  • 1 字节类型
  • 2 字节版本
  • 2 字节长度

您将其映射到结构的尝试存在一些缺陷:

struct ssl_header {
  uint8_t type;
  uint16_t   version;
  uint16_t   length;
};

对于大多数架构,uint8_t 没有特定的对齐要求,而uint16_t 可能在 2 字节边界上对齐。 这是通过插入不可见的填充字节来实现的。 虽然标头是 5 个字节,但您的结构包含 6 个字节甚至更多。

您可以尝试使用打包结构来解决这个问题。

第二个问题是您在数组中使用了错误的类型。

协议定义包含 3 个字节的长度字段和 2 个字节的版本字段。这些总共是 5 个字节。

你的结构看起来像这样:

  unsigned int length[3]; 
  unsigned int ssl_version[2];

这意味着您有 5 个整数,表示总共 10、20 甚至 40 个字节。

此外,您还将在此结构中使用填充字节。

您的结构布局与协议定义相差甚远。

您不应尝试将缓冲区直接读取到被解释为结构的内存位置。 相反,您应该分别阅读和处理每个字段。然后,您可以正确处理字节顺序、任何长度的整数字段,并且不需要注意结构中的填充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多