繼勒索病毒“永恆之藍”445埠被封之後,在公網實現smb檔案共享

云云生息發表於2019-02-01

背景

在最近專案中需要使用到windows smb檔案共享,並且該專案過程不允許重啟系統,其使用到的TCP連線埠為445,該專案測試環境一直處在內部網路,所以一開始沒發現什麼問題,專案進展到一定程度後,需要在公網環境中進行模擬測試,突然發現smb通道不能使用了,查了半天,發現是ISP把445埠給禁了,這讓整個專案處於一個非常尷尬的處境,同時發現很多同行遇到了在原專案中使用了smb檔案共享現在公網環境也無法正常工作,所以需要找到一個優雅的方法來完美解決這個問題。

找出SMB監聽445的服務

按常理會把smb通道指定別的埠進行通訊即可,可研究半天,發現net use使用smb時,無法指定傳輸埠,其原理是在windows開機啟動時載入netbt驅動,smb服務使用預設埠445進行監聽,而作為smb客戶端也是用這個埠進行遠端連線,google半天,是有那麼一個登錄檔可以改這個初始化埠,應該在:

HKLM:\SYSTEM\CurrentControlSet\Services\NetBT

按正常思路,修改登錄檔,重啟對應服務。那接下來使用netstat命令檢視一下監聽445埠的程式:
在這裡插入圖片描述
可以看出是pid為4的程式進行監聽,從工作管理員上看是名叫System,備註"NT Kernel & System",這玩意兒要重啟,豈不是直接告訴你係統重啟,但是該專案最大的特點就是不允許重啟系統,事情發展到這個形態,不由得讓我們Linux開發出身的程式設計師對一個封閉系統的感嘆,唏噓。

埠代理

但問題總要解決,這個時候我想到了埠代理/埠轉發,只要網路流量在公網上不使用445埠就可以,我就設計出了一個思路:
在這裡插入圖片描述
Windows smb客戶端訪問本地445:

net use \\127.0.0.1\C$

1.客戶端通過訪問本地445,埠轉發成訪問遠端,將訪問本地445轉發成訪問遠端8445埠,假設smb伺服器IP為192.168.1.81:

netsh interface portproxy add v4tov4 listenport=445 connectaddress=192.168.1.81 connectport=8445

2.服務端由訪問8445,埠轉發成訪問本地445:

netsh interface portproxy add v4tov4 listenport=8445 connectaddress=192.168.1.81 connectport=445

動手操作,按圖描述的結構進行配置,服務端檢視埠狀態,可看到已有8445埠在監聽
在這裡插入圖片描述
而客戶端檢視445埠狀態,依然是pid為4的服務在監聽,進行net use連線測試,連上的並不是遠端的smb服務,而是本地smb服務。
經分析原理,配置埠代理後,被代理的埠會建立一個監聽狀態,可是本地已有smb服務監聽了445埠,所以在客戶端側埠代理功能相當於失效。

再瞭解一下windows防火牆架構,如下是示意圖:
在這裡插入圖片描述
前面所配置的埠代理應該屬於Ipnat.sys模組,但是當我們在客戶端在使用者態使用net use連線127.0.0.1的smb的時候,在windows sockets driver(winsock.dll)時轉到對應的本地smb應用服務,流量請求根本到不了Ipnat.sys模組,導致埠代理也就不會起作用。

埠攔截、埠代理

通過windows防火牆架構理清楚原因後,我們就想是否有別的辦法在winsock.dll層面將流量報文攔截下來,然後轉移到埠代理中去呢。
果不其然,google上找到了我們需要的驅動WinDivert:

windows 資料包轉移 (WinDivert) 是一種使用者模式的資料包捕獲和轉移包,WinDivert 允許使用者模式應用程式捕獲、修改、丟棄從 windows 網路堆疊傳送的網路資料包。

基於這個工具,在github找到衍生開源專案divertTCPconn
這個專案利用WinDivert驅動可以把指定目的埠的流量轉換成訪問本地其它埠,這不就正是我們想要的東西,那問題基本解決了,躍躍欲試,重新整理架構圖:
在這裡插入圖片描述
把WinDivert和DivertTCPconn結合編譯、執行,將訪問遠端445埠的流量轉換成訪問本地8445,然後再寫一條埠代理從本地8445代理到遠端8445,對應命令如下:

埠攔截

divertTCPconn.exe 445 8445

埠代理
假設遠端smb伺服器IP為192.168.1.81

netsh interface portproxy add v4tov4 listenport=8445 connectaddress=192.168.1.81 connectport=8445

經過客戶端smb連線

net use \\192.168.1.81\C$

測試發現,流量並沒有走8445埠,後面對divertTCPconn專案原始碼進行分析,發現在使用過濾器時,針對的是inbound&dst-port=445進行匹配。但對於我們這種情景來說,本地訪問遠端445是屬於outbound&dst-port=445,趕緊把divertTCPconn程式碼修改:
在這裡插入圖片描述
經再次測試,在伺服器之間走的是8445埠,而客戶端和伺服器內部也能夠將445和8445進行轉換,總結本案例是通過使用者態埠攔截加埠重定向技術,最終達到我們想要的效果,並且在整個過程中,不用修改登錄檔,不用重啟系統。

相關文章