1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#!/usr/bin/env python2
"""
Wraps an unencrypted TCP protocol in SSL.
Reads a pcap file containing a single unencrypted TCP stream and replays the
data over a SSL-encrypted channel (internal SSL server started for this
purpose). You must create server.pem first.
Best combined with src/sslkeylog.sh for extracting the pre-master secret (or
force a certain cipher).
Originally used to generate a pcap for Wireshark bug 11990 from the
evidence01.pcap file from
http://forensicscontest.com/2009/09/25/puzzle-1-anns-bad-aim
Copyright (C) 2016 Peter Wu <peter@lekensteyn.nl>
"""
import argparse, socket, ssl, sys
from threading import Thread, Condition
# Meh, scapy 2.3.1 still does not support Py3... There is scapy3k though.
from scapy.all import *
try:
from queue import Queue
except ImportError:
from Queue import Queue
address = ('127.0.0.1', 4433)
parser = argparse.ArgumentParser()
parser.add_argument("--key", default="server.pem",
help="Private SSL key (default %(default)s)")
parser.add_argument("--cert", default="server.pem",
help="SSL certificate (default %(default)s)")
parser.add_argument("--ciphers",
help="SSL cipher list (see OpenSSL ciphers, default not restricted)")
parser.add_argument("pcap_file", help="Pcap file with single TCP stream")
parser.add_argument("pcap_srvport", type=int, help="Server port in pcap")
def get_server_sock(q, c, key, cert, ciphers):
c.acquire()
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(address)
sock.listen(1)
except:
q.put(None)
raise
finally:
c.notify()
c.release()
try:
conn, addr = sock.accept()
print("Client: %r" % (addr,))
conn = ssl.wrap_socket(conn, key, cert, True, ciphers=ciphers)
q.put(conn)
except:
q.put(None)
raise
def get_client_sock(q, ciphers):
try:
csock = socket.create_connection(address)
print("Client connected to server at: %r" % csock)
csock = ssl.wrap_socket(csock, ciphers=ciphers)
q.put(csock)
except:
q.put(None)
raise
def main():
args = parser.parse_args()
# Connect in separate threads to avoid a deadlock due to the SSL handshake
# waiting for a reply while the other connection still needs to be wrapped.
server_queue = Queue()
client_queue = Queue()
cond = Condition()
server_thread = Thread(target=get_server_sock, name='Server',
args=(server_queue, cond, args.key, args.cert, args.ciphers))
client_thread = Thread(target=get_client_sock, name='Client',
args=(client_queue, args.ciphers))
cond.acquire()
server_thread.start()
cond.wait()
cond.release()
client_thread.start()
server_thread.join()
client_thread.join()
ssock = server_queue.get()
csock = client_queue.get()
print("Server: %r" % ssock)
print("Client: %r" % csock)
if not ssock or not csock:
sys.exit(1)
pkts = rdpcap(args.pcap_file)
for p in pkts:
data = str(p[TCP].payload)
if not data:
print("Skipping empty packet %r", p[TCP])
continue
if p[TCP].sport == args.pcap_srvport:
sender, receiver = ssock, csock
else:
sender, receiver = csock, ssock
print("Sending packet %r" % p[TCP])
sender.sendall(data)
remaining = len(data)
while remaining > 0:
remaining -= len(receiver.recv(remaining))
csock.close()
ssock.close()
print("Final!")
if __name__ == '__main__':
main()
|