summaryrefslogtreecommitdiff
path: root/demo/demo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demo/demo.cpp')
-rw-r--r--demo/demo.cpp257
1 files changed, 257 insertions, 0 deletions
diff --git a/demo/demo.cpp b/demo/demo.cpp
new file mode 100644
index 0000000..e69845b
--- /dev/null
+++ b/demo/demo.cpp
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "gquic_process.h"
+#include "quic_analysis.h"
+#include "parser_quic.h"
+
+static int check_length(int last_len, int field_len)
+{
+ return ((last_len-field_len>0) ? 1 : 0);
+}
+
+
+int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread_seq)
+{
+ if(tlv->value==NULL && len>0)
+ {
+ tlv->value=(char *)calloc(1, len+1);
+ memset(tlv->value, 0, len+1);
+ tlv->length=len;
+ tlv->type=type;
+ memcpy(tlv->value, start_pos, tlv->length);
+ }
+
+ return 0;
+}
+
+static int get_value(unsigned char *payload, int *offset, int len)
+{
+ switch(len)
+ {
+ case 1:
+ return (int)(payload[(*offset)++]);
+ break;
+ case 2:
+ (*offset)+=len;
+ return (int)ntohs(*(unsigned short *)(payload+*offset-len));
+ break;
+ case 3:
+ (*offset)+=len;
+ return ((int)*(payload-2+*offset)<<16|
+ (int)*(payload-1+*offset)<<8|
+ (int)*(payload+*offset)<<0);
+ break;
+ case 4:
+ (*offset)+=len;
+ return (int)ntohl(*(unsigned int *)(payload+*offset-len));
+ break;
+ case 32:
+ (*offset)+=len;
+ return 0;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int parse_encrypt_parameter(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
+{
+ int used_len=0,length=0;
+ while(payload_len>used_len)
+ {
+ if(payload[used_len]> 0x00 && payload[used_len]<=0x20)
+ {
+ get_value(payload, &used_len, 1); //type=1
+ length=get_value(payload, &used_len, 1); // length=1
+ used_len+=length;
+
+ continue;
+ }
+
+ if((*(unsigned short *)(payload+used_len)) == htons(EXT_QUIC_PARAM_USER_AGENT))
+ {
+ quic_stream->ua_idx=quic_stream->ext_tag_num++;
+ get_value(payload, &used_len, 2); //type=2
+ length=get_value(payload, &used_len, 1); // length=1
+ get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ua_idx]), length, EXT_QUIC_PARAM_USER_AGENT, thread_seq);
+ used_len+=length;
+
+ continue;
+ }
+
+ if(*(unsigned int *)(payload+used_len) == htonl(EXT_QUIC_PARAM_QUIC_VERSION))
+ {
+ quic_stream->ver_idx=quic_stream->ext_tag_num++;
+ get_value(payload, &used_len, 4); //type=4
+ length=get_value(payload, &used_len, 1); // length=1
+ get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ver_idx]), length, EXT_QUIC_PARAM_QUIC_VERSION, thread_seq);
+ *(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value=(unsigned int)htonl(*(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value);
+ used_len+=length;
+
+ continue;
+ }
+
+ if((*(unsigned int *)(payload+used_len))== htonl(EXT_QUIC_PARAM_GREASE_HIGH4) && (*(unsigned int *)(payload+used_len+4))== htonl(EXT_QUIC_PARAM_GREASE_LOW4))
+ {
+ used_len+=8; //type=8
+ length=get_value(payload, &used_len, 1); // length=1
+ used_len+=length;
+
+ continue;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+int parse_encrypt_server_name(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
+{
+ int ext_len=0,used_len=0;
+
+ quic_stream->sni_idx=quic_stream->ext_tag_num++;
+ get_value(payload, &used_len, 2); //Server Name List length
+ if(get_value(payload, &used_len, 1)==0) //Server Name type
+ {
+ ext_len=get_value(payload, &used_len, 2); //Server Name length
+ get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->sni_idx]), ext_len, EXTENSION_SERVER_NAME, thread_seq);
+ }
+
+ return 1;
+}
+
+int parse_encrypt_client_hello(void *pstream, struct _quic_stream *quic_stream, void *a_packet, unsigned char *payload, int payload_len)
+{
+ int used_len=0;
+ int flags=0;
+ int skip_len=0,client_hello_len=0;
+ int ext_type=0, extension_total_len=0;
+
+ get_value(payload, &used_len, 1); //handshake type
+ client_hello_len=get_value(payload, &used_len, 3); //client hello length
+ get_value(payload, &used_len, 2); //ssl_version
+
+ get_value(payload, &used_len, 32); //Random
+
+ skip_len=(int)get_value(payload, &used_len, 1); //Session ID length
+ if(!check_length(payload_len-used_len, skip_len))
+ {
+ return flags;
+ }
+ used_len+=skip_len;
+
+ skip_len=(int)get_value(payload, &used_len, 2); //Ciper Suites length
+ if(!check_length(payload_len-used_len, skip_len))
+ {
+ return flags;
+ }
+ used_len+=skip_len;
+
+ skip_len=(int)get_value(payload, &used_len, 1); //Compression Methods
+ if(!check_length(payload_len-used_len, skip_len))
+ {
+ return flags;
+ }
+ used_len+=skip_len;
+
+ extension_total_len=(int)get_value(payload, &used_len, 2); //Extension length
+ if(!check_length(payload_len-used_len, extension_total_len))
+ {
+ return flags;
+ }
+
+ quic_stream->ext_tags=(quic_tlv_t *)calloc(1, sizeof(quic_tlv_t)*3);
+ memset(quic_stream->ext_tags, 0, sizeof(quic_tlv_t)*3);
+
+ while(extension_total_len>used_len)
+ {
+ ext_type=get_value(payload, &used_len, 2); //Extension type
+ skip_len=get_value(payload, &used_len, 2); //length
+ if(!check_length(payload_len-used_len, skip_len) || skip_len==0)
+ {
+ return flags;
+ }
+
+ switch(ext_type)
+ {
+ case EXTENSION_SERVER_NAME:
+ parse_encrypt_server_name(quic_stream, payload+used_len, skip_len, 0);
+ flags=1;
+ break;
+ case EXTENSION_QUIC_PARAM:
+ parse_encrypt_parameter(quic_stream, payload+used_len, skip_len, 0);
+ break;
+ case EXTENSION_SUPPORT_GROUP:
+ case EXTENSION_APP_PROT_NEGO:
+ case EXTENSION_SIG_ALGORITHM:
+ case EXTENSION_KEY_SHARE:
+ case EXTENSION_PSK_EXCHANGE:
+ case EXTENSION_SUPP_SSL_VER:
+ case EXTENSION_COMPRESS_CERT:
+ break;
+ default:
+ break;
+ }
+
+ used_len+=skip_len;
+ }
+
+ return flags;
+}
+
+
+int main(int argc, char *argv[])
+{
+ if(argc<1)
+ {
+ return -1;
+ }
+
+ struct stat statbuf;
+ if (stat(argv[1], &statbuf) == -1)
+ {
+ return -1;
+ }
+
+ unsigned char *payload=(unsigned char *)calloc(1, statbuf.st_size);
+ FILE *fp=fopen(argv[1], "rb");
+ if(fp)
+ {
+ int size=fread(payload, 1, 1315, fp);
+ assert(size==1315);
+ //assert(size==statbuf.st_size);
+
+ struct _quic_stream * quic_stream=(struct _quic_stream *)calloc(1, sizeof(struct _quic_stream));
+ parse_encrypt_client_hello(NULL, quic_stream, NULL, payload+4, 1314)-4;
+
+ fclose(fp);
+ fp=NULL;
+
+ free(quic_stream);
+ quic_stream=NULL;
+
+ free(payload);
+ payload=NULL;
+
+ }
+
+ return 0;
+}