Python實現TCP代理__Python

來源:互聯網
上載者:User

滲透測試中,經常遇到無法使用wireshark、無法嗅探和分析流量的情況,可以通過部署簡單的TCP代理指令碼來瞭解未知的協議,修改資料包,或者為模糊測試建立環境。 介紹 原理

代理工作原理大致如下: [需要代理方]向伺服器發出請求資訊。 [代理方]應答。 [需要代理方]接到應答後發送向[代理方]發送目的ip和連接埠。 [代理方]與目的串連。 [代理方]將[需要代理方]發出的資訊傳到目的方,將目的方發出的資訊傳到[需要代理方]。 代理完成。 Usage Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first] Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True 編寫程式 main() 解析使用者命令列輸入 設定本地監聽參數和遠程目標 確認串連後是否需要先從遠程主機接收資料 進入監聽loop

def main():    # 沒有華麗的命令列解析    if len(sys.argv[1:]) != 5:        print("Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]")        print("Example: ./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    # 現在設定好我們的監聽socket    server_loop(local_host, local_port, remote_host, remote_port, receive_first)__author__ = 'xy'if __name__ == '__main__':    main()
server_loop() 建立TCP socket。 檢查本地連接埠是否可用,並彈出提示。 監聽本地連接埠 開啟線程與遠程主機通訊,當一個請求到達時,使用proxy_handler()函數處理之,並發送到遠程主機。
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 correcct permissions")        sys.exit(0)    print("[*] Listening on %s:%d" % (local_host, local_port))    server.listen(5)    while True:        client_socket, addr = server.accept()        # 列印出串連進來的IP和port        print("[==>] Received incoming connection from %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()
proxy_handler() 串連遠程主機。 如有必要,先從主機接受資料,使用response_handler()函數處理資料,並將其傳給本地。 實現資料從 本地->代理->遠程主機 的功能。
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)        hexdump(remote_buffer)        # 發送給我們的響應處理        remote_buffer = response_handler(remote_buffer)        # 如果我們有資料傳遞給本地用戶端,發送之        if len(remote_buffer):            print("[<==] Sending %d bytes to localhost." % len(remote_buffer))            client_socket.send(remote_buffer)    # 現在我們從本地迴圈讀取資料,發送給遠程主機和本地主機    while True:        # 從本地提取資料        local_buffer = receive_from(client_socket)        if len(local_buffer):            print("[==>] Received %d bytes from localhost." % len(local_buffer))            hexdump(local_buffer)            # 發送給我們的本地請求            local_buffer = request_handler(local_buffer)            # 向遠程主機發送資料            remote_socket.send(local_buffer)            print("[==>] Sent to remote")        # 接收響應的資料        remote_buffer = receive_from(remote_socket)        if len(remote_buffer):            print("[<==] Received %d bytes from remote." % len(remote_buffer))            hexdump(remote_buffer)            # 發送到響應處理函數            remote_buffer = response_handler(remote_buffer)            # 將響應發送到本地socket            client_socket.send(remote_buffer)            print("[<==] Sent to localhost.")        # 如果兩邊都沒有資料,關閉串連        if not len(local_buffer) or not len(remote_buffer):            client_socket.close()            remote_socket.close()            print("[*] No more data. Closing Connections.")            break
requset_handler() 修改請求包(依據實際需要添加函數功能)
# 對目標是遠程主機的請求進行修改def requset_handler(buffer):    # 執行包修改    return buffer
response_handler() 修改響應包(依據實際需要添加函數功能)
# 對目標是本地主機的響應進行修改def response_handler(buffer):    # 執行包修改    return buffer
receive_from() 使用recv()接收並返回資料
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
hexdump() 漂亮的十六進位匯出函數
def hexdump(src, length=16):    result = []    digits = 4 if isinstance(sec, 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))

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.