Feature: server hello decode
This commit is contained in:
@@ -240,10 +240,6 @@ void ssl_handshake_server_key_exchange_decode()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssl_handshake_server_hello_decode()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ssl_read_u8(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint8_t *value)
|
int32_t ssl_read_u8(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint8_t *value)
|
||||||
{
|
{
|
||||||
@@ -261,22 +257,6 @@ int32_t ssl_read_u8(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint8
|
|||||||
return SSL_DECODER_TRUE;
|
return SSL_DECODER_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ssl_read_le_u16(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint16_t *value)
|
|
||||||
{
|
|
||||||
if(pdata_sz<(*pdata_offset)+2)
|
|
||||||
{
|
|
||||||
return SSL_DECODER_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(value!=NULL)
|
|
||||||
{
|
|
||||||
memcpy((uint8_t *)value, pdata+(*pdata_offset), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*pdata_offset)+=2;
|
|
||||||
return SSL_DECODER_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ssl_read_be_u16(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint16_t *value)
|
int32_t ssl_read_be_u16(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset, uint16_t *value)
|
||||||
{
|
{
|
||||||
if(pdata_sz<(*pdata_offset)+2)
|
if(pdata_sz<(*pdata_offset)+2)
|
||||||
@@ -420,6 +400,85 @@ int32_t ssl_server_name_decode(struct ssl_decoder_ltv *sni, uint8_t *pdata, uint
|
|||||||
return SSL_DECODER_TRUE;
|
return SSL_DECODER_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ssl_server_hello *ssl_handshake_server_hello_decode(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset)
|
||||||
|
{
|
||||||
|
int32_t total_len; //3
|
||||||
|
int32_t ret=ssl_read_be_u24(pdata, pdata_sz, pdata_offset, (uint8_t *)&(total_len));
|
||||||
|
if(total_len<0) /*CLIENT_HELLO_HDRLEN: 4 means client_type+len*/
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_server_hello *shello=(struct ssl_server_hello *)CALLOC(struct ssl_server_hello, 1);
|
||||||
|
ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &(shello->version));
|
||||||
|
ssl_read_be_u32(pdata, pdata_sz, pdata_offset, &(shello->random_gmt_time));
|
||||||
|
|
||||||
|
for(int i=1; i<SSL_HELLO_LTV_MAX; i++)
|
||||||
|
{
|
||||||
|
struct ssl_decoder_ltv *ltv=&(shello->ltv[i]);
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case SSL_HELLO_LTV_RANDOM_BYTES:
|
||||||
|
ret=ssl_decoder_random_bytes_get(ltv, SSL_DECODER_NONE, pdata, pdata_sz, pdata_offset);
|
||||||
|
break;
|
||||||
|
case SSL_HELLO_LTV_SESSION:
|
||||||
|
ret=ssl_decoder_ltv_get(ltv, SSL_DECODER_L1V, pdata, pdata_sz, pdata_offset);
|
||||||
|
break;
|
||||||
|
case SSL_HELLO_LTV_CIPERSUITES:
|
||||||
|
shello->ltv[i].lv_u16=2;
|
||||||
|
shello->ltv[i].value=pdata+(*pdata_offset);
|
||||||
|
(*pdata_offset)+=2;
|
||||||
|
break;
|
||||||
|
case SSL_HELLO_LTV_COMPRESS_METHOD:
|
||||||
|
shello->ltv[i].lv_u16=1;
|
||||||
|
shello->ltv[i].value=pdata+(*pdata_offset);
|
||||||
|
(*pdata_offset)+=1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret==SSL_DECODER_FALSE)
|
||||||
|
{
|
||||||
|
FREE(shello);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*get extension*/
|
||||||
|
uint16_t extension_len=0;
|
||||||
|
ret=ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &extension_len);
|
||||||
|
if(ret==SSL_DECODER_FALSE || (extension_len+(*pdata_offset)>pdata_sz))
|
||||||
|
{
|
||||||
|
FREE(shello);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(extension_len==0)
|
||||||
|
{
|
||||||
|
return shello;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t offset=(*pdata_offset);
|
||||||
|
utarray_new(shello->extensions, &UT_ssl_hello_extension_icd);
|
||||||
|
|
||||||
|
for(size_t i=0; pdata_sz>offset && (offset-(*pdata_offset))<extension_len; i++) // min len of ext is 4 byte
|
||||||
|
{
|
||||||
|
struct ssl_decoder_ltv ltv={0};
|
||||||
|
ret=ssl_decoder_ltv_get(<v, SSL_DECODER_L2TV, pdata, pdata_sz, &offset);
|
||||||
|
if(ret==SSL_DECODER_FALSE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
utarray_push_back(shello->extensions, <v);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*pdata_offset)=offset;
|
||||||
|
|
||||||
|
return shello;
|
||||||
|
}
|
||||||
|
|
||||||
struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset)
|
struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_t pdata_sz, size_t *pdata_offset)
|
||||||
{
|
{
|
||||||
int32_t total_len; //3
|
int32_t total_len; //3
|
||||||
@@ -464,7 +523,7 @@ struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_
|
|||||||
/*get extension*/
|
/*get extension*/
|
||||||
uint16_t extension_len=0;
|
uint16_t extension_len=0;
|
||||||
ret=ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &extension_len);
|
ret=ssl_read_be_u16(pdata, pdata_sz, pdata_offset, &extension_len);
|
||||||
if(ret==SSL_DECODER_FALSE)
|
if(ret==SSL_DECODER_FALSE || (extension_len+(*pdata_offset)>pdata_sz))
|
||||||
{
|
{
|
||||||
FREE(chello);
|
FREE(chello);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -475,12 +534,6 @@ struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_
|
|||||||
return chello;
|
return chello;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(extension_len+(*pdata_offset)>pdata_sz)
|
|
||||||
{
|
|
||||||
FREE(chello);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
utarray_new(chello->extensions, &UT_ssl_hello_extension_icd);
|
utarray_new(chello->extensions, &UT_ssl_hello_extension_icd);
|
||||||
|
|
||||||
for(size_t i=0; pdata_sz>(*pdata_offset); i++) // min len of ext is 4 byte
|
for(size_t i=0; pdata_sz>(*pdata_offset); i++) // min len of ext is 4 byte
|
||||||
@@ -523,6 +576,54 @@ struct ssl_client_hello *ssl_handshake_client_hello_decode(uint8_t *pdata, size_
|
|||||||
return chello;
|
return chello;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t ssl_server_hello_ja3s_generate(struct ssl_server_hello *shello)
|
||||||
|
{
|
||||||
|
if(shello==NULL)
|
||||||
|
{
|
||||||
|
return SSL_DECODER_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
UT_string *ja3s_string;
|
||||||
|
utstring_new(ja3s_string);
|
||||||
|
utstring_printf(ja3s_string, "%u,", shello->version);
|
||||||
|
|
||||||
|
int32_t flag=SSL_DECODER_FALSE;
|
||||||
|
size_t offset=0;
|
||||||
|
struct ssl_decoder_ltv *cipher_suites=&(shello->ltv[SSL_HELLO_LTV_CIPERSUITES]);
|
||||||
|
for(; offset<cipher_suites->lv_u16; )
|
||||||
|
{
|
||||||
|
uint16_t cipher_suite=0;
|
||||||
|
ssl_read_be_u16(cipher_suites->value, cipher_suites->lv_u16, &offset, &cipher_suite);
|
||||||
|
if(ssl_is_grease_value(cipher_suite))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_printf(ja3s_string, "%s%u", ((flag==SSL_DECODER_FALSE) ? "" : "-"), cipher_suite);
|
||||||
|
flag=SSL_DECODER_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_printf(ja3s_string, "%s", ",");
|
||||||
|
|
||||||
|
flag=SSL_DECODER_FALSE;
|
||||||
|
for(uint32_t i=0; i<utarray_len(shello->extensions); i++)
|
||||||
|
{
|
||||||
|
struct ssl_decoder_ltv *ext=(struct ssl_decoder_ltv *)utarray_eltptr(shello->extensions, i);
|
||||||
|
if(ext==NULL || ssl_is_grease_value(ext->vtype))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_printf(ja3s_string, "%s%u", ((flag==SSL_DECODER_FALSE) ? "" : "-"), ext->vtype);
|
||||||
|
flag=SSL_DECODER_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_hello_md5sum(&(shello->ja3s), utstring_body(ja3s_string), utstring_len(ja3s_string));
|
||||||
|
utstring_free(ja3s_string);
|
||||||
|
|
||||||
|
return SSL_DECODER_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t ssl_client_hello_ja3_generate(struct ssl_client_hello *chello)
|
int32_t ssl_client_hello_ja3_generate(struct ssl_client_hello *chello)
|
||||||
{
|
{
|
||||||
if(chello==NULL)
|
if(chello==NULL)
|
||||||
@@ -631,6 +732,7 @@ void ssl_handshake_decode(struct ssl_decoder_plugin_env *plugin_env, struct sess
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_client_hello *chello=NULL;
|
struct ssl_client_hello *chello=NULL;
|
||||||
|
struct ssl_server_hello *shello=NULL;
|
||||||
struct ssl_handshake_type *handshake_type=(struct ssl_handshake_type *)(segment_buff+(*segment_buff_offset));
|
struct ssl_handshake_type *handshake_type=(struct ssl_handshake_type *)(segment_buff+(*segment_buff_offset));
|
||||||
(*segment_buff_offset)+=sizeof(struct ssl_handshake_type);
|
(*segment_buff_offset)+=sizeof(struct ssl_handshake_type);
|
||||||
switch(handshake_type->content_type)
|
switch(handshake_type->content_type)
|
||||||
@@ -640,13 +742,14 @@ void ssl_handshake_decode(struct ssl_decoder_plugin_env *plugin_env, struct sess
|
|||||||
ssl_client_hello_ja3_generate(chello);
|
ssl_client_hello_ja3_generate(chello);
|
||||||
break;
|
break;
|
||||||
case SSL_HANDSHAKE_SERVER_HELLO:
|
case SSL_HANDSHAKE_SERVER_HELLO:
|
||||||
ssl_handshake_server_hello_decode();
|
shello=ssl_handshake_server_hello_decode(segment_buff, segment_buff_sz, segment_buff_offset);
|
||||||
|
ssl_server_hello_ja3s_generate(shello);
|
||||||
break;
|
break;
|
||||||
case SSL_HANDSHAKE_CERTIFICATE:
|
case SSL_HANDSHAKE_CERTIFICATE:
|
||||||
ssl_handshake_certificate_decode();
|
// ssl_handshake_certificate_decode();
|
||||||
break;
|
break;
|
||||||
case SSL_HANDSHAKE_SERVER_KEY_EXCHANGE:
|
case SSL_HANDSHAKE_SERVER_KEY_EXCHANGE:
|
||||||
ssl_handshake_server_key_exchange_decode();
|
// ssl_handshake_server_key_exchange_decode();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ struct ssl_server_hello
|
|||||||
uint32_t random_gmt_time;
|
uint32_t random_gmt_time;
|
||||||
|
|
||||||
UT_array *extensions;
|
UT_array *extensions;
|
||||||
struct ssl_decoder_ltv *ja3s;
|
struct ssl_decoder_ltv ja3s;
|
||||||
struct ssl_decoder_ltv ltv[SSL_HELLO_LTV_MAX];
|
struct ssl_decoder_ltv ltv[SSL_HELLO_LTV_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user