📄 sslsniffer.c
字号:
public value.*/static void ProcessTLSClientKeyExchange(char *buffer, ssl_connection *ssl_conn){ char *ptr = buffer + TLS_HANDSHAKE_HEADER_SIZE; int i; unsigned int len = ThreeBytesToInt(buffer+1); unsigned int byte = 0; switch(ssl_conn->keyxchange_alg) { case RSA: printf("Length of RSA Encrypted PreMaster Secret -- %d bytes\n",len); printf("RSA Encrypted PreMaster Secret --\n 0x"); /* 1 for first byte specifying type and 3 for length field */ for(i = 0, ptr += 4; i < len; i++, ptr++) { byte = 0; memcpy(&byte, ptr, 1); printf("%2.2x", byte); } printf("\n"); break; case DH: if(!len) { ExtractParams(ptr,"DH public value"); } else { printf("DH public key is implicit in client certificate\n"); } break; default: printf("Unable to process Client Key Exchange %d\n", ssl_conn->keyxchange_alg); }}/* ---------------------------- SSL2 -------------------------------- */static int ProcessOneSSL2Record(ssl_connection *ssl_conn){ /* print out protocol version */ printf("Protocol Version: SSLV2\n"); printf("From Record Header -- Record Length: %d\n", ssl_conn->record_len - ssl_conn->ssl2_record_hdr_len ); /* print out padding length if record was padded */ if(ssl_conn->ssl2_record_hdr_len == SSL2_3BYTE_RECORD_HEADER_SIZE) { printf(" Padding Length: %d\n", ssl_conn->ssl2_padding_len); } /* the packet is encrypted. we cannot even parse to determine the content type */ if(ssl_conn->ssl2_packets_encrypted) { printf("Packet is encrypted.\n"); return 1; } switch(ssl_conn->record[ssl_conn->ssl2_record_hdr_len]) { case SSL2_MT_CLIENT_MASTER_KEY: ProcessSSLV2ClientMasterKey(ssl_conn); /* all further packets will be encrypted */ ssl_conn->ssl2_packets_encrypted = 1; break; case SSL2_MT_CLIENT_HELLO: /* this should never be called though */ ProcessSSLV2ClientHello(ssl_conn); break; case SSL2_MT_SERVER_HELLO: /* check if we should expect a client master key packet next by looking at the resume hit char */ if(ssl_conn->record[ssl_conn->ssl2_record_hdr_len + 1] != 0) { /* since the session id hit, all further packets will be encrypted */ ssl_conn->ssl2_packets_encrypted = 1; } ProcessSSLV2ServerHello(ssl_conn); break; case SSL2_MT_ERROR: ProcessSSLV2Error(ssl_conn); break;/* these are all sent encrypted. since we are only parsing in this version, we cannot do anything since we don't even know the kind of packet this is case SSL2_MT_CLIENT_FINISHED: ProcessSSLV2ClientFinished(ssl_conn); break; case SSL2_MT_SERVER_VERIFY: break; case SSL2_MT_SERVER_FINISHED: break; case SSL2_MT_REQUEST_CERTIFICATE: break; case SSL2_MT_CLIENT_CERTIFICATE: ProcessSSLV2ClientCertificate(ssl_conn); break;*/ default: printf("Received Unknown packet type.\n"); return -1; } //printf("\n"); return 1;}/* Processes the client master key packet.*/static voidProcessSSLV2ClientMasterKey(ssl_connection *ssl_conn){ unsigned short clear_key_data_len = 0; unsigned short encrypted_key_data_len = 0; unsigned short key_arg_data_len = 0; char *record = ssl_conn->record; printf("Received Client Master Key Packet --\n"); printf("Cipher Suite --\n"); ProcessSSLV2OneCipherSuite(record[1], record[2], record[3]); clear_key_data_len = (((unsigned short) record[4]) << 8) | ((unsigned char) record[5]); encrypted_key_data_len = (((unsigned short) record[6]) << 8) | ((unsigned char) record[7]); key_arg_data_len = (((unsigned short) record[8]) << 8) | ((unsigned char) record[9]); printf("Clear Key Data Length -- %hu\n", clear_key_data_len); printf("Encrypted Key Data Length -- %hu\n", encrypted_key_data_len); printf("Key Arg Data Length -- %hu\n", encrypted_key_data_len); printf("All further packets will be encrypted.\n");}/* Examines the bytes given and prints out the cipher suite that is being used. This is used when a SSLV2 client hello is being processed.*/static voidProcessSSLV2OneCipherSuite(char byte1, char byte2, char byte3){ char unknown = 0; if(byte1 == 0x00) /* TLS Ciphers used */ { ProcessTLSCipherSuite(byte2,byte3); return; } printf(" Hex Code:"); utl_PrintCharAsHex(byte1); utl_PrintCharAsHex(byte2); utl_PrintCharAsHex(byte3); printf("\n Type: "); switch((unsigned char) byte1) { case 0x01: if(byte3 == (char) 0x80) { printf("RSA with 128 bit RC4 and hash function MD5\n"); } else { unknown = 1; } break; case 0x02: if(byte3 == (char) 0x80) { printf("RSA Export with 40 bit RC4 and hash function MD5\n"); } else { unknown = 1; } break; case 0x03: if(byte3 == (char) 0x80) { printf("RSA with 128 bit RC2 CBC and hash function MD5\n"); } else { unknown = 1; } break; case 0x04: if(byte3 == (char) 0x80) { printf("RSA Export with 40 bit RC2 and hash function MD5\n"); } else { unknown = 1; } break; case 0x05: if(byte3 == (char) 0x80) { if(byte2 == (char) 0x00) { printf("RSA with 128 bit IDEA CBC and hash function MD5\n"); } else { printf("RSA with 128 bit IDEA CBC and hash function SHA\n"); } } else { unknown = 1; } break; case 0x06: if(byte3 == (char) 0x40) { printf("RSA with 64 bit DES CBC and hash function MD5\n"); } else { unknown = 1; } break; case 0x07: if(byte3 == (char) 0xC0) { if(byte2 == (char) 0x00) { printf("RSA with 192 bit 3DES EDE CBC and hash function MD5\n"); } else { printf("RSA with 192 bit 3DES EDE CBC and hash function SHA\n"); } } else { unknown = 1; } break; case 0xff: if(byte3 == 0x00) { printf("RSA with 64 bit DES CFB with hash function MD5\n"); } else { printf("No Cipher Suite\n"); } break; default: unknown = 1; } if(unknown) { printf("Unknown SSLV2 cipher used\n"); }}/* Processes the SSLV2 Client Hello message. This message is only sent by clients that support both TLS1.0 and SSLV2. Appendix E RFC 2246. Assumes that the buffer points to the record type which is 2 bytes after the start of the packet. -- not any more. Now assumes starts at record beginning.*/static void ProcessSSLV2ClientHello(ssl_connection *ssl_conn){ char *buffer = ssl_conn->record + SSL2_2BYTE_RECORD_HEADER_SIZE; /* skip over record */ short cipher_spec_len = TwoBytesToInt(&(buffer[SSL2_CLIENT_HELLO_CIPHER_SPEC_LEN_OFFSET])); short session_id_len = TwoBytesToInt(&(buffer[SSL2_CLIENT_HELLO_SESSION_ID_LEN_OFFSET])); short challenge_len = TwoBytesToInt(&(buffer[SSL2_CLIENT_HELLO_CHALLENGE_LEN_OFFSET])); char *ptr; int session_id_offset = cipher_spec_len + SSL2_CLIENT_HELLO_CIPHER_SPEC_OFFSET; int i; unsigned int byte; printf("Received SSLV2 Client Hello ...\n"); printf("\nFrom Client Hello -- Protocol Version: %d.%d\n", buffer[1], buffer[2]); printf("Session ID Length -- %hd bytes\n", session_id_len); printf("Session ID --\n"); for(i = 0, ptr = buffer + session_id_offset; i < session_id_len; i++, ptr++) { byte = 0; memcpy(&byte, ptr, 1); printf("%.2x", byte); } ProcessSSLV2CipherSuiteData(buffer + SSL2_CLIENT_HELLO_CIPHER_SPEC_OFFSET, cipher_spec_len); printf("Challenge Length -- %hd bytes\n", challenge_len);}/* Processes all the cipher suite data*/static void ProcessSSLV2CipherSuiteData(char *cipher_suite_data, unsigned short data_len){ int i; char *ptr; printf("Cipher Suite Length %hd bytes ... number of cipher suites %d\n", data_len, data_len / SSL2_ONE_CIPHER_SUITE_LEN); printf("Cipher Suite List is -- \n"); for(i = 0, ptr = cipher_suite_data; i < data_len; i += SSL2_ONE_CIPHER_SUITE_LEN, ptr += SSL2_ONE_CIPHER_SUITE_LEN) { ProcessSSLV2OneCipherSuite(ptr[0], ptr[1], ptr[2]); }}/* Checks if the record hdr is a v2 client hello. we don't have to worry about the padding byte because a client hello is always in plain text.*/static intIsV2ClientHello(char *record_hdr){ return((record_hdr[0] & 0x80) && (record_hdr[SSL2_MSG_TYPE_OFFSET] == SSL2_MT_CLIENT_HELLO)); }/* prints out the relevant information for a server hello*/static void ProcessSSLV2ServerHello(ssl_connection *ssl_conn){ char session_id_hit = 0; char certificate_type; unsigned short server_version; unsigned short certificate_len; unsigned short cipher_spec_len; unsigned short connection_id_len; char *record_data = ssl_conn->record + ssl_conn->ssl2_record_hdr_len; char *cert_data = record_data + SSL2_SERVER_HELLO_CERT_DATA_OFFSET; char *cipher_spec_data; X509 *cert; printf("Received Server Hello Packet --\n"); /* first pull out all the data */ session_id_hit = record_data[1]; certificate_type = record_data[2]; server_version = ((unsigned short) (record_data[3] << 8)) | ((unsigned char) record_data[4]); certificate_len = ((unsigned short) (record_data[5] << 8)) | ((unsigned char) record_data[6]); cipher_spec_len = ((unsigned short) (record_data[7] << 8)) | ((unsigned char) record_data[8]); connection_id_len = ((unsigned short) (record_data[9] << 8)) | ((unsigned char) record_data[10]); cipher_spec_data = cert_data + certificate_len; printf("Server version is %hu\n", server_version); if(session_id_hit) { printf("Session ID matched previous session - SSL2 Resume\n" "All further packets will be encrypted\n"); return; /* all the other fields will be empty */ } else { printf("Session ID did not match any previous session - No Resume\n"); } /* it appears that V2 doesn't seem to support the chain the same way as TLS. In fact, it doesn't seem to support any chains at all. ProcessCertificateChain(cert_data, ssl_conn); */ /* extract and print out the cert */ cert = d2i_X509(NULL, (unsigned char **) &cert_data, certificate_len); ProcessCertificate(cert); ProcessSSLV2CipherSuiteData(cipher_spec_data, cipher_spec_len); printf("Connection ID len is %hu\n", connection_id_len); }/* prints out the relevant information for a server hello*/static void ProcessSSLV2Error(ssl_connection *ssl_conn){ char *record_data = ssl_conn->record + ssl_conn->ssl2_record_hdr_len; unsigned short error_code; printf("Received SSLV2 Error -- \n"); error_code = (record_data[1] << 8) | ((unsigned char) record_data[2]); printf("Error Code is %hu -- ", error_code); switch(error_code) { case SSL2_PE_NO_CIPHER: printf("No common ciphers supported.\n"); break; case SSL2_PE_NO_CERTIFICATE: printf("No certificate sent by client.\n"); break; case SSL2_PE_BAD_CERTIFICATE: printf("Bad certificate sent.\n"); break; case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE: printf("Unsupported certificate type.\n"); break; default: printf("Unknown error.\n"); break; }}#if 0/* Since we are only parsing it and it is sent encrypted, we can't do very much here*/static voidProcessSSLV2ClientFinished(ssl_connection *ssl_conn){ printf("Received SSLV2 Client Finished -- \n" "Packet is encrypted\n");}/* Since we are only parsing it and it is sent encrypted, we can't do very much here*/static voidProcessSSLV2ClientCertificate(ssl_connection *ssl_conn){ printf("Received SSLV2 Client Certificate --\n" "Packet is encrypted\n\n");}#endif/* --------------------- UTILITIES ---------------------------------- *//* A wrapper for close that does some error checking.*/void CloseSocket(int sock){ if(close(sock) < 0 ) { perror("Close socket error"); exit(FAILURE); }}/* used for converting the short in 2 byte length fields to an int. returns the value as a short in the host byte order. can't dereference a short directly because it might not be word aligned.*/shortTwoBytesToInt(char *buffer){ int i; char *temp; short len = 0; /* get the length of the message */ temp = (char *) &len; for(i = 0; i < 2; i++) /* 2 is the size of the length field */ { memcpy(&(temp[i]), buffer + i, 1); } return ntohs(len);}/* used for converting the 3 byte field in the handshake packet that represents the length of the packet to an int*/unsigned intThreeBytesToInt(char *buffer){ int i; char *temp; unsigned int len = 0; /* get the length of the message */ temp = (char *) &len; for(i = 0; i < 3; i++) /* 3 is the size of the length field */ { memcpy(&(temp[i]), buffer + 2 - i, 1); } return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -