diff --git a/CHANGELOG b/CHANGELOG
index a68030218..370824b8e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,7 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [Nping] Nping is now fully compatible with Npcap. [Daniel Miller]
+
o [GH#279][Zenmap] Added a legend for the Topography window. [Suraj Hande]
o [NSE] Added clamav-exec to detect ClamAV servers vulnerable to unauthorized
diff --git a/nping/nping.vcxproj b/nping/nping.vcxproj
index 8b9d708d0..619079711 100644
--- a/nping/nping.vcxproj
+++ b/nping/nping.vcxproj
@@ -80,7 +80,7 @@
true
..\mswin32\lib;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)
%(IgnoreSpecificDefaultLibraries)
- wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs)
+ packet.dll;wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs)
true
.\Debug/nmap.pdb
Console
@@ -121,7 +121,7 @@
true
..\mswin32\lib;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)
%(IgnoreSpecificDefaultLibraries)
- wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs)
+ packet.dll;wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs)
.\Release/nping.pdb
Console
true
diff --git a/nping/winfix.cc b/nping/winfix.cc
index bd3b60016..da77158da 100644
--- a/nping/winfix.cc
+++ b/nping/winfix.cc
@@ -143,6 +143,10 @@
#define DLI_ERROR VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
#endif
+#define PCAP_DRIVER_NONE 0
+#define PCAP_DRIVER_WINPCAP 1
+#define PCAP_DRIVER_NPCAP 2
+
extern NpingOps o;
/* internal functions */
@@ -163,14 +167,15 @@ void win_pre_init() {
fatal("failed to start winsock.\n");
}
-/* Check if the NPF service is running on Windows, and try to start it if it's
+/* Check if the NPCAP service is running on Windows, and try to start it if it's
not. Return true if it was running or we were able to start it, false
otherwise. */
-static bool start_npf() {
+static bool start_service(const char *svcname) {
SC_HANDLE scm, npf;
SERVICE_STATUS service;
bool npf_running;
int ret;
+ char startsvc[32];
scm = NULL;
npf = NULL;
@@ -180,7 +185,7 @@ static bool start_npf() {
error("Error in OpenSCManager");
goto quit_error;
}
- npf = OpenService(scm, "npf", SC_MANAGER_CONNECT | SERVICE_QUERY_STATUS);
+ npf = OpenService(scm, svcname, SC_MANAGER_CONNECT | SERVICE_QUERY_STATUS);
if (npf == NULL) {
error("Error in OpenService");
goto quit_error;
@@ -195,19 +200,20 @@ static bool start_npf() {
if (npf_running) {
if (o.getDebugging() > DBG_1)
- printf("NPF service is already running.\n");
+ printf("%s service is already running.\n", svcname);
return true;
}
- /* NPF is not running. Try to start it. */
+ /* Service is not running. Try to start it. */
if (o.getDebugging() > DBG_1)
- printf("NPF service is not running.\n");
+ printf("%s service is already running.\n", svcname);
- ret = (int) ShellExecute(0, "runas", "net.exe", "start npf", 0, SW_HIDE);
+ Snprintf(startsvc, 32, "start %s", svcname);
+ ret = (int) ShellExecute(0, "runas", "net.exe", startsvc, 0, SW_HIDE);
if (ret <= 32) {
- error("Unable to start NPF service: ShellExecute returned %d.\n\
-Resorting to unprivileged (non-administrator) mode.", ret);
+ error("Unable to start %s service: ShellExecute returned %d.\n\
+Resorting to unprivileged (non-administrator) mode.", svcname, ret);
return false;
}
@@ -246,6 +252,27 @@ static void init_dll_path()
}
}
+/* If we find the Npcap driver, allow Nmap to load Npcap DLLs from the "\System32\Npcap" directory. */
+static void init_npcap_dll_path()
+{
+ BOOL(WINAPI *SetDllDirectory)(LPCTSTR);
+ char sysdir_name[512];
+ int len;
+
+ SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
+ if (SetDllDirectory == NULL) {
+ pfatal("Error in SetDllDirectory");
+ }
+ else {
+ len = GetSystemDirectory(sysdir_name, 480); // be safe
+ if (!len)
+ pfatal("Error in GetSystemDirectory (%d)", GetLastError());
+ strcat(sysdir_name, "\\Npcap");
+ if (SetDllDirectory(sysdir_name) == 0)
+ pfatal("Error in SetDllDirectory(\"System32\\Npcap\")");
+ }
+}
+
/* Requires that win_pre_init() has already been called, also that
options processing has been done so that o.debugging is
available */
@@ -258,6 +285,7 @@ void win_init()
PMIB_IPADDRTABLE pIp = 0;
int i;
int numipsleft;
+ int pcap_driver;
init_dll_path();
@@ -283,6 +311,17 @@ void win_init()
ULONG len = sizeof(pcaplist);
if(o.getDebugging() >= DBG_2) printf("Trying to initialize WinPcap\n");
+
+ if (start_service("npcap"))
+ pcap_driver = PCAP_DRIVER_NPCAP;
+ else if (start_service("npf"))
+ pcap_driver = PCAP_DRIVER_WINPCAP;
+ else
+ pcap_driver = PCAP_DRIVER_NONE;
+
+ if (pcap_driver == PCAP_DRIVER_NPCAP)
+ init_npcap_dll_path();
+
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
wait = WaitForSingleObject(pcapMutex, INFINITE);
PacketGetAdapterNames(pcaplist, &len);
@@ -305,7 +344,7 @@ void win_init()
--unprivileged. In that case don't bother them with a
potential UAC dialog when starting NPF. */
if (o.isRoot())
- o.setHavePcap(o.havePcap() && start_npf());
+ o.setHavePcap(o.havePcap() && ((bool) pcap_driver));
}
#ifdef _MSC_VER
__except (1) {