-
Notifications
You must be signed in to change notification settings - Fork 0
/
proxy.py
159 lines (121 loc) · 5.09 KB
/
proxy.py
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/python2.7
#Black Hat Python Chapter Two: Building a TCP proxy
import sys
import socket
import threading
def server_loop(local_host,local_port,remote_host,remote_port,receive_first):
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
server.bind((local_host,local_port))
except:
print "[!!] Failed to listen on %s:%d" % (local_host,local_port)
print "[!!] Check for other listening sockets or correct permissions"
sys.exit(0)
print "[*] Listening on %s:%d" % (local_host,local_port)
server.listen(5)
while True:
client_socket, addr= server.accept()
#print out the local connection information
print "[==>] Recieved incoming connection from %s:%d" (addr[0],addr[1])
#start a thread to talk to the remote host
proxy_thread=threading.Thread(target=proxy_handler, args=(client_socket,remote_host,remote_port,receive_first))
proxy_thread.start()
def main():
#no fancy command line parsing ehre
if len(sys.argv[1:]) !=5:
print "Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [recieve_first]"
print "Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True"
sys.exit(0)
#setup local listening parameters
local_host = sys.argv[1]
local_port = int(sys.argv[2])
#set up remote target
remote_host = sys.argv[3]
remote_port = sys.argv[4]
#this tells our proxy to connect and receive data
# before sending to the remote host
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else:
receive_first = False
#now spin up our listening port
server_loop(local_host,local_port,remote_host,remote_port,receive_first)
def proxy_handler(client_socket,remote_host,remote_port, receive_first):
#connect to the remote host
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host,remote_port))
#receive the data from the remote end if necessary
if receive_first:
remote_buffer= receive_from(remote_socket)
hexdump(remote_buffer)
#send it to our response handler
remote_buffer= response_handler(remote_buffer)
#if we have data to send to our local client, send it
if len(remote_buffer):
print "[<==] Sedning %d bytes to localhost" % len(remote_buffer)
client_socket.send(remote_buffer)
# now lets loop and read from local,
# send to remote, send to local
# rinse, wash, repeat
while True:
#read from localhost
local_buffer=receive_from(client_socket)
if len(local_buffer):
print "[==>] Received %d bytes from localhost." % len(local_buffer)
hexdump(local_buffer)
#send it to our request handler
local_buffer = request_handler(local_buffer)
#send off the data to the remote host
remote_socket.send(local_buffer)
print "[==>] Sent to remote."
#receive back the response
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print "[<==] Received %d bytes from remote." % len(remote_buffer)
hexdump(remote_buffer)
#send to our response handler
remote_buffer = response_handler(remote_buffer)
#seend the response to the local socket
client_socket.send(remote_buffer)
print "[<==] Sent to localhost."
# if no more data on either side, close the connections.
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print "[*] No more data. Closing connections."
break
# this is a pretty hexdump function taken from the comments here:
# http://code.activestate.com/recipes/142812-hex-dumper/
def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src, unicode) else 2
for i in xrange(0, len(src), length):
s = src[i:i+length]
hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
result.append( b"%04X %=*s %s" % (i, length*(digits + 1), hexa, text) )
print b'\n'.join(result)
def receive_from(connction):
buffer= ""
# we set a 2 second timeout; depending on target,
# this may need to be adjusted
connection.settimeout(2)
try:
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except:
pass
return buffer
# Modify any requests destined for the remote host
def request_handler(buffer):
#perform packet modifications
return buffer
# Modify any responses destined for the local host
def response_handler(buffer):
#perform packet modifications
return buffer
main()