1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Support Npcap 0.9983's new loopback behavior

This commit is contained in:
dmiller
2019-09-03 19:13:14 +00:00
parent ef2825b3bc
commit 8d59507aad
3 changed files with 191 additions and 21 deletions

View File

@@ -1,5 +1,10 @@
#Nmap Changelog ($Id$); -*-text-*-
o [Windows] Add support for the new loopback behavior in Npcap 0.9983. This
enables Nmap to scan localhost on Windows without needing the Npcap Loopback
Adapter to be installed, which was a source of problems for some users.
[Daniel Miller]
o [NSE][GH#1720] Function marshall_dom_sid2 in library msrpctypes was not
correctly populating ID Authority. [nnposter]

View File

@@ -2411,3 +2411,135 @@ index 434142e..31b9f8c 100644
o REVERTED the change that added a mutex protecting calls to OpenServiceA. We
are optimistic that Npcap does not have the reported problem.
o Add support for new loopback behavior in Npcap 0.9983. There is no KM-TEST
adapter in GetAdaptersAddresses in this case.
diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c
index 1399db2..352da4c 100644
--- a/libdnet-stripped/src/intf-win32.c
+++ b/libdnet-stripped/src/intf-win32.c
@@ -26,6 +26,7 @@
#include <Ntddndis.h>
int g_has_npcap_loopback = 0;
+#define _DEVICE_PREFIX "\\Device\\"
struct ifcombo {
struct {
@@ -214,6 +215,10 @@ _adapter_address_to_entry(intf_t *intf, IP_ADAPTER_ADDRESSES *a,
#define NPCAP_SERVICE_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Services\\npcap"
+/* The name of the Npcap loopback adapter is stored in the npcap service's
+ * Registry key in the LoopbackAdapter value. For legacy loopback support, this
+ * is a name like "NPF_{GUID}", but for newer Npcap the name is "NPF_Loopback"
+ */
int intf_get_loopback_name(char *buffer, int buf_size)
{
HKEY hKey;
@@ -252,43 +257,65 @@ _update_tables_for_npcap_loopback(IP_ADAPTER_ADDRESSES *p)
IP_ADAPTER_ADDRESSES *a_original_loopback_prev = NULL;
IP_ADAPTER_ADDRESSES *a_original_loopback = NULL;
IP_ADAPTER_ADDRESSES *a_npcap_loopback = NULL;
- char npcap_loopback_name[1024];
- int has_npcap_loopback = 0;
+ static char npcap_loopback_name[1024] = {0};
- g_has_npcap_loopback = has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024);
- if (has_npcap_loopback == 0)
+ /* Don't bother hitting the registry every time. Not ideal for long-running
+ * processes, but works for Nmap. */
+ if (npcap_loopback_name[0] == '\0')
+ g_has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024);
+ if (g_has_npcap_loopback == 0)
return p;
if (!p)
return p;
+ /* Loop through the addresses looking for the dummy loopback interface from Windows. */
for (a = p; a != NULL; a = a->Next) {
if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
+ /* Dummy loopback. Keep track of it. */
a_original_loopback = a;
a_original_loopback_prev = a_prev;
}
- else if (strcmp(a->AdapterName, npcap_loopback_name + strlen("\\Device\\")) == 0) {
+ else if (strcmp(a->AdapterName, npcap_loopback_name + strlen(_DEVICE_PREFIX) - 1) == 0) {
+ /* Legacy loopback adapter. The modern one doesn't show up in GetAdaptersAddresses. */
a_npcap_loopback = a;
}
a_prev = a;
}
- if (!a_original_loopback || !a_npcap_loopback)
+ /* If there's no loopback on this system, something's wrong. Windows is
+ * supposed to create this. */
+ if (!a_original_loopback)
return p;
-
- a_npcap_loopback->IfType = a_original_loopback->IfType;
- a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress;
- a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix;
- memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN);
- if (a_original_loopback_prev) {
- a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next;
+ /* If we didn't find the legacy adapter, use the modern adapter name. */
+ if (!a_npcap_loopback) {
+ /* Overwrite the name we got from the Registry, in case it's a broken legacy
+ * install, in which case we'll never find the legacy adapter anyway. */
+ strlcpy(npcap_loopback_name, _DEVICE_PREFIX "NPF_Loopback", 1024);
+ /* Overwrite the AdapterName from the system's own loopback adapter with
+ * the NPF_Loopback name. This is what we use to open the adapter with
+ * Packet.dll later. */
+ a_original_loopback->AdapterName = npcap_loopback_name + sizeof(_DEVICE_PREFIX) - 1;
return p;
}
- else if (a_original_loopback == p) {
- return a_original_loopback->Next;
- }
else {
- return p;
+ /* Legacy loopback adapter was found. Copy some key info from the system's
+ * loopback adapter. */
+ a_npcap_loopback->IfType = a_original_loopback->IfType;
+ a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress;
+ a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix;
+ memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN);
+ /* Unlink the original loopback adapter from the list. We'll use Npcap's instead. */
+ if (a_original_loopback_prev) {
+ a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next;
+ return p;
+ }
+ else if (a_original_loopback == p) {
+ return a_original_loopback->Next;
+ }
+ else {
+ return p;
+ }
}
}
@@ -551,11 +578,17 @@ intf_get_pcap_devname_cached(const char *intf_name, char *pcapdev, int pcapdevle
for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) {
char *name;
- if (pdev->name == NULL)
- continue;
- name = strchr(pdev->name, '{');
- if (name == NULL)
+ if (pdev->name == NULL || strlen(pdev->name) < sizeof(_DEVICE_PREFIX))
continue;
+ /* "\\Device\\NPF_{GUID}"
+ * "\\Device\\NPF_Loopback"
+ * Find the '{'after device prefix.
+ */
+ name = strchr(pdev->name + sizeof(_DEVICE_PREFIX) - 1, '{');
+ if (name == NULL) {
+ /* If no GUID, just match the whole device name */
+ name = pdev->name + sizeof(_DEVICE_PREFIX) - 1;
+ }
if (strcmp(name, a->AdapterName) == 0)
break;
}

View File

@@ -26,6 +26,7 @@
#include <Ntddndis.h>
int g_has_npcap_loopback = 0;
#define _DEVICE_PREFIX "\\Device\\"
struct ifcombo {
struct {
@@ -214,6 +215,10 @@ _adapter_address_to_entry(intf_t *intf, IP_ADAPTER_ADDRESSES *a,
#define NPCAP_SERVICE_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Services\\npcap"
/* The name of the Npcap loopback adapter is stored in the npcap service's
* Registry key in the LoopbackAdapter value. For legacy loopback support, this
* is a name like "NPF_{GUID}", but for newer Npcap the name is "NPF_Loopback"
*/
int intf_get_loopback_name(char *buffer, int buf_size)
{
HKEY hKey;
@@ -252,34 +257,55 @@ _update_tables_for_npcap_loopback(IP_ADAPTER_ADDRESSES *p)
IP_ADAPTER_ADDRESSES *a_original_loopback_prev = NULL;
IP_ADAPTER_ADDRESSES *a_original_loopback = NULL;
IP_ADAPTER_ADDRESSES *a_npcap_loopback = NULL;
char npcap_loopback_name[1024];
int has_npcap_loopback = 0;
static char npcap_loopback_name[1024] = {0};
g_has_npcap_loopback = has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024);
if (has_npcap_loopback == 0)
/* Don't bother hitting the registry every time. Not ideal for long-running
* processes, but works for Nmap. */
if (npcap_loopback_name[0] == '\0')
g_has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024);
if (g_has_npcap_loopback == 0)
return p;
if (!p)
return p;
/* Loop through the addresses looking for the dummy loopback interface from Windows. */
for (a = p; a != NULL; a = a->Next) {
if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
/* Dummy loopback. Keep track of it. */
a_original_loopback = a;
a_original_loopback_prev = a_prev;
}
else if (strcmp(a->AdapterName, npcap_loopback_name + strlen("\\Device\\")) == 0) {
else if (strcmp(a->AdapterName, npcap_loopback_name + strlen(_DEVICE_PREFIX) - 1) == 0) {
/* Legacy loopback adapter. The modern one doesn't show up in GetAdaptersAddresses. */
a_npcap_loopback = a;
}
a_prev = a;
}
if (!a_original_loopback || !a_npcap_loopback)
/* If there's no loopback on this system, something's wrong. Windows is
* supposed to create this. */
if (!a_original_loopback)
return p;
/* If we didn't find the legacy adapter, use the modern adapter name. */
if (!a_npcap_loopback) {
/* Overwrite the name we got from the Registry, in case it's a broken legacy
* install, in which case we'll never find the legacy adapter anyway. */
strlcpy(npcap_loopback_name, _DEVICE_PREFIX "NPF_Loopback", 1024);
/* Overwrite the AdapterName from the system's own loopback adapter with
* the NPF_Loopback name. This is what we use to open the adapter with
* Packet.dll later. */
a_original_loopback->AdapterName = npcap_loopback_name + sizeof(_DEVICE_PREFIX) - 1;
return p;
}
else {
/* Legacy loopback adapter was found. Copy some key info from the system's
* loopback adapter. */
a_npcap_loopback->IfType = a_original_loopback->IfType;
a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress;
a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix;
memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN);
/* Unlink the original loopback adapter from the list. We'll use Npcap's instead. */
if (a_original_loopback_prev) {
a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next;
return p;
@@ -291,6 +317,7 @@ _update_tables_for_npcap_loopback(IP_ADAPTER_ADDRESSES *p)
return p;
}
}
}
static int
_refresh_tables(intf_t *intf)
@@ -551,11 +578,17 @@ intf_get_pcap_devname_cached(const char *intf_name, char *pcapdev, int pcapdevle
for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) {
char *name;
if (pdev->name == NULL)
continue;
name = strchr(pdev->name, '{');
if (name == NULL)
if (pdev->name == NULL || strlen(pdev->name) < sizeof(_DEVICE_PREFIX))
continue;
/* "\\Device\\NPF_{GUID}"
* "\\Device\\NPF_Loopback"
* Find the '{'after device prefix.
*/
name = strchr(pdev->name + sizeof(_DEVICE_PREFIX) - 1, '{');
if (name == NULL) {
/* If no GUID, just match the whole device name */
name = pdev->name + sizeof(_DEVICE_PREFIX) - 1;
}
if (strcmp(name, a->AdapterName) == 0)
break;
}