Advertisement
Guest User

Untitled

a guest
Aug 18th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.04 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # Extremely Principled TLS v1.2 ClientHello parser for ALPN extensions
  3.  
  4. import struct
  5. import binascii
  6.  
  7.  
  8. _int16 = struct.Struct(">H")
  9.  
  10.  
  11. def int16(b):
  12. """
  13. Return first two bytes of b as an unsigned integer.
  14. """
  15. return _int16.unpack(b[:2])[0]
  16.  
  17.  
  18. def take(data, count):
  19. prefix = data[:count]
  20. data = data[count:]
  21. return prefix, data
  22.  
  23.  
  24. # Handshake, 3, 1 (TLS 1.0)
  25. HEADER = b"\x16\x03\x01"
  26. TYPE_ALPN = b"\x00\x10"
  27.  
  28.  
  29. def parseHello(data):
  30. """
  31. Parse TLS 1.2 ClientHello from data, return the extensions as binary data
  32. or None if not found.
  33.  
  34. Likely to raise struct.error or IndexError on error.
  35. """
  36. # if not data.startswith(HEADER):
  37. # return
  38. header, data = take(data, 7)
  39. messageId, major, minor, l1, l2 = struct.unpack(">BBBHH", header)
  40. print(messageId, major, minor, l1, l2)
  41. # if not data.startswith(b"\x01"): # ClientHello
  42. # return
  43. header2, data = take(data, 4)
  44. print(struct.unpack(">HBB", header2)) # inner length; 3; 3
  45. # random
  46. random, data = take(data, 32)
  47. # session identifier
  48. slen, data = take(data, 1)
  49. slen = slen[0]
  50. session, data = take(data, slen)
  51. # ciphers list
  52. clen, data = take(data, 2)
  53. clen = int16(clen)
  54. ciphers, data = take(data, clen)
  55. # compression methods (should always be an array of length 1, with one 0 element)
  56. compression_length, data = take(data, 1)
  57. compression_methods, data = take(data, compression_length[0])
  58. # extensions
  59. extlen, data = take(data, 2)
  60. extensions, data = take(data, int16(extlen))
  61. return extensions
  62.  
  63.  
  64. def parseExtensions(data):
  65. """
  66. Yield (type, body) for TLS extensions in data, as binary data.
  67. """
  68. while data:
  69. type, data = take(data, 2)
  70. length, data = take(data, 2)
  71. body, data = take(data, int16(length))
  72. yield (type, body)
  73.  
  74.  
  75. def parseAlpn(body):
  76. """
  77. Parse array of Pascal strings, ignore a 16-bit length header.
  78. """
  79. length, body = take(body, 2)
  80. while body:
  81. protocol, body = take(body[1:], body[0])
  82. yield protocol
  83.  
  84.  
  85. if __name__ == "__main__":
  86. sample_hello = b"FgMBAgABAAH8AwN3t6WJKcsKcWo+roqQX7Nuc8SYCUAKTIkINuDoJm4ooiDRiC2236q0JY/NewWV9KcViEzk7S03gwwUSioSOKbOcAAkEwETAxMCwCvAL8ypzKjALMAwwArACcATwBQAMwA5AC8ANQAKAQABjwAAAA4ADAAACWxvY2FsaG9zdAAXAAD/AQABAAAKAA4ADAAdABcAGAAZAQABAQALAAIBAAAjAAAAEAAOAAwCaDIIaHR0cC8xLjEABQAFAQAAAAAAMwBrAGkAHQAgcqzbr+1AYblh6qcR+qvjokWhIpbChkaqpXuDY9uHhVoAFwBBBAq/uAsPt0n3lc9MGArs6RqLoQE+1eWkstNR0zPjxlQcqGSD+1mKyvSCGEwU0DCZAEFEvhnj5YxSyqcAFODwnp4AKwAJCAMEAwMDAgMBAA0AGAAWBAMFAwYDCAQIBQgGBAEFAQYBAgMCAQAtAAIBAQAcAAJAAQAVAJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
  87.  
  88. import base64
  89. import pprint
  90.  
  91. data = bytearray(base64.b64decode(sample_hello))
  92. extensions = parseHello(data)
  93. for (type, body) in parseExtensions(extensions):
  94. if type == TYPE_ALPN:
  95. pprint.pprint(list(parseAlpn(body)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement