📄 spyserver.c
字号:
/******************************************************************/
/* */
/* Winpooch : Windows Watchdog */
/* Copyright (C) 2004-2006 Benoit Blanchon */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General Public */
/* License as published by the Free Software Foundation; either */
/* version 2 of the License, or (at your option) any later */
/* version. */
/* */
/* This program is distributed in the hope that it will be */
/* useful, but WITHOUT ANY WARRANTY; without even the implied */
/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
/* PURPOSE. See the GNU General Public License for more */
/* details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with this program; if not, write to the Free */
/* Software Foundation, Inc., */
/* 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/******************************************************************/
/******************************************************************/
/* Build configuration */
/******************************************************************/
#define TRACE_LEVEL 2 // warning level
/******************************************************************/
/* Includes */
/******************************************************************/
// module's interface
#include "SpyServer.h"
// Windows headers
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <winioctl.h>
// project's headers
#include "AskDlg.h"
#include "Assert.h"
#include "Config.h"
#include "DrvInterface.h"
#include "EventLog.h"
#include "Filter.h"
#include "FilterDefault.h"
#include "FilterFile.h"
#include "FilterSet.h"
#include "Language.h"
#include "Link.h"
#include "Malloc.h"
#include "ProcList.h"
#include "ProcListWnd.h"
#include "ProjectInfo.h"
#include "Reason.h"
#include "Resources.h"
#include "FiltRule.h"
#include "RuleDlg.h"
#include "Scanner.h"
#include "Sounds.h"
#include "Strlcpy.h"
#include "TrayIcon.h"
#include "Trace.h"
#include "VirusDlg.h"
/******************************************************************/
/* Internal macros */
/******************************************************************/
#define arraysize(A) (sizeof(A)/sizeof((A)[0]))
/******************************************************************/
/* Internal constants */
/******************************************************************/
TCHAR szFilterFilename[] = TEXT("Current.wpf") ;
TCHAR g_szServiceName[] = TEXT("Winpooch") ;
TCHAR g_szDriverFileName[] = TEXT("Winpooch.sys") ;
TCHAR szNoFiltersAlert[] =
TEXT("No filter file has been found, default filters will be used.\n"
"You can ignore this alert if you are running Winpooch for the first time.") ;
TCHAR szFiltersErrorAlert[] =
TEXT("Error reading file %s :\n%s\nDefault filters will be used.") ;
TCHAR szOldFiltersCleared[] =
TEXT("Filters from a previous version have been found but can't be used.\n"
"The file has been backed up but filters have been cleared.") ;
/******************************************************************/
/* Internal data types */
/******************************************************************/
typedef LPTHREAD_START_ROUTINE THREADPROC ;
/******************************************************************/
/* Internal data */
/******************************************************************/
static HINSTANCE g_hInstance = NULL ;
static HWND g_hwndMain = NULL ;
static HFILTERSET g_hFilterSet = NULL ;
static HANDLE g_hFilterMutex = NULL ;
static HANDLE g_hDriver = NULL ;
/******************************************************************/
/* Internal functions */
/******************************************************************/
// Notification function called by spy DLL
DWORD _SpySrv_RequestFromDriver (LPVOID, DWORD) ;
// initialize spy dll
BOOL _SpySrv_InitDriver () ;
// destroy filters
BOOL _SpySrv_UninitFilters () ;
// uninitialize spy dll
VOID _SpySrv_UninitDriver () ;
BOOL _SpySrv_RefreshProcList () ;
/******************************************************************/
/* Internal function */
/******************************************************************/
BOOL _SpySrv_Log (PROCADDR nProcessAddr, PCFILTCOND pCond,
DWORD nReaction, BOOL bAlert)
{
UINT nProcessId ;
DWORD dwEventId ;
TCHAR szProcess[MAX_PATH] = TEXT("???") ;
TRACE ;
// get process name
{
PROCSTRUCT * pProc ;
ProcList_Lock () ;
pProc = ProcList_Get (nProcessAddr) ;
nProcessId = pProc->nProcessId ;
if( pProc ) {
wcslcpy (szProcess, pProc->szPath, MAX_PATH) ;
} else {
wsprintf (szProcess, TEXT("Process %d"), nProcessId) ;
TRACE_WARNING (TEXT("Process %d not in list (addr=0x08X)\n"),
nProcessId, nProcessAddr) ;
}
ProcList_Unlock () ;
}
dwEventId = EventLog_Add (nProcessId, szProcess, nReaction,
bAlert ? RULE_ALERT : RULE_LOG,
pCond) ;
if( bAlert )
{
Sounds_Play (SOUND_ALERT) ;
PostMessage (g_hwndMain, WM_SPYNOTIFY, SN_ALERT, dwEventId) ;
}
PostMessage (g_hwndMain, WM_SPYNOTIFY, SN_EVENTLOGGED, dwEventId) ;
return TRUE ;
}
/******************************************************************/
/* Internal function */
/******************************************************************/
DWORD _SpySrv_Ask (PROCADDR nProcessAddress, UINT nDefReaction, PFILTCOND pCond)
{
TCHAR szProcess[MAX_PATH] = TEXT("???") ;
UINT nProcessId ;
int nResult ;
TRACE ;
// get process name
{
PROCSTRUCT * pProc ;
ProcList_Lock () ;
pProc = ProcList_Get (nProcessAddress) ;
nProcessId = pProc->nProcessId ;
if( pProc ) {
wcslcpy (szProcess, pProc->szPath, MAX_PATH) ;
} else {
wsprintf (szProcess, TEXT("Process %d"), nProcessId) ;
TRACE_WARNING (TEXT("Process %d not in list (addr=0x%08X\n"),
nProcessId, nProcessAddress) ;
}
ProcList_Unlock () ;
}
Sounds_Play (SOUND_ASK) ;
TRACE_INFO (TEXT(" /----ASK----\\\n")) ;
askdlg:
nResult = AskDlg_DialogBox (g_hInstance, g_hwndMain, szProcess, nProcessId, nDefReaction, pCond) ;
if( nResult==ASKDLG_CREATEFILTER )
{
FILTRULE * pRule ;
// alloc new rule
pRule = (FILTRULE*) calloc (1, sizeof(FILTRULE)) ;
// fill params as they appear in the ask dialog
pRule->nReaction = nDefReaction ;
pRule->nVerbosity = RULE_LOG ;
pRule->nOptions = 0 ;
FiltCond_Dup (&pRule->condition, pCond) ;
// show rule dialog
if( IDOK!=RuleDlg_DialogBox (g_hInstance, g_hwndMain, szProcess, pRule, FALSE) )
{
free (pRule) ;
goto askdlg ;
}
// verify that this rule matches the current event
if( ! FiltCond_Check(&pRule->condition,pCond) )
{
MessageBox (g_hwndMain,
STR_DEF(_RULE_DOESNT_MATCH,
TEXT("The rule you defined doesn't match current event")),
TEXT(APPLICATION_NAME), MB_ICONERROR) ;
free (pRule) ;
goto askdlg ;
}
SpySrv_AddRuleForProgram (pRule, szProcess) ;
nResult = pRule->nReaction ;
}
if( nResult==ASKDLG_UNHOOK )
{
SpySrv_IgnoreProcess (nProcessAddress, TRUE) ;
nResult = RULE_ACCEPT ;
}
TRACE_INFO (TEXT(" \\----ASK-%d--/\n"), nResult) ;
return nResult ;
}
/******************************************************************/
/* */
/* Return true if file open is allowed */
/******************************************************************/
SCANRESULT SpySrv_ScanFile (LPCTSTR szFilePath, BOOL bBackground)
{
TCHAR szOutput[1024] ;
UINT nResult ;
VIRUSDLGPARAMS dlgparams = {
szFilePath,
szOutput
} ;
TRACE_INFO (TEXT("Will scan file %ls\n"), szFilePath) ;
if( ! Scanner_IsConfigured() )
return SCAN_NOT_SCANNED ;
nResult = Scanner_ScanFile (szFilePath,szOutput,1024,bBackground) ;
TRACE_INFO (TEXT("Scan result = %d\n"), nResult) ;
if( nResult != SCAN_NO_VIRUS )
{
UINT nReaction ;
Sounds_Play (SOUND_VIRUS) ;
nReaction = DialogBoxParam (g_hInstance, MAKEINTRESOURCE(DLG_VIRUS), g_hwndMain,
VirusDlg_DlgProc, (LPARAM)&dlgparams) ;
if( nReaction == RULE_ACCEPT )
nResult++ ;
}
return nResult ;
}
/******************************************************************/
/* Internal function : SpyDllNotify */
/******************************************************************/
DWORD _SpySrv_RequestFromDriver (LPVOID pBuffer, DWORD nSize)
{
SDNMHDR *p = pBuffer ;
VOID *pSerial ;
UINT nSerialSize ;
DWORD nResponseSize = 0 ;
TRACE ;
ASSERT (pBuffer) ;
ASSERT (nSize>0) ;
ASSERT (nSize>=sizeof(SDNMHDR)) ;
TRACE_INFO (TEXT(" /----REQ-%d----\\ (size=%d\n"), p->dwCode, nSize) ;
switch( p->dwCode )
{
case SDN_ASK:
{
DWORD nReaction ;
FILTCOND cond ;
pSerial = ((SDNASK*)p)->data ;
nSerialSize = nSize - sizeof(SDNASK) ;
ASSERT (nSerialSize>0) ;
if( ! FiltCond_Unserialize (&cond, pSerial, nSerialSize) )
{
TRACE_ERROR (TEXT("FiltCond_Unserialize failed\n")) ;
nReaction = RULE_ACCEPT ;
}
else
{
nReaction = _SpySrv_Ask (((SDNASK*)p)->nProcessAddress,
((SDNASK*)p)->nDefReaction,
&cond) ;
}
*((DWORD*)pBuffer) = nReaction ;
nResponseSize = sizeof(DWORD) ;
}
break ;
case SDN_LOG:
case SDN_ALERT:
{
DWORD nReaction ;
FILTCOND cond ;
nReaction = ((SDNLOG*)p)->dwReaction ;
pSerial = ((SDNLOG*)p)->data ;
nSerialSize = nSize - sizeof(SDNLOG) ;
if( ! FiltCond_Unserialize (&cond, pSerial, nSerialSize) )
{
TRACE_ERROR (TEXT("FiltCond_Unserialize failed\n")) ;
nReaction = RULE_ACCEPT ;
}
else
{
_SpySrv_Log (((SDNLOG*)p)->nProcessAddress, &cond, nReaction, p->dwCode==SDN_ALERT) ;
}
}
break ;
case SDN_SCANFILE:
{
DWORD nScanResult ;
nScanResult = SpySrv_ScanFile (((SDNSCANFILE*)pBuffer)->wszFilePath, FALSE) ;
*((DWORD*)pBuffer) = nScanResult ;
nResponseSize = sizeof(DWORD) ;
}
break ;
case SDN_PROCESSCREATED:
{
SDNPROCESSCREATED * pSdnpc = pBuffer ;
PROCSTRUCT proc ;
proc.nProcessAddress = pSdnpc->nProcessAddress ;
proc.nProcessId = pSdnpc->nProcessId ;
proc.nState = PS_HOOKED_SINCE_BIRTH ;
wcslcpy (proc.szName, PathFindFileName(pSdnpc->wszFilePath), 32) ;
wcslcpy (proc.szPath, pSdnpc->wszFilePath, MAX_PATH) ;
ProcList_Lock () ;
ProcList_Add (&proc) ;
ProcList_Unlock () ;
PostMessage (g_hwndMain, WM_SPYNOTIFY, SN_PROCESSCREATED, pSdnpc->nProcessAddress) ;
}
break ;
case SDN_PIDCHANGED:
{
SDNPIDCHANGED *pSdnpc = pBuffer ;
PROCSTRUCT *pProc ;
ProcList_Lock () ;
pProc = ProcList_Get (pSdnpc->nProcessAddress) ;
if( pProc )
{
TRACE_ALWAYS (TEXT("PID changed %d -> %d\n"), pProc->nProcessId, pSdnpc->nNewProcessId) ;
pProc->nProcessId = pSdnpc->nNewProcessId ;
}
ProcList_Unlock () ;
// This notification has been disabled because it caused a dead-lock.
// PostMessage (g_hwndMain, WM_SPYNOTIFY, SN_PIDCHANGED, pSdnpc->nProcessAddress) ;
}
break ;
case SDN_PROCESSTERMINATED:
{
SDNPROCESSTERMINATED * pSdnpt = pBuffer ;
TRACE_INFO (TEXT("Process terminated 0x%08X\n"),pSdnpt->nProcessAddress) ;
ProcList_Lock () ;
ProcList_Remove (pSdnpt->nProcessAddress) ;
ProcList_Unlock () ;
PostMessage (g_hwndMain, WM_SPYNOTIFY, SN_PROCESSTERMINATED, pSdnpt->nProcessAddress) ;
}
break ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -