diff --git a/main.cc b/main.cc index fae49c4cb..f94646364 100644 --- a/main.cc +++ b/main.cc @@ -165,7 +165,7 @@ extern void set_program_name(const char *name); int main(int argc, char *argv[]) { /* The "real" main is nmap_main(). This function hijacks control at the beginning to do the following: - 3) Check the environment variable NMAP_ARGS. + 1) Check the environment variable NMAP_ARGS. 2) Check if Nmap was called with --resume. 3) Resume a previous scan or just call nmap_main. */ 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) {