1 
2 /***************************************************************************
3  * winfix.cc -- A few trivial windows-compatibility-related functions that *
4  * are specific to Nping.  Most of this has been moved into nbase so it can *
5  * be shared.                                                              *
6  *                                                                         *
7  ***********************IMPORTANT NMAP LICENSE TERMS************************
8  *                                                                         *
9  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
10  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
11  *                                                                         *
12  * This program is distributed under the terms of the Nmap Public Source   *
13  * License (NPSL). The exact license text applying to a particular Nmap    *
14  * release or source code control revision is contained in the LICENSE     *
15  * file distributed with that version of Nmap or source code control       *
16  * revision. More Nmap copyright/legal information is available from       *
17  * https://nmap.org/book/man-legal.html, and further information on the    *
18  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
19  * summarizes some key points from the Nmap license, but is no substitute  *
20  * for the actual license text.                                            *
21  *                                                                         *
22  * Nmap is generally free for end users to download and use themselves,    *
23  * including commercial use. It is available from https://nmap.org.        *
24  *                                                                         *
25  * The Nmap license generally prohibits companies from using and           *
26  * redistributing Nmap in commercial products, but we sell a special Nmap  *
27  * OEM Edition with a more permissive license and special features for     *
28  * this purpose. See https://nmap.org/oem                                  *
29  *                                                                         *
30  * If you have received a written Nmap license agreement or contract       *
31  * stating terms other than these (such as an Nmap OEM license), you may   *
32  * choose to use and redistribute Nmap under those terms instead.          *
33  *                                                                         *
34  * The official Nmap Windows builds include the Npcap software             *
35  * (https://npcap.org) for packet capture and transmission. It is under    *
36  * separate license terms which forbid redistribution without special      *
37  * permission. So the official Nmap Windows builds may not be              *
38  * redistributed without special permission (such as an Nmap OEM           *
39  * license).                                                               *
40  *                                                                         *
41  * Source is provided to this software because we believe users have a     *
42  * right to know exactly what a program is going to do before they run it. *
43  * This also allows you to audit the software for security holes.          *
44  *                                                                         *
45  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
46  * and add new features.  You are highly encouraged to submit your         *
47  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
48  * for possible incorporation into the main distribution. Unless you       *
49  * specify otherwise, it is understood that you are offering us very       *
50  * broad rights to use your submissions as described in the Nmap Public    *
51  * Source License Contributor Agreement. This is important because we      *
52  * fund the project by selling licenses with various terms, and also       *
53  * because the inability to relicense code has caused devastating          *
54  * problems for other Free Software projects (such as KDE and NASM).       *
55  *                                                                         *
56  * The free version of Nmap is distributed in the hope that it will be     *
57  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
58  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
59  * indemnification and commercial support are all available through the    *
60  * Npcap OEM program--see https://nmap.org/oem.                            *
61  *                                                                         *
62  ***************************************************************************/
63 
64 /* $Id: */
65 
66 #include "winfix.h"
67 #include "nping.h"
68 //#include "tcpip.h"
69 #include "NpingOps.h"
70 #include "output.h"
71 #include <Packet32.h>
72 #include <shellapi.h>
73 
74 #ifdef _MSC_VER
75 # include <delayimp.h>
76 #endif
77 
78 #ifdef _MSC_VER
79 #define DLI_ERROR VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
80 #endif
81 
82 #define PCAP_DRIVER_NONE 0
83 #define PCAP_DRIVER_WINPCAP 1
84 #define PCAP_DRIVER_NPCAP 2
85 
86 extern NpingOps o;
87 
88 /*   internal functions   */
89 static void win_cleanup(void);
90 static char pcaplist[4096];
91 
92 /* The code that has no preconditions to being called, so it can be
93    executed before even Nping options parsing (so o.getDebugging() and the
94    like don't need to be used.  Its main function is to do
95    WSAStartup() as some of the option parsing code does DNS
96    resolution */
win_pre_init()97 void win_pre_init() {
98 	WORD werd;
99 	WSADATA data;
100 
101 	werd = MAKEWORD( 2, 2 );
102 	if( (WSAStartup(werd, &data)) !=0 )
103 		fatal("failed to start winsock.\n");
104 }
105 
106 /* Check if the NPCAP service is running on Windows, and try to start it if it's
107    not. Return true if it was running or we were able to start it, false
108    otherwise. */
start_service(const char * svcname)109 static bool start_service(const char *svcname) {
110   SC_HANDLE scm, npf;
111   SERVICE_STATUS service;
112   bool npf_running;
113   int ret;
114   char startsvc[32];
115 
116   scm = NULL;
117   npf = NULL;
118 
119   scm = OpenSCManager(NULL, NULL, 0);
120   if (scm == NULL) {
121     error("Error in OpenSCManager");
122     goto quit_error;
123   }
124   npf = OpenService(scm, svcname, SC_MANAGER_CONNECT | SERVICE_QUERY_STATUS);
125   if (npf == NULL) {
126     /* No need to warn at this point: we'll check later
127     error("Error in OpenService");
128     */
129     goto quit_error;
130   }
131   if (!QueryServiceStatus(npf, &service)) {
132     error("Error in QueryServiceStatus");
133     goto quit_error;
134   }
135   npf_running = (service.dwCurrentState & SERVICE_RUNNING) != 0;
136   CloseServiceHandle(scm);
137   CloseServiceHandle(npf);
138 
139   if (npf_running) {
140     if (o.getDebugging() > DBG_1)
141       printf("%s service is already running.\n", svcname);
142     return true;
143   }
144 
145   /* Service is not running. Try to start it. */
146 
147   if (o.getDebugging() > DBG_1)
148     printf("%s service is already running.\n", svcname);
149 
150   Snprintf(startsvc, 32, "start %s", svcname);
151   ret = (int) ShellExecute(0, "runas", "net.exe", startsvc, 0, SW_HIDE);
152   if (ret <= 32) {
153     error("Unable to start %s service: ShellExecute returned %d.\n\
154 Resorting to unprivileged (non-administrator) mode.", svcname, ret);
155     return false;
156   }
157 
158   return true;
159 
160 quit_error:
161   if (scm != NULL)
162     CloseServiceHandle(scm);
163   if (npf != NULL)
164     CloseServiceHandle(npf);
165 
166   return false;
167 }
168 
169 /* Restrict where we're willing to load DLLs from to prevent DLL hijacking. */
init_dll_path()170 static void init_dll_path()
171 {
172 	BOOL (WINAPI *SetDllDirectory)(LPCTSTR);
173 
174 	SetDllDirectory = (BOOL (WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
175 	if (SetDllDirectory == NULL) {
176 		char nmapdir[MAX_PATH];
177 
178 		/* SetDllDirectory is not available before XP SP1. Instead, set
179 		   the current directory to the home of the executable (instead
180 		   of where a malicious DLL may be). */
181 		if (GetModuleFileName(NULL, nmapdir, sizeof(nmapdir)) == 0 ||
182 		    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
183 			pfatal("Error in GetModuleFileName");
184 		}
185 		if (SetCurrentDirectory(nmapdir))
186 			pfatal("Error in SetCurrentDirectory");
187 	} else {
188 		if (SetDllDirectory("") == 0)
189 			pfatal("Error in SetDllDirectory(\"\")");
190 	}
191 }
192 
193 /* If we find the Npcap driver, allow Nping to load Npcap DLLs from the "\System32\Npcap" directory. */
init_npcap_dll_path()194 static void init_npcap_dll_path()
195 {
196 	BOOL(WINAPI *SetDllDirectory)(LPCTSTR);
197 	char sysdir_name[512];
198 	int len;
199 
200 	SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
201 	if (SetDllDirectory == NULL) {
202 		pfatal("Error in SetDllDirectory");
203 	}
204 	else {
205 		len = GetSystemDirectory(sysdir_name, 480);	//	be safe
206 		if (!len)
207 			pfatal("Error in GetSystemDirectory (%d)", GetLastError());
208 		strcat(sysdir_name, "\\Npcap");
209 		if (SetDllDirectory(sysdir_name) == 0)
210 			pfatal("Error in SetDllDirectory(\"System32\\Npcap\")");
211 	}
212 }
213 
214 /* Requires that win_pre_init() has already been called, also that
215    options processing has been done so that o.debugging is
216    available */
win_init()217 void win_init()
218 {
219 	//   variables
220 	DWORD cb = 0;
221 	DWORD nRes;
222 	OSVERSIONINFOEX ver;
223 	PMIB_IPADDRTABLE pIp = 0;
224 	int i;
225 	int numipsleft;
226 	int pcap_driver = PCAP_DRIVER_NONE;
227 
228 	init_dll_path();
229 
230 	ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
231 	if(!GetVersionEx((LPOSVERSIONINFO)&ver))
232 	{
233 		ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
234 		if(!GetVersionEx((LPOSVERSIONINFO)&ver))
235 			fatal("GetVersionEx failed\n");
236 
237 		ver.wServicePackMajor = 0;
238 		ver.wServicePackMinor = 0;
239 	}
240 
241 
242 	//   Try to initialize winpcap
243 #ifdef _MSC_VER
244 	__try
245 #endif
246 	{
247 		ULONG len = sizeof(pcaplist);
248 
249     if(o.getDebugging() >= DBG_2) printf("Trying to initialize Windows pcap engine\n");
250 
251     /* o.getIsRoot() will be false at this point if the user asked for
252        --unprivileged. In that case don't bother them with a
253        potential UAC dialog when starting NPF. */
254     if (o.isRoot()) {
255       if (start_service("npcap"))
256         pcap_driver = PCAP_DRIVER_NPCAP;
257       else if (start_service("npf"))
258         pcap_driver = PCAP_DRIVER_WINPCAP;
259       else {
260         if(o.getDebugging() >= DBG_0) {
261           error("Unable to start either npcap or npf service");
262         }
263         pcap_driver = PCAP_DRIVER_NONE;
264         o.setHavePcap(false);
265       }
266     }
267 
268     if (pcap_driver == PCAP_DRIVER_NPCAP)
269       init_npcap_dll_path();
270 
271 		PacketGetAdapterNames(pcaplist, &len);
272 
273 #ifdef _MSC_VER
274 		if(FAILED(__HrLoadAllImportsForDll("wpcap.dll")))
275 		{
276 			error("WARNING: Failed to load wpcap.dll.  Nmap may not function.\n");
277 			o.setHavePcap(false);
278 		}
279 #endif
280 		if(o.getDebugging() >= DBG_1)
281 			printf("wpcap.dll present, library version: %s\n", pcap_lib_version());
282 
283 	}
284 #ifdef _MSC_VER
285 	__except (1) {
286 			error("WARNING: Could not import all necessary Npcap functions. You may need to upgrade to the latest version from https://npcap.org. Resorting to connect() mode -- Nmap may not function completely");
287 		o.setHavePcap(false);
288 		}
289 #endif
290 
291 	if (!o.havePcap())
292 		o.setIsRoot(0);
293 	atexit(win_cleanup);
294 }
295 
296 
win_cleanup(void)297 static void win_cleanup(void)
298 {
299   WSACleanup();
300 }
301 
fork()302 int fork()
303 {
304 	fatal("no fork for you!\n");
305 	return 0;
306 }
307