在c中使用struct创建数据包的问题 [英] problem in create packet using struct in c

查看:34
本文介绍了在c中使用struct创建数据包的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

I create structures from this link : 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 外都是不正确的:

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��|}

我是 c 语言的新手,特别是结构体,我不确定在创建结构体或尝试打印字段时是否发生了问题.任何人都可以帮助找出问题所在.

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.

推荐答案

您遇到了错误的数据类型和结构填充问题.

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

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

From your link, the TLS header contains:

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

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

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

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

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

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.

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

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

您的结构如下所示:

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

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

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.

这篇关于在c中使用struct创建数据包的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆