Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- ## Trusted Neighbour Discovery Protocol POC
- ##
- ##
- ## The Trusted Neighbour Discovery Protocol is a protocol which can be used to identify computers
- ## on a local LAN that share a common secret and set up trusted communication channels bewteen them
- ## at the same time.
- ## The TNDP uses standard challenge response mechanisms to provide mutual authentication between
- ## two holders of a common secret.
- ## After mutual authentication, TNDP uses Diffie Hellman to create a shared session key for
- ## secure communication. However, by choosing the random challenge nonces from a publicly known
- ## algebraic group, TNDP integrates the Diffie Hellman key exchange mechanism in the challenge
- ## response phase, improving efficiency by two rounds.
- ## The POC implemenation scans the local lan for computers running the POC while listening for
- ## connections from other computers.
- ## Once a neighbour has been identified and authenticated, the listener uses the newly created
- ## secure channel to send some user-specified flag data
- ##
- ## TNDP overview:
- ## Neighbour1 Neighbour2
- ##
- ## (shared secret k) (shared secret k)
- ## HELLO
- ## -------------->
- ## pick random secret x
- ## nonce_1 = g^x (Diffie Hellman public key)
- ## nonce_1
- ## <--------------
- ## pick random secret y
- ## nonce_2 = g^y
- ## encrypt nonces using k
- ## {nonce_1, nonce_2}k
- ## -------------->
- ## check validity of nonce_1
- ## calculate shared secret s = nonce_2^x
- ## nonce_2
- ## <--------------
- ## check validity nonce_2
- ## calculate shared secret
- ## s = nonce_1
- ## {secure data}s
- ## <------------->
- ##
- from Crypto.Cipher import AES
- from Crypto.Util import number
- from Crypto.Util import randpool
- import hashlib
- import struct
- import socket
- import os
- import sys
- import time
- ips = [ "192.168.120.186", "192.168.120.1", "192.168.120.115", "192.168.120.119", "192.168.120.121", "192.168.120.122", "192.168.120.125", "192.168.120.127", "192.168.120.133", "192.168.120.145", "192.168.120.146", "192.168.120.148", "192.168.120.149", "192.168.120.157", "192.168.120.160", "192.168.120.182", "192.168.120.185", "192.168.120.198" ]
- # helper function because python doesn't support conversion of numbers larger than 64 bits
- def toBytes(largeNum):
- part2 = largeNum & 0xFFFFFFFFFFFFFFFF
- part1 = largeNum >> 64
- byteForm = struct.pack('Q', part1) + struct.pack('Q', part2)
- return byteForm
- # helper function because python doesn't support conversion to numbers larger than 64 bits
- def toNum(byteForm):
- part1 = struct.unpack("Q", byteForm[0:8])
- part2 = struct.unpack("Q", byteForm[8:16])
- largeNum = (part1[0] << 64) + part2[0]
- return largeNum
- # the listener, spawns a separate process for each incoming connection
- def startListener(port):
- sock = socket.socket();
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(("0.0.0.0", port));
- sock.listen(5);
- while(True):
- (c, a) = sock.accept()
- pid = os.fork()
- if (pid):
- handleIncoming(c, a)
- break
- # the incoming connection handler,
- def handleIncoming(connection, address):
- inp = connection.recv(6)
- if (not inp[0:5] == "HELLO"):
- connection.shutdown(socket.SHUT_RDWR)
- connection.close()
- print "connection closed after hello"
- sys.exit()
- generator = randpool.RandomPool()
- secret = number.getRandomNumber(128, generator.get_bytes)
- pub = pow(g, secret, prime)
- connection.send(toBytes(pub)) # sending nonce1
- inp = connection.recv(32) # receiving encrypted nonces
- print inp.encode('hex')
- if (not len(inp) == 32):
- print "incoming closed: invalid response size"
- connection.shutdown(socket.SHUT_RDWR)
- connection.close()
- sys.exit()
- decrypted = cipher.decrypt(inp)
- pubTest = toNum(decrypted[0:16])
- if (not pubTest == pub):
- connection.shutdown(socket.SHUT_RDWR)
- connection.close()
- print "incoming closed: authentication failed"
- sys.exit()
- pub2 = toNum(decrypted[16:32])
- connection.send(decrypted[16:32]) # sending nonce2
- sharedSecret = pow(pub2, secret, prime)
- sharedCipher = makeCipher(toBytes(sharedSecret))
- print "incoming successful: sending flag"
- connection.send(sharedCipher.encrypt(paddedString(flag)))
- connection.shutdown(socket.SHUT_RDWR)
- connection.close()
- sys.exit()
- def startFinder(port):
- connections = []
- ipaddr = "192.168.120.145"
- while(True):
- for i in ips:
- if (not i == ipaddr):
- sock = socket.socket()
- sock.settimeout(1)
- print i
- try:
- sock.connect((i, port))
- pid = os.fork()
- if (pid):
- handleOutgoing(sock)
- except Exception as e:
- sock.close()
- time.sleep(1)
- def handleOutgoing(sock):
- print "starting outgoing"
- sock.send("HELLO")
- inp = sock.recv(16) # receiving nonce1
- if (not len(inp) == 16):
- print "outgoing closed: invalid riesponse size nonce1"
- sock.shutdown(socket.SHUT_RDWR)
- socket.close()
- sys.exit()
- pub2 = toNum(inp)
- generator = randpool.RandomPool()
- secret = number.getRandomNumber(128, generator.get_bytes)
- pub = pow(g, secret, prime)
- encrypted = cipher.encrypt(inp + toBytes(pub))
- sock.send(encrypted) #sending encrypted nonces
- inp = sock.recv(16) # receiving nonce2
- print "nonce2 = " + inp + ", len=" + str(len(inp))
- if (not len(inp) == 16):
- print "outgoing closed: invalid response size nonce2, len = " + str(len(inp))
- sock.shutdown(socket.SHUT_RDWR)
- sock.close()
- sys.exit()
- pubTest = toNum(inp)
- if (not pubTest == pub):
- sock.shutdown(socket.SHUT_RDWR)
- sock.close()
- print "outgoing closed: authentication failed"
- sys.exit()
- sharedSecret = pow(pub2, secret, prime)
- sharedCipher = makeCipher(toBytes(sharedSecret))
- inp = sock.recv(32)
- print("outgoing succesfull: flag = " + sharedCipher.decrypt(inp))
- sock.shutdown(socket.SHUT_RDWR)
- sock.close()
- sys.exit()
- def makeCipher(password):
- key = hashlib.sha256(password).digest()
- cipher = AES.new(key, AES.MODE_ECB)
- return cipher
- def paddedString(string):
- return string + (" " * (16 - (len(string) % 16) % 16))
- password = "password"
- if (len(sys.argv) > 1):
- password = sys.argv[1]
- flag = "flag"
- if (len(sys.argv) > 2):
- flag = sys.argv[2]
- cipher = makeCipher(password)
- prime = 234240772648780971299441373185329797673L
- g = 304615143433536066436723092374584571969L
- print "starting finder"
- startFinder(22223)
Add Comment
Please, Sign In to add comment