起因
EnableExcludedPortRange这个东西不管用了
而且WSL开启之后占用端口奇多无比,无法正常使用
首次探索(2021.10.27)
- 根据各种信息,许多人说sc stop winnat一下就好,https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to
- 确实这样可以,但是这么操作完WSL就一直是坏的,重启才能恢复
- 逆向winnat.sys入手,通过函数名找到分配端口的函数是SlbNatAllocPortsWsk,每次分配PortChunkSize大小的端口chunk,默认大小100
- 改成40之后,WSL网络并发性能明显下降,无法apt更新
- 调研了一下WinNat的运作方式,认为应该都是通过Nsi的一套东西走的, 所以找到WinNat对应的moduleID:NPI_MS_WINNAT_MODULEID,找到GUID:{eb004a209b1a11d4-9123-0050047759bc},全局搜索找到了这些dll
- gns.dll:Guest Network Service
- HostNetSvc.dll:Host Network Service
- ipnathlp.dll:IP Nat Helper, SharedAccess服务
- ipxlatcfg.dll
- netiomig.dll
- wbem\NetNat.dll:PowerShell MSFT_NetNat的provider
- netttcim.dll
二次探索(2021.12.28)
- 这次建立了Windows 11 Insider的虚拟机,这样就可以进行内核调试打断点了
- NetNatExternalAddress的创建在winnat中,excludedportrange端口分配最后有SlbNatAllocPortsWsk执行
SlbNatCreateExternalAddressForFamily
→SlbNatAllocPortCallback
→SlbNatAllocatePorts
→SlbNatAllocPortsWsk
SlbNatCreateStaticMapping
→SlbNatAllocatePorts
- 断点断在SlbNatAllocPortsWsk,找到用户态调用均位于ipnathlp.dll内,由RPC调用该dll,随后该dll触发至内核中
bp winnat!SlbNatAllocPortsWsk
- HostNetSvc.dll中在
HNS::Service::Resource::ICSResource::StartSharing
调用V2IpNatHlpStartSharingInternalPrefix
,通过HNS::Service::Resource::ICSResource::SharingDisabled
标志位控制是否分配动态地址 - DisableSharing标志位的计算过于复杂,无法逆向,在网络描述JSON中存在,但是修改后覆盖上去不生效
- 直接patch这个方法为全局disable sharing,WSL无网络
- 通过HNS的接口HCN API管理HNS的网络
- https://github.com/skorhone/wsl2-custom-network
- https://github.com/Biswa96/hvtool
- 观测到一个Default Switch、一个WSL,还有多个vEthernet相关的网络
- 删除掉之后,vEthernet相关的网络还会接着重新生成
- x64dbg断入WmiPrvSe断点
V2IpNatHlpStartSharingInternalPrefix
,在重新生成时回溯找到最初的栈帧 - 发现
HNS::Service::Core::IsAdapterSuitableForMirroring
控制某个adapter具体生成不生成对应的HCN网络 - Patch这个函数为永远不生成,成功
- 随后发现Default Switch也是可以直接删除的,全部删除后,占用端口仅剩2000余个,不影响
三次探索(2022.6.5)
- 重新分析了
HNS::Service::Resource::ICSResource::SharingDisabled
,发现Flags的128控制是否开启Sharing