From 01d5c4c872e30ad28ed613de7f9964eb8cce8f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=94=E4=B8=80=E9=B8=A3?= Date: Thu, 6 Feb 2020 23:35:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E5=8F=96ssl=E6=8F=A1=E6=89=8B?= =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E4=BF=A1=E6=81=AF(=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=AD=97=E6=AE=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DataSet/FeatureExtract/.vscode/ftp-kr.json | 8 +- DataSet/FeatureExtract/entry/CMakeLists.txt | 9 +- DataSet/FeatureExtract/entry/include/base64.h | 2 + DataSet/FeatureExtract/entry/src/base64.cpp | 143 ++++ .../entry/src/sslparse_entry.cpp | 641 ++++++++++++++++++ DataSet/FeatureExtract/vendor/CMakeLists.txt | 30 + .../vendor/openssl-1.1.1.tar.gz | Bin 0 -> 11266843 bytes 7 files changed, 828 insertions(+), 5 deletions(-) create mode 100644 DataSet/FeatureExtract/entry/include/base64.h create mode 100644 DataSet/FeatureExtract/entry/src/base64.cpp create mode 100644 DataSet/FeatureExtract/entry/src/sslparse_entry.cpp create mode 100644 DataSet/FeatureExtract/vendor/openssl-1.1.1.tar.gz diff --git a/DataSet/FeatureExtract/.vscode/ftp-kr.json b/DataSet/FeatureExtract/.vscode/ftp-kr.json index fbb6107..0a3157d 100644 --- a/DataSet/FeatureExtract/.vscode/ftp-kr.json +++ b/DataSet/FeatureExtract/.vscode/ftp-kr.json @@ -1,8 +1,8 @@ { - "host": "192.168.40.133", - "username": "root", - "password": "111111", - "remotePath": "/root/cuiyiming/FeatureExtract", + "host": "123.57.35.217", + "username": "cuiyiming", + "password": "070708", + "remotePath": "/data/cuiyiming/GradProj/FeatureExtract", "protocol": "sftp", "port": 22, "fileNameEncoding": "utf8", diff --git a/DataSet/FeatureExtract/entry/CMakeLists.txt b/DataSet/FeatureExtract/entry/CMakeLists.txt index ce1a263..5102350 100644 --- a/DataSet/FeatureExtract/entry/CMakeLists.txt +++ b/DataSet/FeatureExtract/entry/CMakeLists.txt @@ -5,4 +5,11 @@ target_link_libraries(stmstat MESA_prof_load MESA_field_stat cjson) add_library(sslstat SHARED src/sslstat_entry.cpp) target_include_directories(sslstat PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) -target_link_libraries(sslstat MESA_prof_load MESA_field_stat cjson) \ No newline at end of file +target_link_libraries(sslstat MESA_prof_load MESA_field_stat cjson) + +add_library(sslparse SHARED src/sslparse_entry.cpp src/ssl_utils.cpp src/base64.cpp) +target_include_directories(sslparse PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(sslparse MESA_prof_load MESA_field_stat cjson) + +add_executable(test_base64 src/base64.cpp) +target_include_directories(test_base64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) diff --git a/DataSet/FeatureExtract/entry/include/base64.h b/DataSet/FeatureExtract/entry/include/base64.h new file mode 100644 index 0000000..6f58c5c --- /dev/null +++ b/DataSet/FeatureExtract/entry/include/base64.h @@ -0,0 +1,2 @@ +unsigned int b64_encode(const unsigned char* in, unsigned int in_len, unsigned char* out); +unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned char* out); \ No newline at end of file diff --git a/DataSet/FeatureExtract/entry/src/base64.cpp b/DataSet/FeatureExtract/entry/src/base64.cpp new file mode 100644 index 0000000..b38e169 --- /dev/null +++ b/DataSet/FeatureExtract/entry/src/base64.cpp @@ -0,0 +1,143 @@ + +/* + base64.c - by Joe DF (joedf@ahkscript.org) + Released under the MIT License + + See "base64.h", for more information. + + Thank you for inspiration: + http://www.codeproject.com/Tips/813146/Fast-base-functions-for-encode-decode +*/ + +#include "base64.h" +#include +#include + +//Base64 char table - used internally for encoding +unsigned char b64_chr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +unsigned int b64_int(unsigned int ch) { + + // ASCII to base64_int + // 65-90 Upper Case >> 0-25 + // 97-122 Lower Case >> 26-51 + // 48-57 Numbers >> 52-61 + // 43 Plus (+) >> 62 + // 47 Slash (/) >> 63 + // 61 Equal (=) >> 64~ + if (ch==43) + return 62; + if (ch==47) + return 63; + if (ch==61) + return 64; + if ((ch>47) && (ch<58)) + return ch + 4; + if ((ch>64) && (ch<91)) + return ch - 'A'; + if ((ch>96) && (ch<123)) + return (ch - 'a') + 26; + return 0; +} + +/* +unsigned int b64e_size(unsigned int in_size) { + + // size equals 4*floor((1/3)*(in_size+2)); + int i, j = 0; + for (i=0;i>2 ]; + out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ]; + out[k+2] = b64_chr[ ((s[1]&0x0F)<<2)+((s[2]&0xC0)>>6) ]; + out[k+3] = b64_chr[ s[2]&0x3F ]; + j=0; k+=4; + } + } + + if (j) { + if (j==1) + s[1] = 0; + out[k+0] = b64_chr[ (s[0]&255)>>2 ]; + out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ]; + if (j==2) + out[k+2] = b64_chr[ ((s[1]&0x0F)<<2) ]; + else + out[k+2] = '='; + out[k+3] = '='; + k+=4; + } + + out[k] = '\0'; + + return k; +} + +unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned char* out) { + + unsigned int i=0, j=0, k=0, s[4]; + + for (i=0;i>4); + if (s[2]!=64) { + out[k+1] = ((s[1]&0x0F)<<4)+((s[2]&0x3C)>>2); + if ((s[3]!=64)) { + out[k+2] = ((s[2]&0x03)<<6)+(s[3]); k+=3; + } else { + k+=2; + } + } else { + k+=1; + } + j=0; + } + } + return k; +} + +int test(){ + unsigned char in_buff[100] = "ab\0d\0fghi"; + unsigned char out_buff[100]; + unsigned char *in = in_buff; + unsigned char *out = out_buff; + int in_len = 10; + int out_len = b64_encode(in, in_len, out); + printf("encode: out_len = %d\n", out_len); + for(int i = 0; i < out_len; i++){ + printf("%c ", out[i]); + } + printf("\n"); + std::swap(in, out); + in_len = out_len; + out_len = b64_decode(in, in_len, out); + printf("decode: out_len = %d\n", out_len); + for(int i = 0; i < out_len; i++){ + printf("%c ", out[i]); + } + printf("\n"); + return 0; +} + +int main(){ + test(); +} \ No newline at end of file diff --git a/DataSet/FeatureExtract/entry/src/sslparse_entry.cpp b/DataSet/FeatureExtract/entry/src/sslparse_entry.cpp new file mode 100644 index 0000000..024f878 --- /dev/null +++ b/DataSet/FeatureExtract/entry/src/sslparse_entry.cpp @@ -0,0 +1,641 @@ + +#include "base_utils.h" +#include "ssl_utils.h" +#include "MESA/stream_inc/stream_base.h" +#include "MESA/stream_inc/stream_rawpkt.h" +#include "cjson/cJSON.h" +#include "openssl/x509.h" +#include "base64.h" +#include +#define STREAM_PACKET_COUNT_MAX 10000 +#define TLS_MESSAGE_LEN_MAX 20000 + +void *g_logger = NULL; +FILE *g_fp = NULL; + +struct tls_message_type{ + int message_type; + int content_type; + int handshake_type; + const char *name; +}; + +struct tls_message_type g_tls_types[] = { + {0, 22, 0, "hello_request_RESERVED"}, + {1, 22, 1, "client_hello"}, + {2, 22, 2, "server_hello"}, + {3, 22, 3, "hello_verify_request_RESERVED"}, + {4, 22, 4, "new_session_ticket"}, + {5, 22, 5, "end_of_early_data"}, + {6, 22, 6, "hello_retry_request_RESERVED"}, + {7, 22, 8, "encrypted_extensions"}, + {8, 22, 11, "certificate"}, + {9, 22, 12, "server_key_exchange_RESERVED"}, + {10, 22, 13, "certificate_request"}, + {11, 22, 14, "server_hello_done_RESERVED"}, + {12, 22, 15, "certificate_verify"}, + {13, 22, 16, "client_key_exchange_RESERVED"}, + {14, 22, 20, "finished"}, + {15, 22, 21, "certificate_url_RESERVED"}, + {16, 22, 22, "certificate_status_RESERVED"}, + {17, 22, 23, "supplemental_data_RESERVED"}, + {18, 22, 24, "key_update"}, + {19, 22, 25, "compressed_certificate"}, + {20, 22, 254, "message_hash"}, + {21, 20, 0, "change_cipher_spec"}, + {22, 21, 0, "alert"}, + {23, 23, 0, "application_data"}, + {24, 24, 0, "heartbeat"}, + {25, 25, 0, "tls12_cid"}, + {26, 22, -1, "handshake_unknown"}, +}; + +struct tls_message_detail{ + int type; + int len; + unsigned char buff[TLS_MESSAGE_LEN_MAX]; + int buff_len; +}; + +struct tls_filtered_message{ + unsigned char buff[TLS_MESSAGE_LEN_MAX]; + int buff_len; +}; + +struct pkt_parsed_info{ + addr_type_t addr_type; + union{ + struct iphdr *v4; + struct ip6_hdr *v6; + }iphdr; + uint16_t iphdr_len; + uint16_t ip_totlen; + struct tcphdr *tcphdr; + uint16_t tcphdr_len; + char *data; + uint16_t data_len; +}; + +struct pme_info{ + int _errno; + char sip[INET_ADDRSTRLEN]; + int sport; + char dip[INET_ADDRSTRLEN]; + int dport; + struct ssl_chello chello; + struct tls_message_detail cur_c2s_tls; + struct tls_message_detail cur_s2c_tls; + struct tls_filtered_message message_client_hello; + struct tls_filtered_message message_client_hello_no_extensions; + struct tls_filtered_message message_server_hello; + struct tls_filtered_message message_server_hello_no_extensions; + struct tls_filtered_message message_certificate; + struct tls_filtered_message message_certificate_no_serial; + int has_fin_rst; +}; + +int ipv4_header_parse(const void *a_packet, struct pkt_parsed_info* pktinfo){ + if(a_packet == NULL){ + return -1; + } + pktinfo->addr_type = ADDR_TYPE_IPV4; + pktinfo->iphdr.v4 = (struct iphdr*)a_packet; + pktinfo->iphdr_len = pktinfo->iphdr.v4->ihl * 4; + pktinfo->ip_totlen = ntohs(pktinfo->iphdr.v4->tot_len); + pktinfo->tcphdr = (struct tcphdr*)((char*)pktinfo->iphdr.v4 + pktinfo->iphdr_len); + pktinfo->tcphdr_len = pktinfo->tcphdr->doff * 4; + pktinfo->data = (char*)pktinfo->tcphdr + pktinfo->tcphdr_len; + pktinfo->data_len = pktinfo->ip_totlen - pktinfo->iphdr_len - pktinfo->tcphdr_len; + /* + struct iphdr *_iphdr = pktinfo->iphdr.v4; + int ttl = _iphdr->ttl; + int ipid = ntohs(_iphdr->id); + printf("ipv4: ipid = %02x, ttl = %d, data_len = %d\n", ipid, ttl, pktinfo->data_len); + */ + return 0; +} + + +int chello_packet_parse(struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){ + enum chello_parse_result chello_status = CHELLO_PARSE_INVALID_FORMAT; + char *buff = pktinfo->data; + int len = pktinfo->data_len; + ssl_chello_parse(&(pmeinfo->chello), (const unsigned char*)buff, len, &chello_status); + if(chello_status != CHELLO_PARSE_SUCCESS){ + LOG_ERROR(g_logger, "Error: chello parse failed\n"); + return -1; + } + return 0; +} + +int get_tls_message_type(int content_type, int handshake_type){ + int type_count = sizeof(g_tls_types) / sizeof(struct tls_message_type); + for(int i = 0; i < type_count; i++){ + if(g_tls_types[i].content_type == content_type && g_tls_types[i].handshake_type == handshake_type){ + return i; + } + } + if(content_type == 22){ + return type_count - 1; + } + return -1; +} + +int client_server_hello_get(unsigned char *buff, int len, struct pme_info *pmeinfo, int type){ + char buff1[TLS_MESSAGE_LEN_MAX]; + int i = 0, len1 = 0; + memcpy(buff1 + len1, buff + i, 6); + i += 6; + len1 += 6; + //random + i += 32; + //session_id + int session_id_len = (uint8_t)buff[i]; + i += (1 + session_id_len); + //cipher suites: type = 1, client hello; type = 2, server hello + if(type == 1){ + int cipher_suites_len = (uint16_t)(buff[i] << 8) + (uint8_t)buff[i + 1]; + memcpy(buff1 + len1, buff + i, 2 + cipher_suites_len); + i += (2 + cipher_suites_len); + len1 += (2 + cipher_suites_len); + } + if(type == 2){ + memcpy(buff1 + len1, buff + i, 2); + i += 2; + len1 += 2; + } + //compression methods + int compression_methods_len = (uint8_t)buff[i]; + memcpy(buff1 + len1, buff + i, 1 + compression_methods_len); + i += (1 + compression_methods_len); + len1 += (1 + compression_methods_len); + int extensions_index = len1; + //extensions + int extensions_len = (uint16_t)(buff[i] << 8) + (uint8_t)buff[i + 1]; + memcpy(buff1 + len1, buff + i, 2); + i += 2; + len1 += 2; + int i1 = i; + for(; i + 3 < i1 + extensions_len;){ + int type = (uint16_t)(buff[i] << 8) + (uint8_t)buff[i + 1]; + int extension_len = (uint16_t)(buff[i + 2] << 8) + (uint8_t)buff[i + 3]; + if(type == 21){ + i += (4 + extension_len); + continue; + } + memcpy(buff1 + len1, buff + i, 4 + extension_len); + i += (4 + extension_len); + len1 += (4 + extension_len); + } + if(len1 > len){ + return -1; + } + if(type == 1){ + memcpy(pmeinfo->message_client_hello.buff, buff1, len1); + pmeinfo->message_client_hello.buff_len = len1; + memcpy(pmeinfo->message_client_hello_no_extensions.buff, buff1, extensions_index); + pmeinfo->message_client_hello_no_extensions.buff_len = extensions_index; + } + if(type == 2){ + memcpy(pmeinfo->message_server_hello.buff, buff1, len1); + pmeinfo->message_server_hello.buff_len = len1; + memcpy(pmeinfo->message_server_hello_no_extensions.buff, buff1, extensions_index); + pmeinfo->message_server_hello_no_extensions.buff_len = extensions_index; + } + return 0; +} + +int client_hello_get(struct pme_info* pmeinfo, unsigned char *buff, int len){ + int ret = client_server_hello_get(buff, len, pmeinfo, 1); + if(ret < 0){ + LOG_ERROR(g_logger, "Invalid client hello"); + return -1; + } + /* + printf("client_hello, buff_len = %d\n", pmeinfo->message_client_hello.buff_len); + for(int i = 0; i < pmeinfo->message_client_hello.buff_len; i++){ + printf("%02x ", (uint8_t)pmeinfo->message_client_hello.buff[i]); + } + printf("\n"); + printf("client_hello_no_extensions, buff_len = %d\n", pmeinfo->message_client_hello_no_extensions.buff_len); + for(int i = 0; i < pmeinfo->message_client_hello_no_extensions.buff_len; i++){ + printf("%02x ", (uint8_t)pmeinfo->message_client_hello_no_extensions.buff[i]); + } + printf("\n"); + */ + return 0; +} + +int server_hello_get(struct pme_info* pmeinfo, unsigned char *buff, int len){ + int ret = client_server_hello_get(buff, len, pmeinfo, 2); + if(ret < 0){ + LOG_ERROR(g_logger, "Invalid server hello"); + return -1; + } + /* + printf("server_hello, buff_len = %d\n", pmeinfo->message_server_hello.buff_len); + for(int i = 0; i < pmeinfo->message_server_hello.buff_len; i++){ + printf("%02x ", (uint8_t)pmeinfo->message_server_hello.buff[i]); + } + printf("\n"); + printf("server_hello_no_extensions, buff_len = %d\n", pmeinfo->message_server_hello_no_extensions.buff_len); + for(int i = 0; i < pmeinfo->message_server_hello_no_extensions.buff_len; i++){ + printf("%02x ", (uint8_t)pmeinfo->message_server_hello_no_extensions.buff[i]); + } + printf("\n"); + */ + return 0; +} + +int get_public_key(X509 *cert, unsigned char *public_key){ + //printf("call get_public_key\n"); + int public_key_len = 0; + EVP_PKEY *pkey = X509_get_pubkey(cert); + if(pkey == NULL){ + return -1; + } + unsigned char *p = NULL; + public_key_len = i2d_PUBKEY(pkey, &p); + public_key_len -= 24; + memcpy(public_key, p + 24, public_key_len); + /* + printf("public_key_len = %d\n", public_key_len); + for(int i = 0; i < public_key_len; i++){ + printf("%02x ", public_key[i]); + } + printf("\n"); + */ + EVP_PKEY_free(pkey); + return public_key_len; +} + +int find_sub_block(unsigned char *s1, int len1, unsigned char *s2, int len2){ + for(int i = 0; i + len2 < len1; i++){ + int j; + for(j = 0; j < len2; j++){ + if(s1[i + j] != s2[j]){ + break; + } + } + if(j == len2){ + return i; + } + } + return -1; +} + +int strip_data_from_buff(unsigned char *input, int input_len, int begin, int end, unsigned char *output){ + int output_len = 0; + memcpy(output + output_len, input, begin); + output_len += begin; + memcpy(output + output_len, input + end, input_len - end); + output_len += (input_len - end); + return output_len; +} + +int strip_encrypted_data(unsigned char *input, int input_len, unsigned char *output){ + int encrypted_data_begin = input_len - 24; + int encrypted_data_end = input_len; + return strip_data_from_buff(input, input_len, encrypted_data_begin, encrypted_data_end, output); +} + +int strip_public_key(X509 *cert, unsigned char *input, int input_len, unsigned char *output){ + unsigned char public_key[TLS_MESSAGE_LEN_MAX]; + int public_key_len = get_public_key(cert, public_key); + if(public_key_len < 0){ + return -1; + } + int public_key_begin = find_sub_block(input, input_len, public_key, public_key_len); + //printf("public key begin = %d\n", public_key_begin); + if(public_key_begin < 0){ + return -1; + } + int public_key_end = public_key_begin + public_key_len; + return strip_data_from_buff(input, input_len, public_key_begin, public_key_end, output); +} + + +int get_serial_number(X509 *cert, unsigned char *serial_number){ + ASN1_INTEGER *serial = X509_get_serialNumber(cert); + BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); + int len = BN_num_bytes(bn); + BN_bn2bin(bn, serial_number); + /* + printf("serial number len = %d\n", len); + for(int i = 0; i < len; i++){ + printf("%02x ", serial_number[i]); + } + printf("\n"); + */ + return len; +} + +int strip_serial_number(X509 *cert, unsigned char *input, int input_len, unsigned char *output){ + unsigned char serial_number[TLS_MESSAGE_LEN_MAX]; + int serial_number_len = get_serial_number(cert, serial_number); + if(serial_number_len < 0){ + return -1; + } + int serial_number_begin = find_sub_block(input, input_len, serial_number, serial_number_len); + //printf("serial number begin = %d\n", serial_number_begin); + if(serial_number_begin < 0){ + return -1; + } + int serial_number_end = serial_number_begin + serial_number_len; + return strip_data_from_buff(input, input_len, serial_number_begin, serial_number_end, output); +} + +int certificate_get(struct pme_info* pmeinfo, unsigned char *buff, int len){ + //printf("call certificate_get\n"); + if(10 > len){ + return -1; + } + int cert_len = (buff[7] << 16) + (buff[8] << 8) + buff[9]; + int i = 10; + if(i + cert_len > len){ + return -1; + } + unsigned char cert_buff[TLS_MESSAGE_LEN_MAX]; + memcpy(cert_buff, buff + i, cert_len); + const unsigned char *p = cert_buff; + X509 *cert = d2i_X509(NULL, &p, cert_len); + if(cert == NULL){ + return -1; + } + unsigned char buff1[TLS_MESSAGE_LEN_MAX]; + unsigned char *input = cert_buff; + int input_len = cert_len; + unsigned char *output = buff1; + int output_len = 0; + output_len = strip_public_key(cert, input, input_len, output); + std::swap(output, input); + input_len = output_len; + output_len = strip_encrypted_data(input, input_len, output); + if(output_len >= 0){ + memcpy(pmeinfo->message_certificate.buff, output, output_len); + pmeinfo->message_certificate.buff_len = output_len; + } + std::swap(output, input); + input_len = output_len; + output_len = strip_serial_number(cert, input, input_len, output); + if(output_len >= 0){ + memcpy(pmeinfo->message_certificate_no_serial.buff, output, output_len); + pmeinfo->message_certificate_no_serial.buff_len = output_len; + } + X509_free(cert); + return 0; +} + +int tls_header_parse(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){ + int i = 0, len = pktinfo->data_len; + int curdir = stream->curdir; + struct tls_message_detail *cur_tls = NULL; + if(curdir == 1){ + cur_tls = &(pmeinfo->cur_c2s_tls); + } + if(curdir == 2){ + cur_tls = &(pmeinfo->cur_s2c_tls); + } + int cp_len = 0; + while(i < len){ + if(cur_tls->buff_len < 5){ + cp_len = MIN(5 - cur_tls->buff_len, len - i); + memcpy(cur_tls->buff + cur_tls->buff_len, pktinfo->data + i, cp_len); + cur_tls->buff_len += cp_len; + i += cp_len; + if(cur_tls->buff_len < 5){ + break; + } + } + int content_type = cur_tls->buff[0]; + if(content_type == 0x16){ + if(cur_tls->buff_len < 6){ + cp_len = MIN(1, len - i); + memcpy(cur_tls->buff + cur_tls->buff_len, pktinfo->data + i, cp_len); + cur_tls->buff_len += cp_len; + i += cp_len; + if(cur_tls->buff_len < 6){ + break; + } + } + } + int handshake_type = 0; + if(content_type == 0x16){ + handshake_type = cur_tls->buff[5]; + } + int message_type = get_tls_message_type(content_type, handshake_type); + cur_tls->type = message_type; + cur_tls->len = (uint16_t)(cur_tls->buff[3] << 8) + (uint8_t)cur_tls->buff[4]; + if(message_type < 0){ + LOG_ERROR(g_logger, "message_type unknown, content_type = %d, handshake_type = %d", content_type, handshake_type); + memset(cur_tls, 0, sizeof(*cur_tls)); + break; + } + cp_len = MIN(cur_tls->len + 5 - cur_tls->buff_len, len - i); + //client hello, server hello, certificate + if(message_type == 1 || message_type == 2 || message_type == 8){ + memcpy(cur_tls->buff + cur_tls->buff_len, pktinfo->data + i, cp_len); + } + cur_tls->buff_len += cp_len; + i += cp_len; + if(cur_tls->len + 5 == cur_tls->buff_len){ + if(message_type == 1 || message_type == 2 || message_type == 8){ + switch (message_type){ + case 1: + client_hello_get(pmeinfo, cur_tls->buff + 5, cur_tls->len); + break; + case 2: + server_hello_get(pmeinfo, cur_tls->buff + 5, cur_tls->len); + break; + case 8: + certificate_get(pmeinfo, cur_tls->buff + 5, cur_tls->len); + break; + default: + break; + } + } + memset(cur_tls, 0, sizeof(*cur_tls)); + } + } + return 0; +} + + + +int packet_need_filter(struct pkt_parsed_info *pktinfo){ + struct iphdr *_iphdr = pktinfo->iphdr.v4; + int ttl = _iphdr->ttl; + if(ttl == 70 || ttl == 75){ + //printf("packet_need_filter: ret = 1, ttl = %d\n", ttl); + return 1; + } + int data_len = pktinfo->data_len; + if(data_len == 0){ + //printf("packet_need_filter: ret 1, data_len = %d\n", data_len); + return 1; + } + return 0; +} + +char pending_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){ + //printf("call pending_opstate\n"); + struct tcphdr *_tcphdr = pktinfo->tcphdr; + if(_tcphdr->fin || _tcphdr->rst){ + pmeinfo->has_fin_rst = 1; + } + struct stream_tuple4_v4 *tuple4 = stream->addr.tuple4_v4; + inet_ntop(AF_INET, &(tuple4->saddr), pmeinfo->sip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(tuple4->daddr), pmeinfo->dip, INET_ADDRSTRLEN); + pmeinfo->sport = ntohs(tuple4->source); + pmeinfo->dport = ntohs(tuple4->dest); + if(packet_need_filter(pktinfo) == 1){ + return APP_STATE_FAWPKT | APP_STATE_GIVEME; + } + int ret = chello_packet_parse(pmeinfo, pktinfo); + if(ret < 0){ + pmeinfo->_errno = -1; + return APP_STATE_FAWPKT | APP_STATE_DROPME; + } + tls_header_parse(stream, pmeinfo, pktinfo); + return APP_STATE_FAWPKT | APP_STATE_GIVEME; +} + +char data_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){ + struct tcphdr *_tcphdr = pktinfo->tcphdr; + if(_tcphdr->fin || _tcphdr->rst){ + pmeinfo->has_fin_rst = 1; + } + if(packet_need_filter(pktinfo) == 0){ + tls_header_parse(stream, pmeinfo, pktinfo); + } + return APP_STATE_FAWPKT | APP_STATE_GIVEME; +} + +void time_tostring(struct timeval tv, char *buf, int buflen){ + char tmbuf[64]; + time_t nowtime; + struct tm *nowtm; + nowtime = tv.tv_sec; + //printf("nowtime = %lld\n", nowtime); + nowtm = localtime(&nowtime); + strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm); + snprintf(buf, buflen, "%s.%06ld", tmbuf, tv.tv_usec); + return; +} + +void print_tls_message(struct tls_filtered_message *message, const char *name){ + int len = message->buff_len; + printf("%s: len = %d, data = \n", name, len); + for(int i = 0; i < len; i++){ + printf("%02x ", message->buff[i]); + } + printf("\n"); +} + +void cjson_add_tls_message(cJSON *log_obj, struct tls_filtered_message *message, const char *tls_message_name){ + //print_tls_message(message, tls_message_name); + unsigned char out_buff[TLS_MESSAGE_LEN_MAX]; + int out_len = b64_encode((const unsigned char*)message->buff, message->buff_len, out_buff); + if(out_len > 0){ + memcpy(message->buff, out_buff, out_len); + message->buff_len = out_len; + cJSON *tls_message = cJSON_CreateObject(); + cJSON_AddStringToObject(tls_message, "data", (char*)message->buff); + cJSON_AddNumberToObject(tls_message, "len", message->buff_len); + cJSON_AddItemToObject(log_obj, tls_message_name, tls_message); + } + return; +} + +void output_result(struct pme_info *pmeinfo){ + if(pmeinfo->has_fin_rst == 0){ + printf("not have fin or rst\n"); + return; + } + cJSON *log_obj = cJSON_CreateObject(); + cJSON_AddStringToObject(log_obj, "sip", pmeinfo->sip); + cJSON_AddNumberToObject(log_obj, "sport", pmeinfo->sport); + cJSON_AddStringToObject(log_obj, "dip", pmeinfo->dip); + cJSON_AddNumberToObject(log_obj, "dport", pmeinfo->dport); + cJSON_AddStringToObject(log_obj, "proto", "tcp"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_client_hello), "client_hello"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_client_hello_no_extensions), "client_hello_no_extensions"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_server_hello), "server_hello"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_server_hello_no_extensions), "server_hello_no_extensions"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_certificate), "certificate"); + cjson_add_tls_message(log_obj, &(pmeinfo->message_certificate_no_serial), "certificate_no_serial"); + char *log_msg = cJSON_PrintUnformatted(log_obj); + //printf("%s\n\n", log_msg); + fputs(log_msg, g_fp); + fputs("\n", g_fp); + cJSON_Delete(log_obj); + cJSON_free(log_msg); +} + +char close_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo, const void *a_packet){ + if(a_packet != NULL){ + struct tcphdr *_tcphdr = pktinfo->tcphdr; + if(_tcphdr->fin || _tcphdr->rst){ + pmeinfo->has_fin_rst = 1; + } + if(packet_need_filter(pktinfo) == 0){ + tls_header_parse(stream, pmeinfo, pktinfo); + } + } + return APP_STATE_FAWPKT | APP_STATE_DROPME; +} + +void pme_info_destroy(struct pme_info *pmeinfo){ + FREE(&pmeinfo); + pmeinfo = NULL; +} + +extern "C" char sslparse_entry(struct streaminfo *stream, void** pme, int thread_seq, const void* a_packet){ + //printf("call sslparse_entry\n"); + char ret; + struct pme_info *pmeinfo = *(struct pme_info **)pme; + //printf("pmeinfo = %p, opstate = %d, a_packet = %p\n", pmeinfo, stream->opstate, a_packet); + if(a_packet == NULL && stream->opstate != OP_STATE_CLOSE){ + return APP_STATE_FAWPKT | APP_STATE_GIVEME; + } + struct pkt_parsed_info pktinfo; + memset(&pktinfo, 0, sizeof(pktinfo)); + ipv4_header_parse(a_packet, &pktinfo); + switch(stream->opstate){ + case OP_STATE_PENDING: + //printf("call pending\n"); + pmeinfo = ALLOC(struct pme_info, 1); + *pme = pmeinfo; + ret = pending_opstate(stream, pmeinfo, &pktinfo); + break; + case OP_STATE_DATA: + //printf("call data\n"); + ret = data_opstate(stream, pmeinfo, &pktinfo); + break; + case OP_STATE_CLOSE: + //printf("call close\n"); + ret = close_opstate(stream, pmeinfo, &pktinfo, a_packet); + break; + default: + break; + } + if((ret & APP_STATE_DROPME)){ + if(pmeinfo->_errno >= 0){ + output_result(pmeinfo); + } + pme_info_destroy(pmeinfo); + } + return ret; +} + +extern "C" int sslparse_init(){ + char *log_path = (char*)"./ssl_parse_stat.log"; + int log_level = 10; + g_logger = MESA_create_runtime_log_handle(log_path, log_level); + g_fp = fopen("./ssl_parse_stat.txt", "a+"); + return 0; +} + +extern "C" void sslparse_destroy(){ + +} diff --git a/DataSet/FeatureExtract/vendor/CMakeLists.txt b/DataSet/FeatureExtract/vendor/CMakeLists.txt index dd1ec67..c9290a8 100644 --- a/DataSet/FeatureExtract/vendor/CMakeLists.txt +++ b/DataSet/FeatureExtract/vendor/CMakeLists.txt @@ -3,6 +3,36 @@ include(ExternalProject) + +include(ExternalProject) + +### OpenSSL 1.1.1 +ExternalProject_Add(OpenSSL PREFIX openssl + URL ${CMAKE_CURRENT_SOURCE_DIR}/openssl-1.1.1.tar.gz + URL_MD5 d65944e4aa4de6ad9858e02c82d85183 + CONFIGURE_COMMAND ./Configure enable-ssl3 enable-ssl3-method enable-weak-ssl-ciphers linux-x86_64 --prefix= --openssldir=/lib/ssl + enable-ec_nistp_64_gcc_128 no-shared + BUILD_COMMAND ${MAKE_COMMAND} + INSTALL_COMMAND make install_sw + BUILD_IN_SOURCE 1) + +ExternalProject_Get_Property(OpenSSL INSTALL_DIR) +set(OPENSSL_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) +set(OPENSSL_LINK_DIRECTORIES ${INSTALL_DIR}/lib) +set(OPENSSL_PKGCONFIG_PATH ${INSTALL_DIR}/lib/pkgconfig/) +file(MAKE_DIRECTORY ${INSTALL_DIR}/include) + +add_library(openssl-crypto-static STATIC IMPORTED GLOBAL) +add_dependencies(openssl-crypto-static OpenSSL) +set_property(TARGET openssl-crypto-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libcrypto.a) +set_property(TARGET openssl-crypto-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) + +add_library(openssl-ssl-static STATIC IMPORTED GLOBAL) +add_dependencies(openssl-ssl-static OpenSSL) +set_property(TARGET openssl-ssl-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libssl.a) +set_property(TARGET openssl-ssl-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) + + ### cJSON: 注意: -DCMAKE_POSITION_INDEPENDENT_CODE=ON ExternalProject_Add(cJSON PREFIX cJSON URL ${CMAKE_CURRENT_SOURCE_DIR}/cJSON-1.7.7.tar.gz diff --git a/DataSet/FeatureExtract/vendor/openssl-1.1.1.tar.gz b/DataSet/FeatureExtract/vendor/openssl-1.1.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..ceeca12fa95a98f124d4fd8884bca56ebc8b1be9 GIT binary patch literal 11266843 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