在滲透測試的時候,常需要用到攔截請求的技巧,來達到監聽和分析請求等。在這個時候,我們可以建立一個中間的"轉運站"來達到上述目的,這就是Proxy的功能,Proxy就像是仲介一樣,使用者透過它向伺服器連線,伺服器也透過它向使用者傳送資料,三者之間關係如下:
main函式:
if len(sys.argv[1:]) != 5:
print("使用參數說明: ./tcp_proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]")
print("範例: ./tcp_proxy.py 127.0.0.1 9000 10.12.132.1 9000 True")
sys.exit(0)
local_host = sys.argv[1]
local_port = int(sys.argv[2])
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
if "True" in sys.argv[5]:
receive_first = True
else:
receive_first = False
server_loop(local_host, local_port, remote_host, remote_port, receive_first)
用簡單的sys函數來取得使用者傳入的引數,程式需要5個引數,前兩個是使用者電腦的IP和端口,Proxy將在上面監聽,3、4個引數是伺服器端的IP和端口,將透過該資訊與伺服器建立連線。而最後一個引數是用來指定建立連線後要不要先從伺服器接收資料。在main函式中,我們最後呼叫了server_loop函式,該函式是用來處理連線的一個無窮迴圈:
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("[!!] 無法在 %s:%d 上開啟端口" % (local_host, local_port))
print("[!!] 該端口可能已經被使用")
sys.exit(0)
print("[*] 代理啟動於: %s:%d" % (local_host, local_port))
server.listen(5)
while True:
client_socket, addr = server.accept()
print("[==>] 來自 %s:%d 的連線請求" % (addr[0], addr[1]))
proxy_thread = threading.Thread(target=proxy_handler,
args=(client_socket, remote_host, remote_port, receive_first))
proxy_thread.start()
server_loop函式會建立一個在本機監聽的socket,然後進入無窮迴圈不斷處理請求,如果有新的連線請求,就創建一個執行緒(不懂執行緒概念的讀者可以參考網路上的一些說明)來處理請求,對於每個連線要求的處理,我們獨立一個函式出來:def proxy_handler(client_socket, remote_host, remote_port, receive_first):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive_first:
remote_buffer = receive_from(remote_socket)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print("[<==] 收到 %d 位元組的資料" % len(remote_buffer))
client_socket.send(remote_buffer)
while True:
local_buffer = receive_from(client_socket)
if len(local_buffer):
print("[==>] 傳送 %d 位元組的資料" % len(local_buffer))
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print("[==>] 傳送完成")
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[<==] 收到 %d 位元組的資料" % len(remote_buffer))
remote_buffer = response_handler(remote_buffer)
client_socket.send(remote_buffer)
print("[<==] 接收完成")
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print("[*] 傳輸完成,關閉連線")
break
其實現方式就是不斷檢查有沒有資料要傳輸,如果有的話叫傳到另一邊,而為了增加擴充性,我用request_handler和response_handler函式在傳送前處理一下資料,可以啥事都不做直接return,也可以在函式內對資料做竄改或攔截等。為了簡潔,把接收數據獨立出來一個函式:
def receive_from(connection):
buffer = ''
connection.settimeout(2)
try:
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except:
pass
return buffer
到這邊我們的Proxy基本上已經完成了但還有很多功能還沒實現,只能做簡單的測試等,就當一個python socket的練習吧!完整程式碼下載:Github下載
1 意見
66666666
回覆刪除