* Makefile.in (cygcheck.exe): Add bloda.o as prerequisite, adjusting
dependency-filtering $(wordlist ...) call appropriately. Link ntdll. (bloda.o): New rule to build bloda.o * cygcheck.cc (dump_sysinfo): Call bloda function dump_dodgy_apps(). * bloda.cc: New file implements detection of applications from the Big List Of Dodgy Apps.
This commit is contained in:
parent
6ddcdb9da5
commit
64b94981dc
@ -1,3 +1,12 @@
|
||||
2007-08-03 Dave Korn <dave.korn@artimi.com>
|
||||
|
||||
* Makefile.in (cygcheck.exe): Add bloda.o as prerequisite, adjusting
|
||||
dependency-filtering $(wordlist ...) call appropriately. Link ntdll.
|
||||
(bloda.o): New rule to build bloda.o
|
||||
* cygcheck.cc (dump_sysinfo): Call bloda function dump_dodgy_apps().
|
||||
* bloda.cc: New file implements detection of applications from the
|
||||
Big List Of Dodgy Apps.
|
||||
|
||||
2007-07-24 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* COPYING.dumper: New file.
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Makefile for Cygwin utilities
|
||||
# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006 Red Hat, Inc.
|
||||
# 2005, 2006, 2007 Red Hat, Inc.
|
||||
|
||||
# This file is part of Cygwin.
|
||||
|
||||
@ -99,15 +99,15 @@ else
|
||||
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
|
||||
endif
|
||||
|
||||
cygcheck.exe: cygcheck.o path.o dump_setup.o $(MINGW_DEP_LDLIBS)
|
||||
cygcheck.exe: cygcheck.o bloda.o path.o dump_setup.o $(MINGW_DEP_LDLIBS)
|
||||
ifeq "$(libz)" ""
|
||||
@echo '*** Building cygcheck without package content checking due to missing mingw libz.a.'
|
||||
endif
|
||||
ifdef VERBOSE
|
||||
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
|
||||
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll
|
||||
else
|
||||
@echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz);\
|
||||
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
|
||||
@echo $(CXX) -o $@ ${wordlist 1,4,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz) -lntdll;\
|
||||
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll
|
||||
endif
|
||||
|
||||
dumper.o: dumper.cc dumper.h
|
||||
@ -150,6 +150,14 @@ else
|
||||
$(MINGW_CXX) $(zconf_h) $(zlib_h) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) $<
|
||||
endif
|
||||
|
||||
bloda.o: bloda.cc
|
||||
ifdef VERBOSE
|
||||
${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
|
||||
else
|
||||
@echo $(MINGW_CXX) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) ... $^;\
|
||||
${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
|
||||
endif
|
||||
|
||||
cygcheck.o: cygcheck.cc
|
||||
ifdef VERBOSE
|
||||
${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
|
||||
|
410
winsup/utils/bloda.cc
Normal file
410
winsup/utils/bloda.cc
Normal file
@ -0,0 +1,410 @@
|
||||
/* bloda.cc
|
||||
|
||||
Copyright 2007 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#define cygwin_internal cygwin_internal_dontuse
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <ntdef.h>
|
||||
#include <ddk/ntstatus.h>
|
||||
#include <ddk/ntapi.h>
|
||||
#undef cygwin_internal
|
||||
|
||||
#undef DEBUGGING
|
||||
#ifdef DEBUGGING
|
||||
#define dbg_printf(ARGS) printf ARGS ; fflush (NULL)
|
||||
#else /* !DEBUGGING */
|
||||
#define dbg_printf(ARGS) do { } while (0)
|
||||
#endif /* ?DEBUGGING */
|
||||
|
||||
/* This module detects applications from the Big List of Dodgy Apps,
|
||||
a list of applications that have at some given time been shown to
|
||||
interfere with the operation of cygwin. It detects the presence of
|
||||
applications on the system by looking for any of four traces an
|
||||
installation might leave: 1) registry keys, 2) files on disk
|
||||
3) running executables 4) loaded dlls or drivers.
|
||||
|
||||
At the time of writing, the BLODA amounts to:-
|
||||
|
||||
Sonic Solutions burning software containing DLA component
|
||||
Norton/MacAffee/Symantec antivirus or antispyware
|
||||
Logitech webcam software with "Logitech process monitor" service
|
||||
Kerio, Agnitum or ZoneAlarm Personal Firewall
|
||||
Iolo System Mechanic/AntiVirus/Firewall
|
||||
LanDesk
|
||||
Windows Defender
|
||||
Embassy Trust Suite fingerprint reader software containing wxvault.dll
|
||||
*/
|
||||
|
||||
enum bad_app
|
||||
{
|
||||
SONIC, NORTON, MACAFFEE, SYMANTEC,
|
||||
LOGITECH, KERIO, AGNITUM, ZONEALARM,
|
||||
IOLO, LANDESK, WINDEFENDER, EMBASSYTS
|
||||
};
|
||||
|
||||
struct bad_app_info
|
||||
{
|
||||
enum bad_app app_id;
|
||||
const char *details;
|
||||
char found_it;
|
||||
};
|
||||
|
||||
enum bad_app_det_method
|
||||
{
|
||||
HKLMKEY, HKCUKEY, FILENAME, PROCESSNAME, HOOKDLLNAME
|
||||
};
|
||||
|
||||
struct bad_app_det
|
||||
{
|
||||
enum bad_app_det_method type;
|
||||
const char *param;
|
||||
enum bad_app app;
|
||||
};
|
||||
|
||||
static const struct bad_app_det dodgy_app_detects[] =
|
||||
{
|
||||
{ PROCESSNAME, "dlactrlw.exe", SONIC },
|
||||
{ HOOKDLLNAME, "wxvault.dll", EMBASSYTS },
|
||||
{ HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\vsdatant", ZONEALARM },
|
||||
{ FILENAME, "%windir%\\System32\\vsdatant.sys", ZONEALARM },
|
||||
{ HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv", LOGITECH },
|
||||
{ PROCESSNAME, "LVPrcSrv.exe", LOGITECH },
|
||||
{ FILENAME, "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH },
|
||||
};
|
||||
|
||||
static const size_t num_of_detects = sizeof (dodgy_app_detects) / sizeof (dodgy_app_detects[0]);
|
||||
|
||||
static struct bad_app_info big_list_of_dodgy_apps[] =
|
||||
{
|
||||
{ SONIC, "Sonic Solutions burning software containing DLA component" },
|
||||
{ NORTON, "Norton antivirus or antispyware software" },
|
||||
{ MACAFFEE, "Macaffee antivirus or antispyware software" },
|
||||
{ SYMANTEC, "Symantec antivirus or antispyware software" },
|
||||
{ LOGITECH, "Logitech Process Monitor service" },
|
||||
{ KERIO, "Kerio Personal Firewall" },
|
||||
{ AGNITUM, "Agnitum Personal Firewall" },
|
||||
{ ZONEALARM, "ZoneAlarm Personal Firewall" },
|
||||
{ IOLO, "Iolo System Mechanic/AntiVirus/Firewall software" },
|
||||
{ LANDESK, "Landesk" },
|
||||
{ WINDEFENDER, "Windows Defender" },
|
||||
{ EMBASSYTS, "Embassy Trust Suite fingerprint reader software containing wxvault.dll" },
|
||||
};
|
||||
|
||||
static const size_t num_of_dodgy_apps = sizeof (big_list_of_dodgy_apps) / sizeof (big_list_of_dodgy_apps[0]);
|
||||
|
||||
/* This function is not in the ntdll export lib, so it has
|
||||
to be looked up at runtime and called through a pointer. */
|
||||
VOID NTAPI (*pRtlFreeUnicodeString)(PUNICODE_STRING) = NULL;
|
||||
|
||||
static PSYSTEM_PROCESSES
|
||||
get_process_list (void)
|
||||
{
|
||||
int n_procs = 0x100;
|
||||
PSYSTEM_PROCESSES pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
|
||||
|
||||
while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
|
||||
pslist, n_procs * sizeof *pslist, 0) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
n_procs *= 2;
|
||||
free (pslist);
|
||||
pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
|
||||
}
|
||||
return pslist;
|
||||
}
|
||||
|
||||
static PSYSTEM_MODULE_INFORMATION
|
||||
get_module_list (void)
|
||||
{
|
||||
int modsize = 0x1000;
|
||||
PSYSTEM_MODULE_INFORMATION modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
|
||||
|
||||
while (NtQuerySystemInformation (SystemModuleInformation,
|
||||
modlist, modsize, NULL) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
modsize *= 2;
|
||||
free (modlist);
|
||||
modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
|
||||
}
|
||||
return modlist;
|
||||
}
|
||||
|
||||
static bool
|
||||
find_process_in_list (PSYSTEM_PROCESSES pslist, PUNICODE_STRING psname)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (pslist->ProcessName.Length && pslist->ProcessName.Buffer)
|
||||
{
|
||||
dbg_printf (("%S\n", pslist->ProcessName.Buffer));
|
||||
if (!_wcsicmp (pslist->ProcessName.Buffer, psname->Buffer))
|
||||
return true;
|
||||
}
|
||||
if (!pslist->NextEntryDelta)
|
||||
break;
|
||||
pslist = (PSYSTEM_PROCESSES)(pslist->NextEntryDelta + (char *)pslist);
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist, const char * const modname)
|
||||
{
|
||||
PSYSTEM_MODULE_INFORMATION_ENTRY modptr = &modlist->Module[0];
|
||||
DWORD count = modlist->Count;
|
||||
while (count--)
|
||||
{
|
||||
dbg_printf (("name '%s' offset %d ", &modptr->ImageName[0], modptr->PathLength));
|
||||
dbg_printf (("= '%s'\n", &modptr->ImageName[modptr->PathLength]));
|
||||
if (!_stricmp (&modptr->ImageName[modptr->PathLength], modname))
|
||||
return true;
|
||||
modptr++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
expand_path (const char *path, char *outbuf)
|
||||
{
|
||||
char *dst = outbuf;
|
||||
const char *end, *envval;
|
||||
char envvar[MAX_PATH];
|
||||
size_t len;
|
||||
|
||||
while ((dst - outbuf) < MAX_PATH)
|
||||
{
|
||||
if (*path != '%')
|
||||
{
|
||||
if ((*dst++ = *path++) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/* Expand an environ var. */
|
||||
end = path + 1;
|
||||
while (*end != '%')
|
||||
{
|
||||
/* Watch out for unterminated % */
|
||||
if (*end++ == 0)
|
||||
{
|
||||
end = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If we didn't find the end, can't expand it. */
|
||||
if ((end == NULL) || (end == (path + 1)))
|
||||
{
|
||||
/* Unterminated % so copy verbatim. */
|
||||
*dst++ = *path++;
|
||||
continue;
|
||||
}
|
||||
/* Expand the environment var into the new path. */
|
||||
if ((end - (path + 1)) >= MAX_PATH)
|
||||
return -1;
|
||||
memcpy (envvar, path + 1, end - (path + 1));
|
||||
envvar[end - (path + 1)] = 0;
|
||||
envval = getenv (envvar);
|
||||
/* If not found, copy env var name verbatim. */
|
||||
if (envval == NULL)
|
||||
{
|
||||
*dst++ = *path++;
|
||||
continue;
|
||||
}
|
||||
/* Check enough room before copying. */
|
||||
len = strlen (envval);
|
||||
if ((dst + len - outbuf) >= MAX_PATH)
|
||||
return false;
|
||||
memcpy (dst, envval, len);
|
||||
dst += len;
|
||||
/* And carry on past the end of env var name. */
|
||||
path = end + 1;
|
||||
}
|
||||
return (dst - outbuf) < MAX_PATH;
|
||||
}
|
||||
|
||||
static bool
|
||||
detect_dodgy_app (const struct bad_app_det *det, PSYSTEM_PROCESSES pslist, PSYSTEM_MODULE_INFORMATION modlist)
|
||||
{
|
||||
HANDLE fh;
|
||||
HKEY hk;
|
||||
UNICODE_STRING unicodename;
|
||||
ANSI_STRING ansiname;
|
||||
NTSTATUS rv;
|
||||
bool found;
|
||||
char expandedname[MAX_PATH];
|
||||
|
||||
switch (det->type)
|
||||
{
|
||||
case HKLMKEY:
|
||||
dbg_printf (("Detect reg key hklm '%s'... ", det->param));
|
||||
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey (hk);
|
||||
dbg_printf (("found!\n"));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case HKCUKEY:
|
||||
dbg_printf (("Detect reg key hkcu '%s'... ", det->param));
|
||||
if (RegOpenKeyEx (HKEY_CURRENT_USER, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey (hk);
|
||||
dbg_printf (("found!\n"));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case FILENAME:
|
||||
dbg_printf (("Detect filename '%s'... ", det->param));
|
||||
if (!expand_path (det->param, expandedname))
|
||||
{
|
||||
printf ("Expansion failure!\n");
|
||||
break;
|
||||
}
|
||||
dbg_printf (("('%s' after expansion)... ", expandedname));
|
||||
fh = CreateFile (expandedname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE
|
||||
| FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (fh != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle (fh);
|
||||
dbg_printf (("found!\n"));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROCESSNAME:
|
||||
dbg_printf (("Detect proc name '%s'... ", det->param));
|
||||
/* Equivalent of RtlInitAnsiString. */
|
||||
ansiname.Length = ansiname.MaximumLength = strlen (det->param);
|
||||
ansiname.Buffer = (CHAR *) det->param;
|
||||
rv = RtlAnsiStringToUnicodeString (&unicodename, &ansiname, TRUE);
|
||||
if (rv != STATUS_SUCCESS)
|
||||
{
|
||||
printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv);
|
||||
break;
|
||||
}
|
||||
found = find_process_in_list (pslist, &unicodename);
|
||||
if (!pRtlFreeUnicodeString)
|
||||
pRtlFreeUnicodeString = (VOID NTAPI (*)(PUNICODE_STRING)) GetProcAddress (LoadLibrary ("ntdll.dll"), "RtlFreeUnicodeString");
|
||||
if (pRtlFreeUnicodeString)
|
||||
pRtlFreeUnicodeString (&unicodename);
|
||||
else
|
||||
printf ("leaking mem...oops\n");
|
||||
if (found)
|
||||
{
|
||||
dbg_printf (("found!\n"));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case HOOKDLLNAME:
|
||||
dbg_printf (("Detect hookdll '%s'... ", det->param));
|
||||
if (find_module_in_list (modlist, det->param))
|
||||
{
|
||||
dbg_printf (("found!\n"));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
dbg_printf (("not found.\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct bad_app_info *
|
||||
find_dodgy_app_info (enum bad_app which_app)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < num_of_dodgy_apps; i++)
|
||||
{
|
||||
if (big_list_of_dodgy_apps[i].app_id == which_app)
|
||||
return &big_list_of_dodgy_apps[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* External entrypoint called from cygcheck.cc/dump_sysinfo. */
|
||||
void
|
||||
dump_dodgy_apps (int verbose)
|
||||
{
|
||||
size_t i, n_det = 0;
|
||||
PSYSTEM_PROCESSES pslist;
|
||||
PSYSTEM_MODULE_INFORMATION modlist;
|
||||
|
||||
/* Read system info for detect testing. */
|
||||
pslist = get_process_list ();
|
||||
modlist = get_module_list ();
|
||||
|
||||
/* Go with builtin list for now; later may enhance to
|
||||
read dodgy apps from a file or download from an URL. */
|
||||
for (i = 0; i < num_of_dodgy_apps; i++)
|
||||
{
|
||||
big_list_of_dodgy_apps[i].found_it = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_detects; i++)
|
||||
{
|
||||
const struct bad_app_det *det = &dodgy_app_detects[i];
|
||||
struct bad_app_info *found = find_dodgy_app_info (det->app);
|
||||
bool detected = detect_dodgy_app (det, pslist, modlist);
|
||||
|
||||
/* Not found would mean we coded the lists bad. */
|
||||
assert (found);
|
||||
if (detected)
|
||||
{
|
||||
++n_det;
|
||||
found->found_it |= (1 << det->type);
|
||||
}
|
||||
}
|
||||
if (n_det)
|
||||
{
|
||||
printf ("\nPotential app conflicts:\n\n");
|
||||
for (i = 0; i < num_of_dodgy_apps; i++)
|
||||
{
|
||||
if (big_list_of_dodgy_apps[i].found_it)
|
||||
{
|
||||
printf ("%s%s", big_list_of_dodgy_apps[i].details,
|
||||
verbose ? "\nDetected: " : ".\n");
|
||||
if (!verbose)
|
||||
continue;
|
||||
const char *sep = "";
|
||||
if (big_list_of_dodgy_apps[i].found_it & (1 << HKLMKEY))
|
||||
{
|
||||
printf ("HKLM Registry Key");
|
||||
sep = ", ";
|
||||
}
|
||||
if (big_list_of_dodgy_apps[i].found_it & (1 << HKCUKEY))
|
||||
{
|
||||
printf ("%sHKCU Registry Key", sep);
|
||||
sep = ", ";
|
||||
}
|
||||
if (big_list_of_dodgy_apps[i].found_it & (1 << FILENAME))
|
||||
{
|
||||
printf ("%sNamed file", sep);
|
||||
sep = ", ";
|
||||
}
|
||||
if (big_list_of_dodgy_apps[i].found_it & (1 << PROCESSNAME))
|
||||
{
|
||||
printf ("%sNamed process", sep);
|
||||
sep = ", ";
|
||||
}
|
||||
if (big_list_of_dodgy_apps[i].found_it & (1 << HOOKDLLNAME))
|
||||
{
|
||||
printf ("%sLoaded hook DLL", sep);
|
||||
}
|
||||
printf (".\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Tidy up allocations. */
|
||||
free (pslist);
|
||||
free (modlist);
|
||||
}
|
||||
|
@ -50,9 +50,13 @@ typedef long long longlong;
|
||||
typedef __int64 longlong;
|
||||
#endif
|
||||
|
||||
/* In dump_setup.cc */
|
||||
void dump_setup (int, char **, bool);
|
||||
void package_find (int, char **);
|
||||
void package_list (int, char **);
|
||||
/* In bloda.cc */
|
||||
void dump_dodgy_apps (int verbose);
|
||||
|
||||
|
||||
static const char version[] = "$Revision$";
|
||||
|
||||
@ -1623,6 +1627,8 @@ dump_sysinfo ()
|
||||
if (!cygwin_dll_count)
|
||||
puts ("Warning: cygwin1.dll not found on your path");
|
||||
|
||||
dump_dodgy_apps (verbose);
|
||||
|
||||
if (is_nt)
|
||||
dump_sysinfo_services ();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user