diff --git a/CHANGELOG b/CHANGELOG index fdb22dc..bab7d43 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -310,3 +310,5 @@ WinDivert 2.1.0 - Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows. WinDivert 2.2.0 - Implement new packet parser that correctly handles IP fragments. + - Add a new "fragment" filter field that matches IP fragments. + - (Un)Loading the WinDivert driver will cause a system event to be logged. diff --git a/dll/windivert.c b/dll/windivert.c index be4ea70..f0ec577 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -263,6 +263,33 @@ static BOOLEAN WinDivertGetDriverFileName(LPWSTR sys_str) return TRUE; } +/* + * Register event log. It is not an error if this function fails. + */ +static void WinDivertRegisterEventSource(const wchar_t *windivert_sys) +{ + HKEY key; + size_t len; + DWORD types = 7; + + if (!WinDivertStrLen(windivert_sys, MAX_PATH, &len)) + { + return; + } + if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\EventLog\\System\\WinDivert", + 0, NULL, REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &key, NULL) + != ERROR_SUCCESS) + { + return; + } + RegSetValueExW(key, L"EventMessageFile", 0, REG_SZ, (LPBYTE)windivert_sys, + (len + 1) * sizeof(wchar_t)); + RegSetValueExA(key, "TypesSupported", 0, REG_DWORD, (LPBYTE)&types, + sizeof(types)); + RegCloseKey(key); +} + /* * Install the WinDivert driver. */ @@ -324,6 +351,9 @@ static BOOLEAN WinDivertDriverInstall(VOID) goto WinDivertDriverInstallExit; } + // Register event logging: + WinDivertRegisterEventSource(windivert_sys); + WinDivertDriverInstallExit: success = (service != NULL); @@ -356,7 +386,7 @@ WinDivertDriverInstallExit: ReleaseMutex(mutex); CloseHandle(mutex); SetLastError(err); - + return success; } diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 869c7d5..076f961 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -32,11 +32,6 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include -#include - - - /****************************************************************************/ /* WINDIVERT HELPER IMPLEMENTATION */ /****************************************************************************/ @@ -2149,8 +2144,8 @@ static BOOL WinDivertCondExecFilter(PWINDIVERT_FILTER filter, UINT length, { INT16 ip; UINT16 succ, fail; - BOOL result[WINDIVERT_FILTER_MAXLEN]; - BOOL result_succ, result_fail, result_test; + BOOLEAN result[WINDIVERT_FILTER_MAXLEN]; + BOOLEAN result_succ, result_fail, result_test; if (length == 0) { diff --git a/include/windivert_device.h b/include/windivert_device.h index 325944e..25d4d05 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -38,7 +38,7 @@ /* * NOTE: This is the low-level interface to the WinDivert device driver. * This interface should not be used directly, instead use the high-level - * interface provided by the divert API. + * interface provided by the WinDivert API. */ #define WINDIVERT_KERNEL diff --git a/mingw-build.sh b/mingw-build.sh index 98c69fa..c231bbd 100644 --- a/mingw-build.sh +++ b/mingw-build.sh @@ -41,7 +41,7 @@ ENVS="i686-w64-mingw32 x86_64-w64-mingw32" if [ "$1" = "debug" ] then - MSVCRT=-lmsvcrt + EXTRA_OPTS="-lmsvcrt -include stdio.h" fi for ENV in $ENVS @@ -66,7 +66,7 @@ do CC="$ENV-gcc" COPTS="-fno-ident -shared -Wall -Wno-pointer-to-int-cast -Os -Iinclude/ -Wl,--enable-stdcall-fixup -Wl,--entry=${MANGLE}WinDivertDllEntry" - CLIBS="-lkernel32 -ladvapi32 $MSVCRT" + CLIBS="-lkernel32 -ladvapi32 $EXTRA_OPTS" STRIP="$ENV-strip" DLLTOOL="$ENV-dlltool" if [ -x "`which $CC`" ] diff --git a/sys/windivert.c b/sys/windivert.c index 8ba004b..5852978 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -32,7 +32,6 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #include #include #include @@ -44,6 +43,7 @@ #include #include "windivert_device.h" +#include "windivert_log.h" /* * WDK function declaration cruft. @@ -304,6 +304,7 @@ static LONGLONG counts_per_ms = 0; static POOL_TYPE non_paged_pool = NonPagedPool; static MM_PAGE_PRIORITY no_write_flag = 0; static MM_PAGE_PRIORITY no_exec_flag = 0; +static LONG64 num_opens = 0; /* * Priorities. @@ -491,6 +492,8 @@ static void windivert_reflect_event_notify(context_t context, static void windivert_reflect_established_notify(context_t context, LONGLONG timestamp); extern void windivert_reflect_worker(IN WDFWORKITEM item); +static void windivert_log_event(PEPROCESS process, PDRIVER_OBJECT driver, + const wchar_t *msg_str); /* * WinDivert sublayer GUIDs @@ -1245,11 +1248,11 @@ driver_entry_exit: /* * WinDivert driver unload routine. */ -extern VOID windivert_unload(IN WDFDRIVER driver) +extern VOID windivert_unload(IN WDFDRIVER driver_0) { - UNREFERENCED_PARAMETER(driver); - + PDRIVER_OBJECT driver = WdfDriverWdmGetDriverObject(driver_0); windivert_driver_unload(); + windivert_log_event(PsGetCurrentProcess(), driver, L"UNLOAD"); } /* @@ -3116,6 +3119,7 @@ windivert_ioctl_bad_flags: UINT32 process_id; WINDIVERT_LAYER layer; UINT8 filter_len; + WDFDEVICE device; ioctl = (PWINDIVERT_IOCTL)inbuf; filter_flags = ioctl->startup.flags; @@ -3172,8 +3176,15 @@ windivert_ioctl_bad_flags: context->reflect.open = FALSE; context->shutdown_recv_enabled = (layer != WINDIVERT_LAYER_REFLECT); + device = context->device; KeReleaseInStackQueuedSpinLock(&lock_handle); + if (InterlockedIncrement64(&num_opens) == 1) + { + PDRIVER_OBJECT driver = WdfDriverWdmGetDriverObject( + WdfDeviceGetDriver(device)); + windivert_log_event(process, driver, L"LOAD"); + } windivert_reflect_open_event(context); status = windivert_install_callouts(context, layer, filter_flags); @@ -6182,3 +6193,67 @@ void windivert_reflect_worker(IN WDFWORKITEM item) KeReleaseInStackQueuedSpinLock(&lock_handle); } +/* + * Log a driver event. + */ +static void windivert_log_event(PEPROCESS process, PDRIVER_OBJECT driver, + const wchar_t *msg_str) +{ + const wchar_t windivert_str[] = WINDIVERT_DEVICE_NAME + WINDIVERT_VERSION_LSTR; + wchar_t pid_str[16]; + size_t windivert_size = sizeof(windivert_str), msg_size, pid_size, size; + UNICODE_STRING string; + UINT8 *str; + PIO_ERROR_LOG_PACKET packet; + NTSTATUS status; + + size = ERROR_LOG_MAXIMUM_SIZE - sizeof(wchar_t) - + (sizeof(IO_ERROR_LOG_PACKET) + windivert_size + sizeof(pid_str)); + status = RtlStringCbLengthW(msg_str, size, &msg_size); + if (!NT_SUCCESS(status)) + { + return; + } + msg_size += sizeof(wchar_t); + + if (process != NULL) + { + string.Length = 0; + string.MaximumLength = sizeof(pid_str); + string.Buffer = pid_str; + status = RtlIntegerToUnicodeString( + (UINT32)(ULONG_PTR)PsGetProcessId(process), 10, &string); + pid_size = string.Length + sizeof(wchar_t); + } + if (process == NULL || !NT_SUCCESS(status)) + { + pid_str[0] = pid_str[1] = pid_str[2] = L'?'; + pid_str[3] = L'\0'; + pid_size = 4 * sizeof(wchar_t); + } + + size = sizeof(IO_ERROR_LOG_PACKET) + windivert_size + msg_size + pid_size; + if (size > ERROR_LOG_MAXIMUM_SIZE) + { + return; + } + packet = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(driver, (UCHAR)size); + if (packet == NULL) + { + return; + } + RtlZeroMemory(packet, size); + packet->NumberOfStrings = 3; + packet->StringOffset = sizeof(IO_ERROR_LOG_PACKET); + packet->ErrorCode = WINDIVERT_INFO_EVENT; + str = (UINT8 *)packet + packet->StringOffset; + RtlCopyMemory(str, windivert_str, windivert_size); + str += windivert_size; + RtlCopyMemory(str, msg_str, msg_size); + str += msg_size; + RtlCopyMemory(str, pid_str, pid_size); + + IoWriteErrorLogEntry(packet); +} + diff --git a/sys/windivert.rc b/sys/windivert.rc index 1f27518..11a4e97 100644 --- a/sys/windivert.rc +++ b/sys/windivert.rc @@ -35,6 +35,8 @@ #include #include +#include "windivert_log.rc" + #define VER_FILETYPE VFT_DRV #define VER_FILESUBTYPE VFT2_DRV_NETWORK #define VER_FILEDESCRIPTION_STR \ diff --git a/sys/windivert.vcxproj b/sys/windivert.vcxproj index 6033836..1633c68 100644 --- a/sys/windivert.vcxproj +++ b/sys/windivert.vcxproj @@ -45,6 +45,12 @@ x64 + + + . + . + + diff --git a/sys/windivert_log.mc b/sys/windivert_log.mc new file mode 100644 index 0000000..e8186b8 --- /dev/null +++ b/sys/windivert_log.mc @@ -0,0 +1,59 @@ +;/* +; * windivert_log.mc +; * (C) 2019, all rights reserved, +; * +; * This file is part of WinDivert. +; * +; * WinDivert is free software: you can redistribute it and/or modify it under +; * the terms of the GNU Lesser General Public License as published by the +; * Free Software Foundation, either version 3 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 Lesser General Public +; * License for more details. +; * +; * You should have received a copy of the GNU Lesser General Public License +; * along with this program. If not, see . +; * +; * WinDivert 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., 51 +; * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +; */ + +MessageIdTypedef=NTSTATUS + +SeverityNames = ( + Success = 0x0:STATUS_SEVERITY_SUCCESS + Informational = 0x1:STATUS_SEVERITY_INFORMATIONAL + Warning = 0x2:STATUS_SEVERITY_WARNING + Error = 0x3:STATUS_SEVERITY_ERROR +) + +FacilityNames = ( + System = 0x0:FACILITY_SYSTEM + Runtime = 0x2:FACILITY_RUNTIME + Stubs = 0x3:FACILITY_STUBS + Io = 0x4:FACILITY_IO_ERROR_CODE + WinDivert = 0x574:FACILITY_WINDIVERT +) + +MessageId=0x312D +Facility=WinDivert +Severity=Informational +SymbolicName=WINDIVERT_INFO_EVENT +Language=English +%2 %3 (processId=%4) +. +