проблема в создании пакета с использованием структуры в c - PullRequest
0 голосов
/ 07 января 2020

Я написал c программу, которая прослушивает порт 443 и получает ssl-пакеты:

#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 и особенно в структуре, и я не уверен, что проблема возникает, когда я создаю структуры или пытаюсь напечатать поля. Кто-нибудь может помочь выяснить проблему.

1 Ответ

4 голосов
/ 07 января 2020

У вас проблема с неправильными типами данных и заполнением ваших структур.

По вашей ссылке заголовок TLS содержит:

  • 1 байт типа
  • 2-байтовая версия
  • 2-байтовая длина

Ваша попытка отобразить это на структуру имеет некоторый недостаток:

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

Для большинства архитектур: uint8_t не имеет конкретных c требований к выравниванию, в то время как uint16_t, вероятно, выровнено на границе 2 байта. Это достигается путем вставки невидимых байтов заполнения. Хотя заголовок имеет 5 байтов, ваша структура содержит 6 или более байтов.

Вы можете попытаться решить эту проблему с помощью упакованных структур.

Вторая проблема заключается в том, что вы используете неправильные типы в своем массивы.

Определение протокола содержит поле длины в 3 байта и поле версии в 2 байта. Всего это 5 байтов.

Ваша структура выглядит следующим образом:

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

Это означает, что у вас есть 5 целых чисел, что означает 10, 20 или даже 40 байтов.

Кроме того, у вас также будут байты заполнения в этой структуре.

Структура ваших структур далека от определения протокола.

Не следует пытаться считывать буфер непосредственно в область памяти это интерпретируется как структура. Вместо этого вы должны читать и обрабатывать каждое поле отдельно. Тогда вы можете правильно обрабатывать endianess, целочисленные поля любой длины, и вам не нужно заботиться о заполнении ваших структур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...