problem in create packet using struct in c

折月煮酒 提交于 2020-01-25 07:57:10

问题


I wrote a c program that listen to 443 port and receives ssl packets :

#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);
         }
}

I create structures from this link : http://blog.fourthbit.com/2014/12/23/traffic-analysis-of-an-ssl-slash-tls-session/

when i run the program and connect to it using curl -I https://127.0.0.1:443 --insecure, it receives some data . the problem is when i print that data in logfile file , i get these value that all are incorrect except type1 :

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

i'm new in c and specially in struct and i'm not sure the problem is occurred when i create the structs or when i try to print fields. can anybody help to figure out the problem.


回答1:


You have a problem with wrong data types and with padding of your structures.

From your link, the TLS header contains:

  • 1 byte type
  • 2 bytes version
  • 2 bytes length

Your attempt to map this to a structure has some flaw:

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

For most architectures, a uint8_t has no specific alignment requirements while uint16_t is probably aligned on a 2byte boundary. This is achieved by inserting invisible padding bytes. While the header is 5 bytes, your struct contains 6 bytes or even more.

You might try to address this by using packed structs.

The second problem is you are using wrong types in your arrays.

The protocol definition contains a length field of 3 bytes and a version field of 2 bytes. In total these are 5 bytes.

Your struct looks like this:

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

This means you have 5 integers meaning 10, 20 or even 40 bytes in total.

Additionally you will have padding bytes also in this structure.

The layout of your structures is far off of the protocol definition.

You should not try to read a buffer directly into a memory location that is interpreted as a struct. Instead you should read and handle each field separately. Then you can properly handly endianess, integer fields of any length and don't need to take care about padding in your structs.



来源:https://stackoverflow.com/questions/59629415/problem-in-create-packet-using-struct-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!