]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/bloda.cc
* Makefile.in (cygcheck.exe): Link against ntdll.
[newlib-cygwin.git] / winsup / utils / bloda.cc
1 /* bloda.cc
2
3 Copyright 2007 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #define cygwin_internal cygwin_internal_dontuse
12 #include <stdio.h>
13 #include <assert.h>
14 #include <windows.h>
15 #include <ntdef.h>
16 #include <ddk/ntstatus.h>
17 #include <ddk/ntapi.h>
18 #undef cygwin_internal
19
20 #undef DEBUGGING
21 #ifdef DEBUGGING
22 #define dbg_printf(ARGS) printf ARGS ; fflush (NULL)
23 #else /* !DEBUGGING */
24 #define dbg_printf(ARGS) do { } while (0)
25 #endif /* ?DEBUGGING */
26
27 /* This module detects applications from the Big List of Dodgy Apps,
28 a list of applications that have at some given time been shown to
29 interfere with the operation of cygwin. It detects the presence of
30 applications on the system by looking for any of four traces an
31 installation might leave: 1) registry keys, 2) files on disk
32 3) running executables 4) loaded dlls or drivers.
33
34 At the time of writing, the BLODA amounts to:-
35
36 Sonic Solutions burning software containing DLA component
37 Norton/MacAffee/Symantec antivirus or antispyware
38 Logitech webcam software with "Logitech process monitor" service
39 Kerio, Agnitum or ZoneAlarm Personal Firewall
40 Iolo System Mechanic/AntiVirus/Firewall
41 LanDesk
42 Windows Defender
43 Embassy Trust Suite fingerprint reader software containing wxvault.dll
44 ByteMobile laptop optimization client
45
46 A live version is now being maintained in the Cygwin FAQ, at
47 http://cygwin.com/faq/faq.using.html#faq.using.bloda
48
49 */
50
51 enum bad_app
52 {
53 SONIC, NORTON, MACAFFEE, SYMANTEC,
54 LOGITECH, KERIO, AGNITUM, ZONEALARM,
55 IOLO, LANDESK, WINDEFENDER, EMBASSYTS,
56 BYTEMOBILE
57 };
58
59 struct bad_app_info
60 {
61 enum bad_app app_id;
62 const char *details;
63 char found_it;
64 };
65
66 enum bad_app_det_method
67 {
68 HKLMKEY, HKCUKEY, FILENAME, PROCESSNAME, HOOKDLLNAME
69 };
70
71 struct bad_app_det
72 {
73 enum bad_app_det_method type;
74 const char *param;
75 enum bad_app app;
76 };
77
78 static const struct bad_app_det dodgy_app_detects[] =
79 {
80 { PROCESSNAME, "dlactrlw.exe", SONIC },
81 { HOOKDLLNAME, "wxvault.dll", EMBASSYTS },
82 { HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\vsdatant", ZONEALARM },
83 { FILENAME, "%windir%\\System32\\vsdatant.sys", ZONEALARM },
84 { HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv", LOGITECH },
85 { PROCESSNAME, "LVPrcSrv.exe", LOGITECH },
86 { FILENAME, "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH },
87 { FILENAME, "%windir%\\System32\\bmnet.dll", BYTEMOBILE },
88 };
89
90 static const size_t num_of_detects = sizeof (dodgy_app_detects) / sizeof (dodgy_app_detects[0]);
91
92 static struct bad_app_info big_list_of_dodgy_apps[] =
93 {
94 { SONIC, "Sonic Solutions burning software containing DLA component" },
95 { NORTON, "Norton antivirus or antispyware software" },
96 { MACAFFEE, "Macaffee antivirus or antispyware software" },
97 { SYMANTEC, "Symantec antivirus or antispyware software" },
98 { LOGITECH, "Logitech Process Monitor service" },
99 { KERIO, "Kerio Personal Firewall" },
100 { AGNITUM, "Agnitum Personal Firewall" },
101 { ZONEALARM, "ZoneAlarm Personal Firewall" },
102 { IOLO, "Iolo System Mechanic/AntiVirus/Firewall software" },
103 { LANDESK, "Landesk" },
104 { WINDEFENDER, "Windows Defender" },
105 { EMBASSYTS, "Embassy Trust Suite fingerprint reader software containing wxvault.dll" },
106 { BYTEMOBILE, "ByteMobile laptop optimization client" },
107 };
108
109 static const size_t num_of_dodgy_apps = sizeof (big_list_of_dodgy_apps) / sizeof (big_list_of_dodgy_apps[0]);
110
111 static PSYSTEM_PROCESSES
112 get_process_list (void)
113 {
114 int n_procs = 0x100;
115 PSYSTEM_PROCESSES pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
116
117 while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
118 pslist, n_procs * sizeof *pslist, 0) == STATUS_INFO_LENGTH_MISMATCH)
119 {
120 n_procs *= 2;
121 free (pslist);
122 pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
123 }
124 return pslist;
125 }
126
127 static PSYSTEM_MODULE_INFORMATION
128 get_module_list (void)
129 {
130 int modsize = 0x1000;
131 PSYSTEM_MODULE_INFORMATION modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
132
133 while (NtQuerySystemInformation (SystemModuleInformation,
134 modlist, modsize, NULL) == STATUS_INFO_LENGTH_MISMATCH)
135 {
136 modsize *= 2;
137 free (modlist);
138 modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
139 }
140 return modlist;
141 }
142
143 static bool
144 find_process_in_list (PSYSTEM_PROCESSES pslist, PUNICODE_STRING psname)
145 {
146 while (1)
147 {
148 if (pslist->ProcessName.Length && pslist->ProcessName.Buffer)
149 {
150 dbg_printf (("%S\n", pslist->ProcessName.Buffer));
151 if (!_wcsicmp (pslist->ProcessName.Buffer, psname->Buffer))
152 return true;
153 }
154 if (!pslist->NextEntryDelta)
155 break;
156 pslist = (PSYSTEM_PROCESSES)(pslist->NextEntryDelta + (char *)pslist);
157 };
158 return false;
159 }
160
161 static bool
162 find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist, const char * const modname)
163 {
164 PSYSTEM_MODULE_INFORMATION_ENTRY modptr = &modlist->Module[0];
165 DWORD count = modlist->Count;
166 while (count--)
167 {
168 dbg_printf (("name '%s' offset %d ", &modptr->ImageName[0], modptr->PathLength));
169 dbg_printf (("= '%s'\n", &modptr->ImageName[modptr->PathLength]));
170 if (!_stricmp (&modptr->ImageName[modptr->PathLength], modname))
171 return true;
172 modptr++;
173 }
174 return false;
175 }
176
177 static bool
178 expand_path (const char *path, char *outbuf)
179 {
180 char *dst = outbuf;
181 const char *end, *envval;
182 char envvar[MAX_PATH];
183 size_t len;
184
185 while ((dst - outbuf) < MAX_PATH)
186 {
187 if (*path != '%')
188 {
189 if ((*dst++ = *path++) != 0)
190 continue;
191 break;
192 }
193 /* Expand an environ var. */
194 end = path + 1;
195 while (*end != '%')
196 {
197 /* Watch out for unterminated % */
198 if (*end++ == 0)
199 {
200 end = NULL;
201 break;
202 }
203 }
204 /* If we didn't find the end, can't expand it. */
205 if ((end == NULL) || (end == (path + 1)))
206 {
207 /* Unterminated % so copy verbatim. */
208 *dst++ = *path++;
209 continue;
210 }
211 /* Expand the environment var into the new path. */
212 if ((end - (path + 1)) >= MAX_PATH)
213 return -1;
214 memcpy (envvar, path + 1, end - (path + 1));
215 envvar[end - (path + 1)] = 0;
216 envval = getenv (envvar);
217 /* If not found, copy env var name verbatim. */
218 if (envval == NULL)
219 {
220 *dst++ = *path++;
221 continue;
222 }
223 /* Check enough room before copying. */
224 len = strlen (envval);
225 if ((dst + len - outbuf) >= MAX_PATH)
226 return false;
227 memcpy (dst, envval, len);
228 dst += len;
229 /* And carry on past the end of env var name. */
230 path = end + 1;
231 }
232 return (dst - outbuf) < MAX_PATH;
233 }
234
235 static bool
236 detect_dodgy_app (const struct bad_app_det *det, PSYSTEM_PROCESSES pslist, PSYSTEM_MODULE_INFORMATION modlist)
237 {
238 HANDLE fh;
239 HKEY hk;
240 UNICODE_STRING unicodename;
241 ANSI_STRING ansiname;
242 NTSTATUS rv;
243 bool found;
244 char expandedname[MAX_PATH];
245
246 switch (det->type)
247 {
248 case HKLMKEY:
249 dbg_printf (("Detect reg key hklm '%s'... ", det->param));
250 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
251 {
252 RegCloseKey (hk);
253 dbg_printf (("found!\n"));
254 return true;
255 }
256 break;
257
258 case HKCUKEY:
259 dbg_printf (("Detect reg key hkcu '%s'... ", det->param));
260 if (RegOpenKeyEx (HKEY_CURRENT_USER, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
261 {
262 RegCloseKey (hk);
263 dbg_printf (("found!\n"));
264 return true;
265 }
266 break;
267
268 case FILENAME:
269 dbg_printf (("Detect filename '%s'... ", det->param));
270 if (!expand_path (det->param, expandedname))
271 {
272 printf ("Expansion failure!\n");
273 break;
274 }
275 dbg_printf (("('%s' after expansion)... ", expandedname));
276 fh = CreateFile (expandedname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE
277 | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
278 if (fh != INVALID_HANDLE_VALUE)
279 {
280 CloseHandle (fh);
281 dbg_printf (("found!\n"));
282 return true;
283 }
284 break;
285
286 case PROCESSNAME:
287 dbg_printf (("Detect proc name '%s'... ", det->param));
288 /* Equivalent of RtlInitAnsiString. */
289 ansiname.Length = ansiname.MaximumLength = strlen (det->param);
290 ansiname.Buffer = (CHAR *) det->param;
291 rv = RtlAnsiStringToUnicodeString (&unicodename, &ansiname, TRUE);
292 if (rv != STATUS_SUCCESS)
293 {
294 printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv);
295 break;
296 }
297 found = find_process_in_list (pslist, &unicodename);
298 RtlFreeUnicodeString (&unicodename);
299 if (found)
300 {
301 dbg_printf (("found!\n"));
302 return true;
303 }
304 break;
305
306 case HOOKDLLNAME:
307 dbg_printf (("Detect hookdll '%s'... ", det->param));
308 if (find_module_in_list (modlist, det->param))
309 {
310 dbg_printf (("found!\n"));
311 return true;
312 }
313 break;
314
315 }
316 dbg_printf (("not found.\n"));
317 return false;
318 }
319
320 static struct bad_app_info *
321 find_dodgy_app_info (enum bad_app which_app)
322 {
323 size_t i;
324 for (i = 0; i < num_of_dodgy_apps; i++)
325 {
326 if (big_list_of_dodgy_apps[i].app_id == which_app)
327 return &big_list_of_dodgy_apps[i];
328 }
329 return NULL;
330 }
331
332 /* External entrypoint called from cygcheck.cc/dump_sysinfo. */
333 void
334 dump_dodgy_apps (int verbose)
335 {
336 size_t i, n_det = 0;
337 PSYSTEM_PROCESSES pslist;
338 PSYSTEM_MODULE_INFORMATION modlist;
339
340 /* Read system info for detect testing. */
341 pslist = get_process_list ();
342 modlist = get_module_list ();
343
344 /* Go with builtin list for now; later may enhance to
345 read dodgy apps from a file or download from an URL. */
346 for (i = 0; i < num_of_dodgy_apps; i++)
347 {
348 big_list_of_dodgy_apps[i].found_it = false;
349 }
350
351 for (i = 0; i < num_of_detects; i++)
352 {
353 const struct bad_app_det *det = &dodgy_app_detects[i];
354 struct bad_app_info *found = find_dodgy_app_info (det->app);
355 bool detected = detect_dodgy_app (det, pslist, modlist);
356
357 /* Not found would mean we coded the lists bad. */
358 assert (found);
359 if (detected)
360 {
361 ++n_det;
362 found->found_it |= (1 << det->type);
363 }
364 }
365 if (n_det)
366 {
367 printf ("\nPotential app conflicts:\n\n");
368 for (i = 0; i < num_of_dodgy_apps; i++)
369 {
370 if (big_list_of_dodgy_apps[i].found_it)
371 {
372 printf ("%s%s", big_list_of_dodgy_apps[i].details,
373 verbose ? "\nDetected: " : ".\n");
374 if (!verbose)
375 continue;
376 const char *sep = "";
377 if (big_list_of_dodgy_apps[i].found_it & (1 << HKLMKEY))
378 {
379 printf ("HKLM Registry Key");
380 sep = ", ";
381 }
382 if (big_list_of_dodgy_apps[i].found_it & (1 << HKCUKEY))
383 {
384 printf ("%sHKCU Registry Key", sep);
385 sep = ", ";
386 }
387 if (big_list_of_dodgy_apps[i].found_it & (1 << FILENAME))
388 {
389 printf ("%sNamed file", sep);
390 sep = ", ";
391 }
392 if (big_list_of_dodgy_apps[i].found_it & (1 << PROCESSNAME))
393 {
394 printf ("%sNamed process", sep);
395 sep = ", ";
396 }
397 if (big_list_of_dodgy_apps[i].found_it & (1 << HOOKDLLNAME))
398 {
399 printf ("%sLoaded hook DLL", sep);
400 }
401 printf (".\n\n");
402 }
403 }
404 }
405 /* Tidy up allocations. */
406 free (pslist);
407 free (modlist);
408 }
409
This page took 0.056097 seconds and 6 git commands to generate.