📄 sslsniffer.c
字号:
break; case TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST: printf("Certificate request\n"); ProcessCertificateRequest(cur_handshake_packet, ssl_conn); break; case TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE: printf("Server hello done\n"); break; case TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY: printf("Certificate verify\n"); break; case TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE: printf("Client key exchange\n"); ProcessTLSClientKeyExchange(cur_handshake_packet, ssl_conn); break; case TLS_HANDSHAKE_TYPE_FINISHED: printf("Finished Handshake!\n"); break; default: printf("Can't recognise Handshake request type %d!\n",cur_handshake_packet[0]); } /* pull out the content length of the handshake packet and add it to both the bytes processed and also the currentpacket pointer */ handshake_packet_len = ThreeBytesToInt(&(cur_handshake_packet[1])); bytes_processed += handshake_packet_len + TLS_HANDSHAKE_HEADER_SIZE; cur_handshake_packet += handshake_packet_len + TLS_HANDSHAKE_HEADER_SIZE; /* just for formatting reasons */ if(bytes_processed < total_bytes_to_process) { printf("\n"); } }}/* Given the handshake packet containing the Client Hello message, this processes it to obtain the protocol version, session ID and the list of cipher suite that the client can use.*/static void ProcessTLSClientHello(char *buffer){ char *ptr; /* points at cipher suite */ short cipher_suite_len; int i; printf("From Client Hello -- "); ptr = ProcessTLSHello(buffer); memcpy(&cipher_suite_len, ptr, 2); cipher_suite_len = ntohs(cipher_suite_len); printf("Cipher suite length is %d bytes ... number of cipher suites %d\n", cipher_suite_len,cipher_suite_len / 2); ptr += 2; /* advance over the length field of cipher suite */ printf("List of cipher suites are -- \n"); for(i = 0; i < cipher_suite_len; i += 2) ProcessTLSCipherSuite(ptr[i], ptr[i + 1]); }/* Given the handshake packet containing either the ClientHello or ServerHello message, it extracts the protocol version, the session ID which is printed byte by byte in hex and returns the a pointer to the length field of the cipher suite.*/static char *ProcessTLSHello(char *buffer){ char *temp, *ptr = buffer + TLS_HANDSHAKE_HEADER_SIZE; int i; unsigned int byte; /* print out protocol version */ printf("Protocol Version %d.%d\n",(int)ptr[0],(int)ptr[1]); ptr += SESSION_ID_OFFSET; /* skip over random and protocol version field */ /* sesssion ID in a hello record is only max 32 bytes => need 1 byte session ID */ printf("Length of session ID -- %d bytes\n",(int) (*ptr)); /* nothing big enough to hold a number of 32 bytes so just iterate over the chars and print them */ printf("Session ID --\n 0x"); for(i = 0, temp = ptr + 1; i < *ptr; i++, temp++) { byte = 0; memcpy(&byte, temp, 1); printf("%2.2x",byte); } printf("\n"); /* skip over the number of bytes in the session ID field */ ptr += ((*ptr) + 1); /* now pointing at cipher suite */ return ptr;}/* Given the handshake packet containing the Server Hello message, this processes it to obtain the protocol version, session ID and the cipher suite that is to be used.*/static voidProcessServerHello(char *buffer, ssl_connection *ssl_conn){ char *ptr; printf("From Server Hello -- "); ptr = ProcessTLSHello(buffer); /* points at cipher suite */ printf("Cipher Suite is -- \n"); ProcessTLSCipherSuite(ptr[0], ptr[1]); DetermineTLSKeyExchangeAlgorithm(ptr[1], ssl_conn);}/* Examines the bytes given and prints out the cipher suite that is being used.*/static voidProcessTLSCipherSuite(char byte1,char byte2){ char *name; if(byte1 == (char)0xff) { printf(" Hex Code:"); utl_PrintCharAsHex(byte1); utl_PrintCharAsHex(byte2); printf("\n Type: Unknown Cipher Suite\n"); return; } /* done because 0x will only be prefixed to a non zero result. */ printf(" Hex Code:"); utl_PrintCharAsHex(byte1); utl_PrintCharAsHex(byte2); printf("\n Type: "); switch(byte2) { case 0x00: name = "No encryption"; break; case 0x01: name = "RSA with hash function MD5"; break; case 0x02: name = "RSA with SHA"; break; case 0x03: name = "RSA EXPORT with 40 bit RC4 and hash function MD5"; break; case 0x04: name = "RSA with 128 bit RC4 and hash function MD5"; break; case 0x05: name = "RSA with 128 bit RC4 and hash function SHA"; break; case 0x06: name = "RSA EXPORT with 40 bit RC2 in CBC mode and hash function MD5"; break; case 0x07: name = "RSA with IDEA in CBC mode and hash function SHA"; break; case 0x08: name = "RSA EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x09: name = "RSA with DES in CBC mode and hash function SHA"; break; case 0x0A: name = "RSA with 3DES EDE in CBC mode and hash function SHA"; break; case 0x0B: name = "DH DSS EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x0C: name = "DH DSS with DES in CBC mode and hash function SHA"; break; case 0x0D: name = "DH DSS with 3DES EDE in CBC mode and hash function SHA"; break; case 0x0E: name = "DH RSA EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x0F: name = "DH RSA with DES in CBC mode and hash function SHA"; break; case 0x10: name = "DH RSA with 3DES EDE in CBC mode and hash function SHA"; break; case 0x11: name = "DHE DSS EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x12: name = "DHE DSS with DES in CBC mode and hash function SHA"; break; case 0x13: name = "DHE DSS with 3DES EDE in CBC mode and hash function SHA"; break; case 0x14: name = "RSA EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x15: name = "DHE RSA with DES in CBC mode and hash function SHA"; break; case 0x16: name = "DHE RSA with 3DES EDE in CBC mode and hash function SHA"; break; case 0x17: name = "Anonymous DH EXPORT with 40 bit RC4 and hash function MD5"; break; case 0x18: name = "Anonymous DH with 128 bit RC4 and hash function MD5"; break; case 0x19: name = "Anonymous DH EXPORT with 40 bit DES in CBC mode and hash function SHA"; break; case 0x1A: name = "Anonymous DH with DES in CBC mode and hash function SHA"; break; case 0x1B: name = "Anonymous DH with 3DES EDE in CBC mode and hash function SHA"; break; /* Elliptic Curve Cipher Suites */ case 0x34: name = "Elliptic Curve DHE DSS and hash function SHA"; break; case 0x36: name = "Elliptic Curve DHE DSS with 128 bit RC4 and hash function SHA"; break; case 0x37: name = "Elliptic Curve DHE DSS with DES CBC and hash function SHA"; break; case 0x38: name = "Elliptic Curve DHE DSS with 3DES EDE CBC and hash function SHA"; break; case 0x39: name = "Elliptic Curve DHE DSS Export with 40 bit DES CBC and hash function SHA"; break; case 0x40: name = "Elliptic Curve DHE DSS Export with 40 bit RC4 and hash function SHA"; break; case 0x60: name = "RSA Export with 56 bit RC4 and hash function MD5"; break; case 0x61: name = "RSA Export with 56 bit RC2 CBC and hash function MD5"; break; case 0x62: name = "RSA Export with DES CBC and hash function SHA"; break; case 0x63: name = "DHE DSS Export with DES CBC and hash function SHA"; break; case 0x64: name = "RSA Export with 56 bit RC4 and hash function SHA"; break; case 0x65: name = "DHE DSS Export with 56 bit RC4 and hash function SHA"; break; case 0x66: name = "DHE DSS with 128 bit RC4 and hash function SHA"; break; default: printf("Unknown Cipher Suite\n"); return; } printf("%s\n",name); }/* Determines if the algorithm is using DH or RSA and returns the value through keyxchange_alg field of the ssl_conn struct.*/static voidDetermineTLSKeyExchangeAlgorithm(char byte1, ssl_connection *ssl_conn){ switch(byte1) { case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x14: case 0x60: case 0x61: case 0x62: case 0x64: ssl_conn->keyxchange_alg = RSA; break; case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11: case 0x12: case 0x13: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x40: case 0x63: case 0x65: case 0x66: ssl_conn->keyxchange_alg = DH; break; default: printf("Error: no such key exchange algorithm\n"); }}/* processes the certificates that the server might send to the client. uses code from the openssl library. This should not be used for a SSLV2 certificate data because it seems like V2 does not support cert chains.*/static voidProcessCertificateChain(char *buffer, ssl_connection *ssl_conn){ X509 *cert = NULL; unsigned long nc, llen, l; unsigned char *p,*d,*q; /* from openssl, including naming conventions */ /* these pointers are different depending on what version of ssl */ if(ssl_conn->ssl_version == VERSION_TLS || ssl_conn->ssl_version == VERSION_SSL3) { d = p = (unsigned char *) (buffer + TLS_HANDSHAKE_HEADER_SIZE); } else { printf(" ERR Incorrect SSL version in record header for certificate.\n"); return; } n2l3(p, llen); for (nc = 0; nc < llen; ) { n2l3(p, l); if ((l + nc + 3) > llen) { printf(" ERR Certificate length mismatch\n"); return; } q = p; cert = d2i_X509(NULL, &q, l); /* grab the current cert */ if (cert == NULL) { printf(" ERR Bad Certificate\n"); return; } if (q != (p + l)) { printf(" ERR in Certificate Decode\n"); return; } ProcessCertificate(cert); cert = NULL; nc += l + 3; p = q; }}/* takes the X509 certificate and parses out the information into a UTL_CERT_INFO struct. Taken from Dan Boneh's utl_cert.c*/static voidProcessCertificate(X509 *x){ UTL_CERT_INFO buf; BIO *mem = NULL; EVP_PKEY *key; if ((mem=BIO_new(BIO_s_mem())) == NULL) { printf("ERR Unable to create new BIO\n"); return; } /* Extract and process validity periods */ ASN1_UTCTIME_print(mem, X509_get_notAfter(x)); BIO_gets(mem, buf.notAfter, sizeof(buf.notAfter)); ASN1_UTCTIME_print(mem, X509_get_notBefore(x)); BIO_gets(mem, buf.notBefore, sizeof(buf.notBefore)); /* Extract and process subject name */ buf.subj = X509_get_subject_name(x); X509_NAME_oneline(buf.subj, buf.subj_DistName, sizeof(buf.subj_DistName) ); /* Extract and process issuer name */ buf.issuer = X509_get_issuer_name(x); X509_NAME_oneline(buf.issuer, buf.issuer_DistName, sizeof(buf.issuer_DistName) ); /* get the key size */ key = X509_get_pubkey(x); PrintCertificateInfo(&buf,key); BIO_free(mem); EVP_PKEY_free(key); }/* takes the info from utl_cert_info and prints out the info. also prints out the key size and type of key exchange mechanism. key handling taken from Dan Boneh's utl_cert.c*/static voidPrintCertificateInfo(UTL_CERT_INFO *buf, EVP_PKEY *key){ printf(" CERTIFICATE INFORMATION :- \n"); printf(" Validity -- Not After %s\n",buf->notAfter); printf(" Not Before %s\n",buf->notBefore); printf(" Subject Distinguished Name -- \n %s\n",buf->subj_DistName); printf(" Issuer Distinguished Name -- \n %s\n",buf->issuer_DistName); if (key == NULL) return; switch (key->type) { case EVP_PKEY_RSA: buf->keysize = RSA_size(key->pkey.rsa)*8; printf(" RSA Public key size %d bits\n\n",buf->keysize); break; case EVP_PKEY_DSA: buf->keysize = DSA_size(key->pkey.dsa)*8; printf(" DSS Public key size %d bits\n\n",buf->keysize); break; default: printf(" Unknown key type\n\n"); }}/* prints out the types of certificates requested. At present just dumps out the distinguished names of the CA as a string.*/static void ProcessCertificateRequest(char *buffer, ssl_connection *ssl_conn){ char *data = buffer + TLS_HANDSHAKE_HEADER_SIZE; char *temp; unsigned int cert_type_len = 0; int i; unsigned int len = ThreeBytesToInt(buffer + 1); printf("Types of certificates requested --\n"); memcpy(&cert_type_len, data, 1); for(i = 0, data++; i < cert_type_len; i++, data++) { switch(*data) { case 1: printf("\tRSA certificate\n"); break; case 2: printf("\tDSS certificate\n"); break; case 3: printf("\tRSA certificate with fixed DH parameters\n"); break; case 4: printf("\tDSS certificate with fixed DH parameters\n"); break; default: printf("\tUnknown certificate requested\n"); break; } } /* print out the distinguished names of the CA */ len -= cert_type_len; temp = (char *) utl_GetMem(len + 1); memcpy(temp, data, len); temp[len] = '\0'; printf("Distinguished Names of CA's -- %s", temp); free(temp); }/* processes the server key exchange to obtain the parameters. depending on whether the algorithm is RSA or DSS, different params will be printed out.*/static void ProcessTLSServerKeyExchange(char *buffer, ssl_connection *ssl_conn){ char *data = buffer + TLS_HANDSHAKE_HEADER_SIZE; switch(ssl_conn->keyxchange_alg) { case RSA: data = ExtractParams(data, "RSA Modulus"); ExtractParams(data, "RSA Exponent"); break; case DH: data = ExtractParams(data, "DH Prime Modulus p"); data = ExtractParams(data, "DH Generator g"); data = ExtractParams(data, "DH public value (g^X mod p)"); break; }}/* prints out the data in hex of the parameters. assumes that the length of the data is given by the first 2 bytes.*/static char *ExtractParams(char *params, char *type){ unsigned short param_len = TwoBytesToInt(params); char *start = params; int i; unsigned int byte; printf("Length of %s -- %d\n", type, param_len); printf("%s --\n 0x",type); /* skip over two byte length field */ for(i = 0, params += 2; i < param_len; i++, params++) { byte = 0; memcpy(&byte, params, 1); printf("%2.2x", byte); } printf("\n"); return (start + 2 + param_len);}/* Using the keyxchange_alg field of the ssl_conn passed in, will process and print out the appropriate information. For RSA, prints out the RSA encrypted premaster secret and for DH, prints out the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -