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