實現lcx功能的參考方法
1 LCX簡介
lcx是一款強大的內網埠轉發工具,用於將內網主機開放的內部埠對映到外網主機(有公網IP)任意埠。它是一款命令列工具,當然也可以在有許可權的webshell下執行,正因如此lcx常被認為是一款黑客入侵工具,lcx在內網入侵滲透中起著重要的角色。lcx進行埠轉發的原理就是使不同埠之間形成一個迴路。它常用於外網連線內網3389等埠。
2 LCX實現思路
2.1 基於命令的LCX
在windows和linux 中都存在對於埠的轉發命令,人們習慣於稱呼為對映,英文為DNAT(Destination Network Address Translation),官方名稱為目的地址轉換,這種方式在防火牆和路由器中比較常見。
2.1.1 windows 目的地址轉換命令簡介
Windows下使用netsh命令,來進行目的地址轉換。netsh(Network Shell) 是一個windows系統本身提供的功能強大的網路配置命令列工具。它允許從本地或遠端顯示或修改當前正在執行的計算機的網路配置。Netsh 命令的強大,目的地址對映只是其中小部分功能。如此強大的命令如何使用呢?
命令 |
含義 |
netsh interface portproxy add v4tov4 listenaddress=192.168.1.8 listenport=14941 connectaddress=192.168.1.118 connectport=1494 |
在IPV4下將監聽本地IP 192.168.1.8:14941,接受到的資料轉發給192.168.1.118:1494。 |
netsh interface portproxy delete v4tov4 listenaddress=192.168.1.8 listenport=33891 |
在IPV4下刪除監聽本地IP 192.168.1.8:33891 |
netsh interface portproxy show v4tov4 |
檢視在IPV4下配置的埠轉發的策略 |
2.1.2 linux 目的地址轉換命令簡介
Linux下使用iptables命令,來進行目的地址轉換。在預設情況下,linux會禁用此類功能,需要手動開啟。iptables是Linux 核心整合的 IP 資訊包過濾系統,也就是人們常說的LINUX自帶防火牆,經常被用於配置ACL(Access Control List)訪問控制列表。iptables在不同的LINUX版本中存在不同的名稱。2.0.X核心:ipfwadm,2.2.X核心:ipchains,2.4.X核心:iptables。目前linux版本基本為2.4.x以上,低版本的linux比較少見,下面講解的命令,在2.4.x以上的核心版本linux中有效。
l 開啟目的地址轉發功能
n 臨時修改法: echo 1 >/proc/sys/net/ipv4/ip_forward
n 永久修改法: vi /etc/sysctl.conf,net.ipv4.ip_forward = 1找到並修改值為1,sysctl –p(使之立即生效)
l 假設使用者訪問172.16.4.247:728時我想讓它轉發到172.16.4.97:80:
n # iptables -t nat -A PREROUTING -p tcp -d 113.108.110.61 --dport 728 -j DNAT --to-destination 172.16.4.97:80
n # iptables -t nat -A POSTROUTING -p tcp -s 172.16.4.97 --sport 80 -j SNAT --to-source 172.16.4.247
n # service iptables save(將當前規則儲存到 /etc/sysconfig/iptables)
l 本機間不同的埠轉發:
n iptables -t nat -A PREROUTING -p tcp --dport 729 -j REDIRECT --to-ports 80
n service iptables save
n service iptables restart
2.2自實現 LCX
基於命令的 LCX存在無法繞過防毒軟體的攔截,並且需要管理員許可權等問題。所以大多數 LCX 是使用自實現目的地址轉換的方式編寫的工具。簡單說下目的地址轉換的原理。
目的地址轉換的基本工作原理是當公網主機同一 IP包傳送至存在目的地址轉換策略的主機埠時,將 IP 包中的目的地址以及埠進行替換,並且代傳送給替換後的地址和埠。
採用 PYTHON編寫 LCX 工具,工具的使用效果感覺上是非常不錯的,但是 ptyhon 程式打包成 exe 的體積相對比較龐大。筆者推薦使用 asyncore 模組, Python 的 asyncore 模組提供了以非同步的方式寫入套接字服務的客戶端和伺服器的基礎結構,使用比較方便。這個模組是一個以時間驅動的非同步 I/O ,與 C++ 的事件選擇模型相似。每當發生寫、讀事件會交由我們重寫的事件函式進行處理。下面開始編寫自實現的 LCX 。
1、第一步需要先定義 Forwarder :
class PortForwarder(asyncore.dispatcher):#監聽本地 def __init__(self, ip, port, remoteip, remoteport, backlog=5): asyncore.dispatcher.__init__(self) self.remoteip = remoteip self.remoteport = remoteport self.create_socket(socket.AF_INET, socket.SOCK_STREAM)#建立一個套接字物件 self.set_reuse_addr()#設定地址埠可重用 self.bind((ip, port))#繫結本地ip與埠 self.listen(backlog)#開始監聽 def handle_accept(self):#處理接受 conn, addr = self.accept()#等待接受 print "Connected to:", addr Sender(Receiver(conn), self.remoteip, self.remoteport)
2、第二步呼叫 Forwarder, 並且執行 asyncore.loop (用於迴圈監聽網路事件) :
PortForwarder(local_host, local_port, remote_host, remote_port) asyncore.loop()
3、需要接收本地的請求,發給遠端主機:
class Receiver(asyncore.dispatcher):#接受本地請求資料,傳送給遠端主機 def __init__(self, conn): asyncore.dispatcher.__init__(self, conn) #self被初始化為該連線客戶端socket #getpeername函式用於獲取與某個套接字關聯的外地協議地址 self.from_remote_buffer = ''#儲存來自遠端主機資料 self.to_remote_buffer = ''#儲存本地請求資料 self.sender = None def handle_connect(self): pass def handle_read(self):#接受本地請求 read = self.recv(BUFSIZE) self.to_remote_buffer += read; print "receiver read", self.to_remote_buffer def writable(self):#判斷是否有來自遠端主機的資料,如果有,呼叫handle_write return (len(self.from_remote_buffer) > 0) def handle_write(self):#傳送來自遠端主機的資料給本地主機 sent = self.send(self.from_remote_buffer) print "receiver sent", sent self.from_remote_buffer = self.from_remote_buffer[sent:]#傳送完成後清空資料 def handle_close(self): self.close() if self.sender: self.sender.close()
4、需要接受遠端主機資料,發給本地請求:
class Sender(asyncore.dispatcher):#接受遠端主機資料,傳送本地請求資料 def __init__(self, receiver, remoteaddr, remoteport): asyncore.dispatcher.__init__(self) self.receiver = receiver#建立Sender與Receiver之間聯絡 receiver.sender = self#建立Sender與Receiver之間聯絡 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)#建立套接字 self.connect((remoteaddr, remoteport))#連線遠端主機 def handle_connect(self): pass def handle_read(self):#接受來自遠端主機的資料 read = self.recv(BUFSIZE) self.receiver.from_remote_buffer += read print "sender read", self.receiver.from_remote_buffer def writable(self):#判斷是否有本地請求要傳送,如果有,呼叫handle_write if len(self.receiver.to_remote_buffer) > 0: self.receiver.to_remote_buffer = self.receiver.to_remote_buffer.replace\ (LOCAL_SERVER_HOST + ':' + str(LOCAL_SERVER_PORT), REMOTE_SERVER_HOST) #修改本地請求資料,將本地主機中host改為遠端主機地址 return (len(self.receiver.to_remote_buffer) > 0) def handle_write(self):#傳送本地請求資料 sent = self.send(self.receiver.to_remote_buffer) print "sender write",sent self.receiver.to_remote_buffer = self.receiver.to_remote_buffer[sent:] def handle_close(self): self.close() self.receiver.close()
到此一個簡單的LCX程式就完成了,如果新增一些命令列互動提示功能,對於使用者將更加友好。
3 總結
對於LCX原理以及實現思路,簡單整理這麼多。目前來說LCX這類程式,已經被防毒軟體列為木馬。python編寫程式的優勢在於能夠繞過防毒軟體的查殺。對於目的地址轉發這項工作來說所需的程式碼比較少量,但是由於PYTHON打包成EXE時會內建編譯器,所以EXE程式會相對比較大。如果將部分程式碼進行優化,能夠比較好的縮減程式碼量。不過雖然程式碼量可能會有所減少,但是打包後的體積依舊比較大。對於這點目前並尚未找到妥善的解決方法。