Compare commits
28 Commits
v1.4.2
...
flow_layer
| Author | SHA1 | Date | |
|---|---|---|---|
| 29c6fda167 | |||
| 54e627e82b | |||
| 8ff3c86330 | |||
| edbe5ea942 | |||
| 67ad628a1f | |||
| 312050accb | |||
| 0a74b5528c | |||
| 084c78e4af | |||
| 33a461eef6 | |||
| 3e40705178 | |||
| 1ccf486132 | |||
| 4f7ff88664 | |||
| 3966ec1287 | |||
| fc868feb3e | |||
| de4245f95e | |||
| 316765aa92 | |||
| 86db54b400 | |||
| 34e8f96910 | |||
| 5aa4fc3c46 | |||
| fd75e6d42a | |||
| 2ab1ddf1d2 | |||
| f0dd1224b1 | |||
| 6250568974 | |||
| e82552153b | |||
| 822dca9c3f | |||
| 8e44f26b0a | |||
| 6ac22c1650 | |||
| 061535f7a3 |
@@ -125,3 +125,7 @@ WinDivert 1.4.1
|
||||
- Dual license WinDivert under LGPLv3 and GPLv2.
|
||||
WinDivert 1.4.2
|
||||
- Add workaround for pseudo checksum issue (see #134).
|
||||
WinDivert 1.4.3
|
||||
- WinDivert.dll no longer depends on MSVCRT*.dll.
|
||||
WinDivert 1.4.4
|
||||
- Optimize pseudo checksum calculation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
WinDivert is dual-licensed, and is available under the GNU Lesser General
|
||||
Public License (LGPL) Version 3 or the GNU General Public License (GPL)
|
||||
Version 2. Copies of the LGPLv3, GPLv3 and GPLv2 are provided below.
|
||||
WinDivert is dual-licensed under your choice of the GNU Lesser General Public
|
||||
License (LGPL) Version 3 or the GNU General Public License (GPL) Version 2.
|
||||
Copies of the LGPLv3, GPLv3 and GPLv2 are provided below.
|
||||
|
||||
==============================================================================
|
||||
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
WinDivert 1.4: Windows Packet Divert
|
||||
WinDivert 2.0: Windows Packet Divert
|
||||
====================================
|
||||
|
||||
1. Introduction
|
||||
---------------
|
||||
|
||||
Windows Packet Divert (WinDivert) is a user-mode packet capture-and-divert
|
||||
package for Windows Vista, Windows 2008, Windows 7, Windows 8 and Windows 10.
|
||||
Windows Packet Divert (WinDivert) is a user-mode packet interception library
|
||||
for Windows 7, Windows 8 and Windows 10.
|
||||
|
||||
WinDivert allows user-mode programs to capture/modify/drop network packets
|
||||
sent to/from the Windows network stack.
|
||||
In summary, WinDivert can
|
||||
WinDivert enables user-mode capturing/modifying/dropping of network packets
|
||||
sent to/from the Windows network stack. In summary, WinDivert can:
|
||||
- capture network packets
|
||||
- filter/drop network packets
|
||||
- sniff network packets
|
||||
- (re)inject network packets
|
||||
- modify network packets
|
||||
WinDivert can be used to implement user-mode packet filters, packet sniffers,
|
||||
firewalls, NAT, VPNs, tunneling applications, etc., etc..
|
||||
WinDivert can be used to implement user-mode packet filters, sniffers,
|
||||
firewalls, NATs, VPNs, IDSs, tunneling applications, etc..
|
||||
|
||||
The features of WinDivert include:
|
||||
WinDivert supports the following features:
|
||||
- packet interception, sniffing, or dropping modes
|
||||
- support for loopback (localhost) traffic
|
||||
- full IPv6 support
|
||||
@@ -27,23 +26,11 @@ The features of WinDivert include:
|
||||
- high-level filtering language
|
||||
- filter priorities
|
||||
- freely available under the terms of the GNU Lesser General Public
|
||||
License (LGPL)
|
||||
License (LGPLv3)
|
||||
|
||||
For more information about WinDivert, see doc/windivert.html
|
||||
For more information see doc/windivert.html
|
||||
|
||||
2. Similar Packages
|
||||
-------------------
|
||||
|
||||
WinDivert is similar to divert sockets in FreeBSD/MacOS, NETLINK sockets in
|
||||
Linux, and some commercial packet capturing packages such as WinPkFilter for
|
||||
Windows. The design of WinDivert is largely influenced by FreeBSD's divert
|
||||
sockets.
|
||||
|
||||
WinDivert in packet-sniffing mode is similar to Winpcap. Unlike Winpcap,
|
||||
WinDivert fully supports capturing loopback traffic. Furthermore, WinDivert
|
||||
supports packet interception, which is not supported in Winpcap.
|
||||
|
||||
3. Architecture
|
||||
2. Architecture
|
||||
---------------
|
||||
|
||||
The basic architecture of WinDivert is as follows:
|
||||
@@ -68,58 +55,37 @@ The basic architecture of WinDivert is as follows:
|
||||
| |
|
||||
+---------------+
|
||||
|
||||
The WinDivert.sys driver is inserted below the Windows network stack. The
|
||||
following then happens
|
||||
The WinDivert.sys driver is installed below the Windows network stack. The
|
||||
following actions occur:
|
||||
|
||||
(1) a new packet enters the network stack and is intercepted by WinDivert.sys
|
||||
(2a) if the packet matches a PROGRAM-defined filter, it is diverted. The
|
||||
PROGRAM reads the packet with a call to the WinDivertRecv() function.
|
||||
(2b) if the packet does not match the filter, the packet is permitted to
|
||||
continue as normal.
|
||||
(3) PROGRAM either drops, modifies, or re-injects the packet. If the
|
||||
(modified) packet is re-injected, via a call to WinDivertSend(), it is
|
||||
inserted back into the Windows network stack.
|
||||
(1) A new packet enters the network stack and is intercepted by WinDivert.sys
|
||||
(2a) If the packet matches the PROGRAM-defined filter, it is diverted. The
|
||||
PROGRAM can then read the packet using a call to WinDivertRecv().
|
||||
(2b) If the packet does not match the filter, the packet continues as normal.
|
||||
(3) PROGRAM either drops, modifies, or re-injects the packet. PROGRAM can
|
||||
re-inject the (modified) using a call to WinDivertSend().
|
||||
|
||||
4. Building
|
||||
-----------
|
||||
|
||||
(1) In a WinDDK build environment, run the command:
|
||||
|
||||
wddk-build.bat
|
||||
|
||||
(2) [OPTIONAL Visual Studio 2012 support] In a VS2012 command prompt, run the
|
||||
command:
|
||||
|
||||
msvc-build.bat
|
||||
|
||||
(3) [OPTIONAL MinGW support] In Linux with MinGW a cross-compiler, run the
|
||||
command:
|
||||
|
||||
sh mingw-build.sh
|
||||
|
||||
For more detailed build instructions, see doc\windivert.html
|
||||
|
||||
5. License
|
||||
3. License
|
||||
----------
|
||||
|
||||
WinDivert is dual-licensed, and is available under the GNU Lesser General
|
||||
Public License (LGPL) Version 3 or the GNU General Public License (GPL)
|
||||
Version 2. See the LICENSE file for more information.
|
||||
WinDivert is dual-licensed under your choice of the GNU Lesser General Public
|
||||
License (LGPL) Version 3 or the GNU General Public License (GPL) Version 2.
|
||||
See the LICENSE file for more information.
|
||||
|
||||
6. About
|
||||
4. About
|
||||
--------
|
||||
|
||||
WinDivert was written by basil.
|
||||
|
||||
For further information, or bug reports, please contact
|
||||
For further information, or bug reports, please contact:
|
||||
|
||||
basil AT reqrypt DOT org
|
||||
basil@reqrypt.org
|
||||
|
||||
The homepage for WinDivert is
|
||||
The homepage for WinDivert is:
|
||||
|
||||
https://reqrypt.org/windivert.html
|
||||
|
||||
The source code for WinDivert is hosted by GitHub at
|
||||
The source code for WinDivert is hosted by GitHub at:
|
||||
|
||||
https://github.com/basil00/Divert
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
|
||||
TARGETNAME=WinDivert
|
||||
TARGETTYPE=DYNLINK
|
||||
TARGETPATH=..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\advapi32.lib \
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\kernel32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib
|
||||
C_DEFINES=/DWIN32 /D_WINDOWS /D_USRDLL /DUSE_STDAFX /DUNICODE /D_UNICODE
|
||||
DLLENTRY=WinDivertDllEntry
|
||||
DLLDEF=windivert.def
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\include
|
||||
SOURCES=windivert.c
|
||||
|
||||
+135
-388
@@ -39,7 +39,7 @@
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -51,47 +51,18 @@
|
||||
#define WINDIVERT_DRIVER32_SYS L"\\" WINDIVERT_DRIVER_NAME L"32.sys"
|
||||
#define WINDIVERT_DRIVER64_SYS L"\\" WINDIVERT_DRIVER_NAME L"64.sys"
|
||||
|
||||
/*
|
||||
* Definitions to remove (some) external dependencies:
|
||||
*/
|
||||
#define BYTESWAP16(x) \
|
||||
((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
|
||||
#define BYTESWAP32(x) \
|
||||
((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
|
||||
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
|
||||
#define ntohs(x) BYTESWAP16(x)
|
||||
#define htons(x) BYTESWAP16(x)
|
||||
#define ntohl(x) BYTESWAP32(x)
|
||||
#define htonl(x) BYTESWAP32(x)
|
||||
|
||||
static BOOLEAN WinDivertIsXDigit(char c);
|
||||
static BOOLEAN WinDivertIsSpace(char c);
|
||||
static BOOLEAN WinDivertIsAlNum(char c);
|
||||
static char WinDivertToLower(char c);
|
||||
static BOOLEAN WinDivertStrLen(const wchar_t *s, size_t maxlen,
|
||||
size_t *lenptr);
|
||||
static BOOLEAN WinDivertStrCpy(wchar_t *dst, size_t dstlen,
|
||||
const wchar_t *src);
|
||||
static int WinDivertStrCmp(const char *s, const char *t);
|
||||
static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr);
|
||||
static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr);
|
||||
|
||||
/*
|
||||
* IPv4/IPv6 pseudo headers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 SrcAddr;
|
||||
UINT32 DstAddr;
|
||||
UINT8 Zero;
|
||||
UINT8 Protocol;
|
||||
UINT16 Length;
|
||||
} WINDIVERT_PSEUDOHDR, *PWINDIVERT_PSEUDOHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 SrcAddr[4];
|
||||
UINT32 DstAddr[4];
|
||||
UINT32 Length;
|
||||
UINT32 Zero:24;
|
||||
UINT32 NextHdr:8;
|
||||
} WINDIVERT_PSEUDOV6HDR, *PWINDIVERT_PSEUDOV6HDR;
|
||||
|
||||
/*
|
||||
* Misc.
|
||||
*/
|
||||
@@ -108,19 +79,16 @@ typedef struct
|
||||
static BOOLEAN WinDivertUse32Bit(void);
|
||||
static BOOLEAN WinDivertGetDriverFileName(LPWSTR sys_str);
|
||||
static SC_HANDLE WinDivertDriverInstall(VOID);
|
||||
static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen);
|
||||
static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped);
|
||||
static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT64 arg1,
|
||||
UINT64 arg2, PVOID buf, UINT len, UINT *iolen);
|
||||
static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT64 arg1,
|
||||
UINT64 arg2, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped);
|
||||
static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len);
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
static void WinDivertFilterDump(windivert_ioctl_filter_t filter, UINT16 len);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include the helper API implementation.
|
||||
*/
|
||||
#include "windivert_shared.c"
|
||||
#include "windivert_helper.c"
|
||||
|
||||
/*
|
||||
@@ -332,8 +300,8 @@ WinDivertDriverInstallExit:
|
||||
/*
|
||||
* Perform a DeviceIoControl.
|
||||
*/
|
||||
static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen)
|
||||
static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT64 arg1,
|
||||
UINT64 arg2, PVOID buf, UINT len, UINT *iolen)
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
DWORD iolen0;
|
||||
@@ -352,7 +320,7 @@ static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
|
||||
memset(&overlapped, 0, sizeof(overlapped));
|
||||
overlapped.hEvent = event;
|
||||
if (!WinDivertIoControlEx(handle, code, arg8, arg, buf, len, iolen,
|
||||
if (!WinDivertIoControlEx(handle, code, arg1, arg2, buf, len, iolen,
|
||||
&overlapped))
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING ||
|
||||
@@ -371,17 +339,15 @@ static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
/*
|
||||
* Perform an (overlapped) DeviceIoControl.
|
||||
*/
|
||||
static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped)
|
||||
static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT64 arg1,
|
||||
UINT64 arg2, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped)
|
||||
{
|
||||
struct windivert_ioctl_s ioctl;
|
||||
WINDIVERT_IOCTL ioctl;
|
||||
BOOL result;
|
||||
DWORD iolen0;
|
||||
|
||||
ioctl.version = WINDIVERT_IOCTL_VERSION;
|
||||
ioctl.magic = WINDIVERT_IOCTL_MAGIC;
|
||||
ioctl.arg8 = arg8;
|
||||
ioctl.arg = arg;
|
||||
ioctl.arg1 = arg1;
|
||||
ioctl.arg2 = arg2;
|
||||
result = DeviceIoControl(handle, code, &ioctl, sizeof(ioctl), buf,
|
||||
(DWORD)len, &iolen0, overlapped);
|
||||
if (result && iolen != NULL)
|
||||
@@ -397,39 +363,48 @@ static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
INT16 priority, UINT64 flags)
|
||||
{
|
||||
struct windivert_ioctl_filter_s object[WINDIVERT_FILTER_MAXLEN];
|
||||
WINDIVERT_FILTER object[WINDIVERT_FILTER_MAXLEN];
|
||||
UINT obj_len;
|
||||
ERROR comp_err;
|
||||
DWORD err;
|
||||
HANDLE handle;
|
||||
SC_HANDLE service;
|
||||
UINT32 priority32;
|
||||
|
||||
UINT64 priority64, filter_flags;
|
||||
|
||||
// Parameter checking.
|
||||
if (!WINDIVERT_FLAGS_VALID(flags) || layer > WINDIVERT_LAYER_MAX)
|
||||
switch (layer)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
case WINDIVERT_LAYER_SOCKET:
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
priority32 = WINDIVERT_PRIORITY(priority);
|
||||
if (priority32 < WINDIVERT_PRIORITY_MIN ||
|
||||
priority32 > WINDIVERT_PRIORITY_MAX)
|
||||
if (!WINDIVERT_FLAGS_VALID(flags))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Compile the filter:
|
||||
if (priority < WINDIVERT_PRIORITY_MIN ||
|
||||
priority > WINDIVERT_PRIORITY_MAX)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Compile & analyze the filter:
|
||||
comp_err = WinDivertCompileFilter(filter, layer, object, &obj_len);
|
||||
if (IS_ERROR(comp_err))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
WinDivertFilterDump(object, obj_len);
|
||||
#endif
|
||||
filter_flags = WinDivertAnalyzeFilter(layer, object, obj_len);
|
||||
|
||||
// Attempt to open the WinDivert device:
|
||||
handle = CreateFile(L"\\\\.\\" WINDIVERT_DEVICE_NAME,
|
||||
@@ -444,6 +419,11 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Open failed because the device isn't installed; install it now.
|
||||
if ((flags & WINDIVERT_FLAG_NO_INSTALL) != 0)
|
||||
{
|
||||
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
SetLastError(0);
|
||||
service = WinDivertDriverInstall();
|
||||
if (service == NULL)
|
||||
@@ -472,8 +452,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
// Set the layer:
|
||||
if (layer != WINDIVERT_LAYER_DEFAULT)
|
||||
{
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_LAYER, 0,
|
||||
(UINT64)layer, NULL, 0, NULL))
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_LAYER,
|
||||
(UINT64)layer, 0, NULL, 0, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -483,8 +463,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
// Set the flags:
|
||||
if (flags != 0)
|
||||
{
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_FLAGS, 0,
|
||||
(UINT64)flags, NULL, 0, NULL))
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_FLAGS, flags, 0,
|
||||
NULL, 0, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -492,10 +472,12 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Set the priority:
|
||||
if (priority32 != WINDIVERT_PRIORITY_DEFAULT)
|
||||
if (priority != WINDIVERT_PRIORITY_DEFAULT)
|
||||
{
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_PRIORITY, 0,
|
||||
(UINT64)priority32, NULL, 0, NULL))
|
||||
// Make positive:
|
||||
priority64 = (UINT64)((INT64)priority + WINDIVERT_PRIORITY_MAX);
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_PRIORITY,
|
||||
priority64, 0, NULL, 0, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -503,8 +485,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Start the filter:
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_START_FILTER, 0, 0,
|
||||
object, obj_len*sizeof(struct windivert_ioctl_filter_s), NULL))
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_START_FILTER,
|
||||
filter_flags, 0, object, obj_len * sizeof(WINDIVERT_FILTER), NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -514,56 +496,21 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for #134
|
||||
*/
|
||||
static void WinDivertFixChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ADDRESS addr)
|
||||
{
|
||||
UINT64 flags =
|
||||
WINDIVERT_HELPER_NO_IP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM;
|
||||
BOOL calc = FALSE;
|
||||
if (addr->PseudoIPChecksum != 0)
|
||||
{
|
||||
addr->PseudoIPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_IP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (addr->PseudoTCPChecksum != 0)
|
||||
{
|
||||
addr->PseudoTCPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_TCP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (addr->PseudoUDPChecksum != 0)
|
||||
{
|
||||
addr->PseudoUDPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_UDP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (calc)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(pPacket, packetLen, addr, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a WinDivert packet.
|
||||
*/
|
||||
extern BOOL WinDivertRecv(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ADDRESS addr, UINT *readlen)
|
||||
{
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV, 0, (UINT64)addr,
|
||||
pPacket, packetLen, readlen);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV, (UINT64)addr,
|
||||
(UINT64)NULL, pPacket, packetLen, readlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a WinDivert packet.
|
||||
*/
|
||||
extern BOOL WinDivertRecvEx(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
UINT64 flags, PWINDIVERT_ADDRESS addr, UINT *readlen,
|
||||
UINT *readLen, UINT64 flags, PWINDIVERT_ADDRESS addr, UINT *pAddrLen,
|
||||
LPOVERLAPPED overlapped)
|
||||
{
|
||||
if (flags != 0)
|
||||
@@ -573,57 +520,62 @@ extern BOOL WinDivertRecvEx(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
}
|
||||
if (overlapped == NULL)
|
||||
{
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV, 0,
|
||||
(UINT64)addr, pPacket, packetLen, readlen);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV,
|
||||
(UINT64)addr, (UINT64)pAddrLen, pPacket, packetLen, readLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return WinDivertIoControlEx(handle, IOCTL_WINDIVERT_RECV, 0,
|
||||
(UINT64)addr, pPacket, packetLen, readlen, overlapped);
|
||||
return WinDivertIoControlEx(handle, IOCTL_WINDIVERT_RECV,
|
||||
(UINT64)addr, (UINT64)pAddrLen, pPacket, packetLen, readLen,
|
||||
overlapped);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a WinDivert packet.
|
||||
*/
|
||||
extern BOOL WinDivertSend(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ADDRESS addr, UINT *writelen)
|
||||
extern BOOL WinDivertSend(HANDLE handle, const VOID *pPacket, UINT packetLen,
|
||||
const WINDIVERT_ADDRESS *addr, UINT *writelen)
|
||||
{
|
||||
if (addr == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertFixChecksums(pPacket, packetLen, addr);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, 0, (UINT64)addr,
|
||||
pPacket, packetLen, writelen);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, (UINT64)addr,
|
||||
sizeof(WINDIVERT_ADDRESS), (PVOID)pPacket, packetLen, writelen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a WinDivert packet.
|
||||
*/
|
||||
extern BOOL WinDivertSendEx(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
UINT64 flags, PWINDIVERT_ADDRESS addr, UINT *writelen,
|
||||
extern BOOL WinDivertSendEx(HANDLE handle, const VOID *pPacket, UINT packetLen,
|
||||
UINT *writeLen, UINT64 flags, const WINDIVERT_ADDRESS *addr, UINT addrLen,
|
||||
LPOVERLAPPED overlapped)
|
||||
{
|
||||
if (flags != 0 || addr == NULL)
|
||||
if (flags != 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertFixChecksums(pPacket, packetLen, addr);
|
||||
if (overlapped == NULL)
|
||||
{
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, 0,
|
||||
(UINT64)addr, pPacket, packetLen, writelen);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND,
|
||||
(UINT64)addr, (UINT64)addrLen, (PVOID)pPacket, packetLen,
|
||||
writeLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return WinDivertIoControlEx(handle, IOCTL_WINDIVERT_SEND, 0,
|
||||
(UINT64)addr, pPacket, packetLen, writelen, overlapped);
|
||||
return WinDivertIoControlEx(handle, IOCTL_WINDIVERT_SEND,
|
||||
(UINT64)addr, (UINT64)addrLen, (PVOID)pPacket, packetLen, writeLen,
|
||||
overlapped);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown a WinDivert handle.
|
||||
*/
|
||||
extern BOOL WinDivertShutdown(HANDLE handle, WINDIVERT_SHUTDOWN how)
|
||||
{
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SHUTDOWN,
|
||||
(UINT64)how, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a WinDivert handle.
|
||||
*/
|
||||
@@ -694,6 +646,33 @@ extern BOOL WinDivertGetParam(HANDLE handle, WINDIVERT_PARAM param,
|
||||
/* REPLACEMENTS */
|
||||
/*****************************************************************************/
|
||||
|
||||
static BOOLEAN WinDivertIsXDigit(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'f') ||
|
||||
(c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
static BOOLEAN WinDivertIsSpace(char c)
|
||||
{
|
||||
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' ||
|
||||
c == '\v');
|
||||
}
|
||||
|
||||
static BOOLEAN WinDivertIsAlNum(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
static char WinDivertToLower(char c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return 'a' + (c - 'A');
|
||||
return c;
|
||||
}
|
||||
|
||||
static BOOLEAN WinDivertStrLen(const wchar_t *s, size_t maxlen,
|
||||
size_t *lenptr)
|
||||
{
|
||||
@@ -728,6 +707,24 @@ static BOOLEAN WinDivertStrCpy(wchar_t *dst, size_t dstlen, const wchar_t *src)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int WinDivertStrCmp(const char *s, const char *t)
|
||||
{
|
||||
int cmp;
|
||||
size_t i;
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
cmp = s[i] - t[i];
|
||||
if (cmp != 0)
|
||||
{
|
||||
return cmp;
|
||||
}
|
||||
if (s[i] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr)
|
||||
{
|
||||
size_t i = 0;
|
||||
@@ -766,7 +763,7 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr)
|
||||
{
|
||||
i += 2;
|
||||
}
|
||||
for (; str[i] && isxdigit(str[i]); i++)
|
||||
for (; str[i] && WinDivertIsXDigit(str[i]); i++)
|
||||
{
|
||||
num0 = num;
|
||||
num *= 16;
|
||||
@@ -776,7 +773,7 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr)
|
||||
}
|
||||
else
|
||||
{
|
||||
num += (UINT32)(tolower(str[i]) - 'a') + 0x0A;
|
||||
num += (UINT32)(WinDivertToLower(str[i]) - 'a') + 0x0A;
|
||||
}
|
||||
if (num0 > num)
|
||||
{
|
||||
@@ -791,253 +788,3 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* DEBUGGING */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
/*
|
||||
* Print a filter (debugging).
|
||||
*/
|
||||
static void WinDivertFilterDump(windivert_ioctl_filter_t filter, UINT16 len)
|
||||
{
|
||||
UINT16 i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
printf("label_%u:\n\tif (", i);
|
||||
switch (filter[i].field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
printf("zero ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
printf("inbound ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
printf("outbound ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
printf("ifIdx ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
printf("subIfIdx ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP:
|
||||
printf("ip ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6:
|
||||
printf("ipv6 ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP:
|
||||
printf("icmp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6:
|
||||
printf("icmpv6 ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP:
|
||||
printf("tcp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP:
|
||||
printf("udp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
|
||||
printf("ip.HdrLength ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_TOS:
|
||||
printf("ip.TOS ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_LENGTH:
|
||||
printf("ip.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_ID:
|
||||
printf("ip.Id ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_DF:
|
||||
printf("ip.DF ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_MF:
|
||||
printf("ip.MF ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_FRAGOFF:
|
||||
printf("ip.FragOff ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_TTL:
|
||||
printf("ip.TTL ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_PROTOCOL:
|
||||
printf("ip.Protocol ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_CHECKSUM:
|
||||
printf("ip.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_SRCADDR:
|
||||
printf("ip.SrcAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_DSTADDR:
|
||||
printf("ip.DstAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS:
|
||||
printf("ipv6.TrafficClass ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL:
|
||||
printf("ipv6.FlowLabel ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_LENGTH:
|
||||
printf("ipv6.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR:
|
||||
printf("ipv6.NextHdr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT:
|
||||
printf("ipv6.HopLimit ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
|
||||
printf("ipv6.SrcAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
|
||||
printf("ipv6.DstAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_TYPE:
|
||||
printf("icmp.Type ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_CODE:
|
||||
printf("icmp.Code ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM:
|
||||
printf("icmp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_BODY:
|
||||
printf("icmp.Body ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE:
|
||||
printf("icmpv6.Type ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_CODE:
|
||||
printf("icmpv6.Code ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM:
|
||||
printf("icmpv6.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_BODY:
|
||||
printf("icmpv6.Body ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SRCPORT:
|
||||
printf("tcp.SrcPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_DSTPORT:
|
||||
printf("tcp.DstPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SEQNUM:
|
||||
printf("tcp.SeqNum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_ACKNUM:
|
||||
printf("tcp.AckNum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH:
|
||||
printf("tcp.HdrLength ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URG:
|
||||
printf("tcp.Urg ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_ACK:
|
||||
printf("tcp.Ack ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PSH:
|
||||
printf("tcp.Psh ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_RST:
|
||||
printf("tcp.Rst ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SYN:
|
||||
printf("tcp.Syn ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_FIN:
|
||||
printf("tcp.Fin ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_WINDOW:
|
||||
printf("tcp.Window ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM:
|
||||
printf("tcp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URGPTR:
|
||||
printf("tcp.UrgPtr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH:
|
||||
printf("tcp.PayloadLength " );
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_SRCPORT:
|
||||
printf("udp.SrcPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_DSTPORT:
|
||||
printf("udp.DstPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_LENGTH:
|
||||
printf("udp.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM:
|
||||
printf("udp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
printf("udp.PayloadLength ");
|
||||
break;
|
||||
default:
|
||||
printf("unknown.Field ");
|
||||
break;
|
||||
}
|
||||
switch (filter[i].test)
|
||||
{
|
||||
case WINDIVERT_FILTER_TEST_EQ:
|
||||
printf("== ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_NEQ:
|
||||
printf("!= ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_LT:
|
||||
printf("< ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_LEQ:
|
||||
printf("<= ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_GT:
|
||||
printf("> ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_GEQ:
|
||||
printf(">= ");
|
||||
break;
|
||||
default:
|
||||
printf("?? ");
|
||||
break;
|
||||
}
|
||||
printf("%u)\n", filter[i].arg[0]);
|
||||
switch (filter[i].success)
|
||||
{
|
||||
case WINDIVERT_FILTER_RESULT_ACCEPT:
|
||||
printf("\t\treturn ACCEPT;\n");
|
||||
break;
|
||||
case WINDIVERT_FILTER_RESULT_REJECT:
|
||||
printf("\t\treturn REJECT;\n");
|
||||
break;
|
||||
default:
|
||||
printf("\t\tgoto label_%u;\n", filter[i].success);
|
||||
break;
|
||||
}
|
||||
printf("\telse\n");
|
||||
switch (filter[i].failure)
|
||||
{
|
||||
case WINDIVERT_FILTER_RESULT_ACCEPT:
|
||||
printf("\t\treturn ACCEPT;\n");
|
||||
break;
|
||||
case WINDIVERT_FILTER_RESULT_REJECT:
|
||||
printf("\t\treturn REJECT;\n");
|
||||
break;
|
||||
default:
|
||||
printf("\t\tgoto label_%u;\n", filter[i].failure);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WINDIVERT_DEBUG */
|
||||
|
||||
|
||||
+14
-1
@@ -6,12 +6,25 @@ EXPORTS
|
||||
WinDivertRecvEx
|
||||
WinDivertSend
|
||||
WinDivertSendEx
|
||||
WinDivertShutdown
|
||||
WinDivertClose
|
||||
WinDivertSetParam
|
||||
WinDivertGetParam
|
||||
WinDivertHelperCalcChecksums
|
||||
WinDivertHelperHashPacket
|
||||
WinDivertHelperParsePacket
|
||||
WinDivertHelperParseIPv4Address
|
||||
WinDivertHelperParseIPv6Address
|
||||
WinDivertHelperCheckFilter
|
||||
WinDivertHelperFormatIPv4Address
|
||||
WinDivertHelperFormatIPv6Address
|
||||
WinDivertHelperCompileFilter
|
||||
WinDivertHelperEvalFilter
|
||||
WinDivertHelperFormatFilter
|
||||
WinDivertHelperNtohs
|
||||
WinDivertHelperHtons
|
||||
WinDivertHelperNtohl
|
||||
WinDivertHelperHtonl
|
||||
WinDivertHelperNtohll
|
||||
WinDivertHelperHtonll
|
||||
WinDivertHelperNtohIpv6Address
|
||||
WinDivertHelperHtonIpv6Address
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<TARGETNAME>WinDivert</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<ModuleDefinitionFile>windivert.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="windivert.c"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="windivert.def"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* windivert_hash.c
|
||||
* (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (C) 2012-2016, Yann Collet
|
||||
*
|
||||
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a modified version of the 64bit xxHash algorithm:
|
||||
* - The algorithm is seeded with packet data rather than the single 64bit
|
||||
* "seed" value.
|
||||
* - The input sized is fixed to 32bytes (excluding the seed), so there is
|
||||
* only ever a single round. As such, the algorithm has been specialized.
|
||||
*/
|
||||
|
||||
#define WINDIVERT_ROTL(x, r) (((x) << (r)) | ((x) >> (64 - (r))))
|
||||
|
||||
static const UINT64 WINDIVERT_PRIME64_1 = 11400714785074694791ull;
|
||||
static const UINT64 WINDIVERT_PRIME64_2 = 14029467366897019727ull;
|
||||
static const UINT64 WINDIVERT_PRIME64_3 = 1609587929392839161ull;
|
||||
static const UINT64 WINDIVERT_PRIME64_4 = 9650029242287828579ull;
|
||||
|
||||
static UINT64 WinDivertXXH64Round(UINT64 acc, UINT64 input)
|
||||
{
|
||||
acc += input * WINDIVERT_PRIME64_2;
|
||||
acc = WINDIVERT_ROTL(acc, 31);
|
||||
acc *= WINDIVERT_PRIME64_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
static UINT64 WinDivertXXH64MergeRound(UINT64 acc, UINT64 val)
|
||||
{
|
||||
val = WinDivertXXH64Round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * WINDIVERT_PRIME64_1 + WINDIVERT_PRIME64_4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
static UINT64 WinDivertXXH64Avalanche(UINT64 h64)
|
||||
{
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= WINDIVERT_PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= WINDIVERT_PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
return h64;
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert packet hash function.
|
||||
*/
|
||||
static UINT64 WinDivertHashPacket(UINT64 seed, PWINDIVERT_IPHDR ip_header,
|
||||
PWINDIVERT_IPV6HDR ipv6_header, PWINDIVERT_ICMPHDR icmp_header,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header, PWINDIVERT_TCPHDR tcp_header,
|
||||
PWINDIVERT_UDPHDR udp_header)
|
||||
{
|
||||
UINT64 h64, v1, v2, v3, v4, v[4], *data64;
|
||||
UINT32 *data32;
|
||||
UINT i;
|
||||
static const UINT64 padding64[] = // SHA2 IV
|
||||
{
|
||||
0x428A2F9871374491ull, 0xB5C0FBCFE9B5DBA5ull, 0x3956C25B59F111F1ull,
|
||||
0x923F82A4AB1C5ED5ull, 0xD807AA9812835B01ull, 0x243185BE550C7DC3ull,
|
||||
0x72BE5D7480DEB1FEull, 0x9BDC06A7C19BF174ull, 0xE49B69C1EFBE4786ull,
|
||||
};
|
||||
|
||||
// Set-up seed & data
|
||||
v1 = seed ^ padding64[0];
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)ip_header;
|
||||
v2 = data64[0] ^ padding64[1];
|
||||
v3 = data64[1] ^ padding64[2];
|
||||
data32 = (UINT32 *)ip_header;
|
||||
v4 = (UINT64)data32[4] ^ padding64[3];
|
||||
i = 0;
|
||||
}
|
||||
else if (ipv6_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)ipv6_header;
|
||||
v2 = data64[0] ^ padding64[1];
|
||||
v3 = data64[1] ^ padding64[2];
|
||||
v4 = data64[2] ^ padding64[3];
|
||||
v[0] = data64[3] ^ padding64[4];
|
||||
v[1] = data64[4] ^ padding64[5];
|
||||
i = 2;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)tcp_header;
|
||||
v[i] = data64[0] ^ padding64[i+4]; i++;
|
||||
v[i] = data64[1] ^ padding64[i+4]; i++;
|
||||
data32 = (UINT32 *)tcp_header;
|
||||
if (i <= 3)
|
||||
{
|
||||
v[i] = (UINT64)data32[4] ^ padding64[i+4]; i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
v2 ^= ((UINT64)data32[4] << 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)udp_header;
|
||||
v[i] = data64[0] ^ padding64[i+4]; i++;
|
||||
}
|
||||
else if (icmp_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)icmp_header;
|
||||
v[i] = data64[0] ^ padding64[i+4]; i++;
|
||||
}
|
||||
else if (icmpv6_header != NULL)
|
||||
{
|
||||
data64 = (UINT64 *)icmpv6_header;
|
||||
v[i] = data64[0] ^ padding64[i+4]; i++;
|
||||
}
|
||||
}
|
||||
|
||||
while (i <= 3)
|
||||
{
|
||||
v[i] = seed ^ padding64[i+4]; i++;
|
||||
}
|
||||
|
||||
// Hash
|
||||
v1 = WinDivertXXH64Round(v[0], v1);
|
||||
v2 = WinDivertXXH64Round(v[1], v2);
|
||||
v3 = WinDivertXXH64Round(v[2], v3);
|
||||
v4 = WinDivertXXH64Round(v[3], v4);
|
||||
h64 = WINDIVERT_ROTL(v1, 1) + WINDIVERT_ROTL(v2, 7) +
|
||||
WINDIVERT_ROTL(v3, 12) + WINDIVERT_ROTL(v4, 18);
|
||||
h64 = WinDivertXXH64MergeRound(h64, v1);
|
||||
h64 = WinDivertXXH64MergeRound(h64, v2);
|
||||
h64 = WinDivertXXH64MergeRound(h64, v3);
|
||||
h64 = WinDivertXXH64MergeRound(h64, v4);
|
||||
h64 += 32; // "length"
|
||||
h64 = WinDivertXXH64Avalanche(h64);
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
+2817
-723
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* windivert_shared.c
|
||||
* (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define WINDIVERT_OBJECT_MAXLEN \
|
||||
(8 + 4 + 2 + WINDIVERT_FILTER_MAXLEN * (1 + 2 + 2 + 4*7 + 2 + 2) + 1)
|
||||
|
||||
#define MAX(a, b) ((a) > (b)? (a): (b))
|
||||
|
||||
/*
|
||||
* Definitions to remove (some) external dependencies:
|
||||
*/
|
||||
#define BYTESWAP16(x) \
|
||||
((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
|
||||
#define BYTESWAP32(x) \
|
||||
((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
|
||||
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
|
||||
#define BYTESWAP64(x) \
|
||||
((((x) >> 56) & 0x00000000000000FFull) | \
|
||||
(((x) >> 40) & 0x000000000000FF00ull) | \
|
||||
(((x) >> 24) & 0x0000000000FF0000ull) | \
|
||||
(((x) >> 8) & 0x00000000FF000000ull) | \
|
||||
(((x) << 8) & 0x000000FF00000000ull) | \
|
||||
(((x) << 24) & 0x0000FF0000000000ull) | \
|
||||
(((x) << 40) & 0x00FF000000000000ull) | \
|
||||
(((x) << 56) & 0xFF00000000000000ull))
|
||||
#define ntohs(x) BYTESWAP16(x)
|
||||
#define htons(x) BYTESWAP16(x)
|
||||
#define ntohl(x) BYTESWAP32(x)
|
||||
#define htonl(x) BYTESWAP32(x)
|
||||
|
||||
#include "windivert_hash.c"
|
||||
|
||||
/*
|
||||
* IPv4/IPv6 pseudo headers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 SrcAddr;
|
||||
UINT32 DstAddr;
|
||||
UINT8 Zero;
|
||||
UINT8 Protocol;
|
||||
UINT16 Length;
|
||||
} WINDIVERT_PSEUDOHDR, *PWINDIVERT_PSEUDOHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 SrcAddr[4];
|
||||
UINT32 DstAddr[4];
|
||||
UINT32 Length;
|
||||
UINT32 Zero:24;
|
||||
UINT32 NextHdr:8;
|
||||
} WINDIVERT_PSEUDOV6HDR, *PWINDIVERT_PSEUDOV6HDR;
|
||||
|
||||
/*
|
||||
* Streams.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *data;
|
||||
UINT pos;
|
||||
UINT max;
|
||||
BOOL overflow;
|
||||
} WINDIVERT_STREAM, *PWINDIVERT_STREAM;
|
||||
|
||||
/*
|
||||
* Prototypes.
|
||||
*/
|
||||
static UINT16 WinDivertInitPseudoHeader(PWINDIVERT_IPHDR ip_header,
|
||||
PWINDIVERT_IPV6HDR ipv6_header, UINT8 protocol, UINT len,
|
||||
void *pseudo_header);
|
||||
static UINT16 WinDivertCalcChecksum(PVOID pseudo_header,
|
||||
UINT16 pseudo_header_len, PVOID data, UINT len);
|
||||
|
||||
/*
|
||||
* Put a char into a stream.
|
||||
*/
|
||||
static void WinDivertPutChar(PWINDIVERT_STREAM stream, char c)
|
||||
{
|
||||
if (stream->pos >= stream->max)
|
||||
{
|
||||
stream->overflow = TRUE;
|
||||
return;
|
||||
}
|
||||
stream->data[stream->pos] = c;
|
||||
stream->pos++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a string into a stream.
|
||||
*/
|
||||
static void WinDivertPutString(PWINDIVERT_STREAM stream, const char *str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
WinDivertPutChar(stream, *str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a NUL character into a stream.
|
||||
*/
|
||||
static void WinDivertPutNul(PWINDIVERT_STREAM stream)
|
||||
{
|
||||
if (stream->pos >= stream->max && stream->max > 0)
|
||||
{
|
||||
stream->data[stream->max-1] = '\0'; // Truncate
|
||||
}
|
||||
else
|
||||
{
|
||||
WinDivertPutChar(stream, '\0');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a number.
|
||||
*/
|
||||
static void WinDivertSerializeNumber(PWINDIVERT_STREAM stream, UINT32 val)
|
||||
{
|
||||
UINT64 mask = 0x00000007C0000000ull;
|
||||
UINT dig = 6;
|
||||
UINT64 val64 = (UINT64)val;
|
||||
BOOL final;
|
||||
|
||||
while ((mask & val64) == 0 && dig != 0)
|
||||
{
|
||||
mask >>= 5;
|
||||
dig--;
|
||||
}
|
||||
while (TRUE)
|
||||
{
|
||||
final = (dig == 0);
|
||||
WinDivertPutChar(stream, '!' + (char)((mask & val64) >> (5 * dig)) +
|
||||
(final? 32: 0));
|
||||
if (final)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mask >>= 5;
|
||||
dig--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a test.
|
||||
*/
|
||||
static void WinDivertSerializeTest(PWINDIVERT_STREAM stream,
|
||||
const WINDIVERT_FILTER *filter)
|
||||
{
|
||||
INT idx;
|
||||
UINT i;
|
||||
|
||||
WinDivertPutChar(stream, '_');
|
||||
WinDivertSerializeNumber(stream, filter->field);
|
||||
WinDivertSerializeNumber(stream, filter->test);
|
||||
WinDivertSerializeNumber(stream, filter->arg[0]);
|
||||
switch (filter->field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
|
||||
case WINDIVERT_FILTER_FIELD_LOCALADDR:
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
WinDivertSerializeNumber(stream, filter->arg[i]);
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
idx = (INT)filter->arg[1];
|
||||
idx += UINT16_MAX;
|
||||
WinDivertSerializeNumber(stream, (UINT32)idx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
WinDivertSerializeNumber(stream, (UINT8)(filter->success + 2));
|
||||
WinDivertSerializeNumber(stream, (UINT8)(filter->failure + 2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a test.
|
||||
*/
|
||||
static void WinDivertSerializeFilter(PWINDIVERT_STREAM stream,
|
||||
const WINDIVERT_FILTER *filter, UINT8 length)
|
||||
{
|
||||
UINT8 i;
|
||||
WinDivertPutString(stream, "@WinDiv_"); // Magic
|
||||
WinDivertSerializeNumber(stream, 0); // Version
|
||||
WinDivertSerializeNumber(stream, length); // Length
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
WinDivertSerializeTest(stream, filter + i);
|
||||
}
|
||||
WinDivertPutNul(stream);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip well-known IPv6 extension headers.
|
||||
*/
|
||||
static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
|
||||
{
|
||||
UINT hdrlen;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (*len <= 2)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
hdrlen = (UINT)*(*header + 1);
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_FRAGMENT:
|
||||
hdrlen = 8;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
hdrlen += 2;
|
||||
hdrlen *= 4;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
hdrlen++;
|
||||
hdrlen *= 8;
|
||||
break;
|
||||
case IPPROTO_NONE:
|
||||
return proto;
|
||||
default:
|
||||
return proto;
|
||||
}
|
||||
|
||||
if (hdrlen >= *len)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
proto = **header;
|
||||
*header += hdrlen;
|
||||
*len -= hdrlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 *pProto,
|
||||
PVOID *ppData, UINT *pDataLen)
|
||||
{
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6_header = NULL;
|
||||
PWINDIVERT_ICMPHDR icmp_header = NULL;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header = NULL;
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT16 header_len;
|
||||
UINT8 trans_proto = 0;
|
||||
PVOID data = NULL;
|
||||
UINT data_len = 0;
|
||||
BOOL success;
|
||||
|
||||
if (pPacket == NULL || packetLen < sizeof(UINT8))
|
||||
{
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = pPacket;
|
||||
data_len = packetLen;
|
||||
|
||||
ip_header = (PWINDIVERT_IPHDR)data;
|
||||
switch (ip_header->Version)
|
||||
{
|
||||
case 4:
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5 ||
|
||||
data_len < ip_header->HdrLength*sizeof(UINT32) ||
|
||||
ntohs(ip_header->Length) != data_len)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ip_header->Protocol;
|
||||
header_len = ip_header->HdrLength*sizeof(UINT32);
|
||||
data = (PVOID)((UINT8 *)data + header_len);
|
||||
data_len -= header_len;
|
||||
break;
|
||||
case 6:
|
||||
ip_header = NULL;
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
|
||||
ntohs(ipv6_header->Length) !=
|
||||
data_len - sizeof(WINDIVERT_IPV6HDR))
|
||||
{
|
||||
ipv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ipv6_header->NextHdr;
|
||||
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_IPV6HDR);
|
||||
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
|
||||
&data_len);
|
||||
break;
|
||||
default:
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
switch (trans_proto)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_TCPHDR) ||
|
||||
tcp_header->HdrLength < 5 ||
|
||||
data_len < tcp_header->HdrLength*sizeof(UINT32))
|
||||
{
|
||||
tcp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
header_len = tcp_header->HdrLength*sizeof(UINT32);
|
||||
data = ((UINT8 *)data + header_len);
|
||||
data_len -= header_len;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_UDPHDR) ||
|
||||
ntohs(udp_header->Length) != data_len)
|
||||
{
|
||||
udp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_UDPHDR));
|
||||
data_len -= sizeof(WINDIVERT_UDPHDR);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)data;
|
||||
if (ip_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPHDR))
|
||||
{
|
||||
icmp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPHDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPHDR);
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)data;
|
||||
if (ipv6_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPV6HDR))
|
||||
{
|
||||
icmpv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPV6HDR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data_len == 0)
|
||||
{
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
WinDivertHelperParsePacketExit:
|
||||
success = TRUE;
|
||||
if (ppIpHdr != NULL)
|
||||
{
|
||||
*ppIpHdr = ip_header;
|
||||
success = success && (ip_header != NULL);
|
||||
}
|
||||
if (ppIpv6Hdr != NULL)
|
||||
{
|
||||
*ppIpv6Hdr = ipv6_header;
|
||||
success = success && (ipv6_header != NULL);
|
||||
}
|
||||
if (ppIcmpHdr != NULL)
|
||||
{
|
||||
*ppIcmpHdr = icmp_header;
|
||||
success = success && (icmp_header != NULL);
|
||||
}
|
||||
if (ppIcmpv6Hdr != NULL)
|
||||
{
|
||||
*ppIcmpv6Hdr = icmpv6_header;
|
||||
success = success && (icmpv6_header != NULL);
|
||||
}
|
||||
if (ppTcpHdr != NULL)
|
||||
{
|
||||
*ppTcpHdr = tcp_header;
|
||||
success = success && (tcp_header != NULL);
|
||||
}
|
||||
if (ppUdpHdr != NULL)
|
||||
{
|
||||
*ppUdpHdr = udp_header;
|
||||
success = success && (udp_header != NULL);
|
||||
}
|
||||
if (pProto != NULL)
|
||||
{
|
||||
*pProto = trans_proto;
|
||||
}
|
||||
if (ppData != NULL)
|
||||
{
|
||||
*ppData = data;
|
||||
success = success && (data != NULL);
|
||||
}
|
||||
if (pDataLen != NULL)
|
||||
{
|
||||
*pDataLen = data_len;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
const WINDIVERT_ADDRESS *pAddr, UINT64 flags)
|
||||
{
|
||||
UINT8 pseudo_header[
|
||||
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
|
||||
UINT16 pseudo_header_len;
|
||||
PWINDIVERT_IPHDR ip_header;
|
||||
PWINDIVERT_IPV6HDR ipv6_header;
|
||||
PWINDIVERT_ICMPHDR icmp_header;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT payload_len, checksum_len;
|
||||
UINT count = 0;
|
||||
|
||||
WinDivertParsePacket(pPacket, packetLen, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL,
|
||||
&payload_len);
|
||||
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
if (pAddr == NULL || pAddr->PseudoIPChecksum == 0)
|
||||
{
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
ip_header, ip_header->HdrLength*sizeof(UINT32));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
|
||||
IPPROTO_ICMPV6, checksum_len, pseudo_header);
|
||||
icmpv6_header->Checksum = 0;
|
||||
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
|
||||
pseudo_header_len, icmpv6_header, checksum_len);
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
if (pAddr == NULL || pAddr->PseudoTCPChecksum == 0)
|
||||
{
|
||||
// Full TCP checksum
|
||||
checksum_len = payload_len + tcp_header->HdrLength*sizeof(UINT32);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_TCP, checksum_len, pseudo_header);
|
||||
tcp_header->Checksum = 0;
|
||||
tcp_header->Checksum = WinDivertCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
|
||||
}
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo TCP checksum
|
||||
tcp_header->Checksum = 0;
|
||||
}
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
if (pAddr == NULL || pAddr->PseudoUDPChecksum == 0)
|
||||
{
|
||||
// Full UDP checksum
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_UDP, checksum_len, pseudo_header);
|
||||
udp_header->Checksum = 0;
|
||||
udp_header->Checksum = WinDivertCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, udp_header, checksum_len);
|
||||
if (udp_header->Checksum == 0)
|
||||
{
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
}
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo UDP checksum
|
||||
udp_header->Checksum = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the IP/IPv6 pseudo header.
|
||||
*/
|
||||
static UINT16 WinDivertInitPseudoHeader(PWINDIVERT_IPHDR ip_header,
|
||||
PWINDIVERT_IPV6HDR ipv6_header, UINT8 protocol, UINT len,
|
||||
void *pseudo_header)
|
||||
{
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
PWINDIVERT_PSEUDOHDR pseudo_header_v4 =
|
||||
(PWINDIVERT_PSEUDOHDR)pseudo_header;
|
||||
pseudo_header_v4->SrcAddr = ip_header->SrcAddr;
|
||||
pseudo_header_v4->DstAddr = ip_header->DstAddr;
|
||||
pseudo_header_v4->Zero = 0;
|
||||
pseudo_header_v4->Protocol = protocol;
|
||||
pseudo_header_v4->Length = htons((UINT16)len);
|
||||
return sizeof(WINDIVERT_PSEUDOHDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
PWINDIVERT_PSEUDOV6HDR pseudo_header_v6 =
|
||||
(PWINDIVERT_PSEUDOV6HDR)pseudo_header;
|
||||
memcpy(pseudo_header_v6->SrcAddr, ipv6_header->SrcAddr,
|
||||
sizeof(pseudo_header_v6->SrcAddr));
|
||||
memcpy(pseudo_header_v6->DstAddr, ipv6_header->DstAddr,
|
||||
sizeof(pseudo_header_v6->DstAddr));
|
||||
pseudo_header_v6->Length = htonl((UINT32)len);
|
||||
pseudo_header_v6->NextHdr = protocol;
|
||||
pseudo_header_v6->Zero = 0;
|
||||
return sizeof(WINDIVERT_PSEUDOV6HDR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic checksum computation.
|
||||
*/
|
||||
static UINT16 WinDivertCalcChecksum(PVOID pseudo_header,
|
||||
UINT16 pseudo_header_len, PVOID data, UINT len)
|
||||
{
|
||||
register const UINT16 *data16 = (const UINT16 *)pseudo_header;
|
||||
register size_t len16 = pseudo_header_len >> 1;
|
||||
register UINT32 sum = 0;
|
||||
size_t i;
|
||||
|
||||
// Pseudo header:
|
||||
for (i = 0; i < len16; i++)
|
||||
{
|
||||
sum += (UINT32)data16[i];
|
||||
}
|
||||
|
||||
// Main data:
|
||||
data16 = (const UINT16 *)data;
|
||||
len16 = len >> 1;
|
||||
for (i = 0; i < len16; i++)
|
||||
{
|
||||
sum += (UINT32)data16[i];
|
||||
}
|
||||
|
||||
if (len & 0x1)
|
||||
{
|
||||
const UINT8 *data8 = (const UINT8 *)data;
|
||||
sum += (UINT16)data8[len-1];
|
||||
}
|
||||
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
sum += (sum >> 16);
|
||||
sum = ~sum;
|
||||
return (UINT16)sum;
|
||||
}
|
||||
|
||||
+66
-135
@@ -1,18 +1,16 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WinDivert 1.4 Documentation</title>
|
||||
<title>WinDivert 2.0 Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WinDivert 1.4: Windows Packet Divert</h1>
|
||||
<h1>WinDivert 2.0: Windows Packet Divert</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#introduction">1. Introduction</a></li>
|
||||
<li><a href="#building">2. Building</a></li>
|
||||
<ul>
|
||||
<li><a href="#driver_signing">2.1 Driver Signing</a></li>
|
||||
<li><a href="#visual_studio_2012_support">2.2 Visual Studio 2012 Support</a></li>
|
||||
<li><a href="#mingw_support">2.3 MinGW Support</a></li>
|
||||
</ul>
|
||||
<li><a href="#installing">3. Installing</a></li>
|
||||
<li><a href="#uninstalling">4. Uninstalling</a></li>
|
||||
@@ -87,76 +85,63 @@ WinDivert also supports passive packet sniffing similar to <tt>Winpcap</tt>.
|
||||
<hr>
|
||||
<a name="building"><h2>2. Building</h2></a>
|
||||
<p>
|
||||
Note that pre-built WinDivert binary distributions are available from the
|
||||
<a href="https://reqrypt.org/windivert.html">WinDivert website</a>.
|
||||
Most users do not need to build their own version of WinDivert from source.
|
||||
</p>
|
||||
<p>
|
||||
The source code for WinDivert is available for download at
|
||||
<blockquote>
|
||||
<a href="https://github.com/basil00/Divert">
|
||||
https://github.com/basil00/Divert</a>
|
||||
</blockquote>
|
||||
To build the WinDivert package from source:
|
||||
To build the WinDivert drivers from source:
|
||||
<ol>
|
||||
<li> Download and install <a href="http://www.microsoft.com/whdc/devtools/wdk/default.mspx">
|
||||
Windows Driver Kit 7.1.0</a>.</li>
|
||||
<li> Open a <i>Free Build Environment</i> console (or
|
||||
<i>Checked Build Environment</i> for debugging).</li>
|
||||
<li> Open a <i>x86 Free Build Environment</i> console.</li>
|
||||
<li> In the WinDivert package root directory, run the command:
|
||||
<pre>
|
||||
wddk-build.bat
|
||||
</pre>
|
||||
This will build the following files and place them in the
|
||||
<tt>install\WDDK</tt> subdirectory:
|
||||
<ul>
|
||||
<li> <tt>WinDivert.dll</tt>: User-mode library.</li>
|
||||
<li> <tt>WinDivert32.sys</tt> or <tt>WinDivert64.sys</tt>:
|
||||
Kernel-mode WDF/WFP call-out driver.</li>
|
||||
<li> <tt>*.exe</tt>: Sample applications from the <tt>divert\examples</tt>
|
||||
directory.</li>
|
||||
</ul></li>
|
||||
</ol>
|
||||
<i>NOTE:</i> The <tt>WinDivert.dll</tt> and <tt>WinDivert.lib</tt> files
|
||||
are only compatible with programs compiled with the WDDK compiler.
|
||||
See below for Visual Studio 2012 and MinGW support.
|
||||
</p>
|
||||
|
||||
<a name="driver_signing"><h3>2.1 Driver Signing</h3></a>
|
||||
<p>
|
||||
Before the WinDivert package can be used, the
|
||||
<tt>WinDivert32.sys</tt>/<tt>WinDivert64.sys</tt> driver
|
||||
must be digitally signed.
|
||||
See <a href="http://msdn.microsoft.com/en-us/windows/hardware/gg487317.aspx">Driver Signing Requirements for Windows</a>
|
||||
for more information.
|
||||
</p>
|
||||
|
||||
<a name="visual_studio_2012_support"><h3>2.2 Visual Studio 2012 Support</h3></a>
|
||||
<p>
|
||||
To build the WinDivert package for Visual Studio 2012:
|
||||
<ol>
|
||||
<li> First build the driver by running <tt>wddk-build.bat</tt> as per the
|
||||
instructions above.</li>
|
||||
<li> Open a <i>Visual Studio Command Prompt</i> environment.</li>
|
||||
<li> In the WinDivert package root directory, run the command:
|
||||
<pre>
|
||||
msvc-build.bat
|
||||
</pre>
|
||||
This will build Visual Studio 2012 compatible files and place them in the
|
||||
<tt>install\MSVC</tt> subdirectory.</li>
|
||||
This will build the <tt>install\WDDK\i386\WinDivert32.sys</tt> driver.</li>
|
||||
<li> Next, open a <i>x64 Free Build Environment</i> console.</li>
|
||||
<li> Re-run the <tt>wddk-build.bat</tt> command to build the
|
||||
<tt>install\WDDK\amd64\WinDivert64.sys</tt> driver.</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
<a name="mingw_support"><h3>2.3 MinGW Support</h3></a>
|
||||
<p>
|
||||
To build the WinDivert package for MinGW:
|
||||
To build the WinDivert user-mode library (<tt>WinDivert.dll</tt>) and sample
|
||||
programs:
|
||||
<ol>
|
||||
<li> First build the driver by running <tt>wddk-build.bat</tt> as per
|
||||
the instructions above.</li>
|
||||
<li> First, build the WinDivert drivers by running the
|
||||
<tt>wddk-build.bat</tt> command described above.</li>
|
||||
<li> In Linux (with the MinGW cross-compilers installed) and in the
|
||||
WinDivert package root directory, run the command:
|
||||
<pre>
|
||||
sh mingw-build.sh
|
||||
</pre>
|
||||
This will build MinGW compatible files and place them in the
|
||||
<tt>install\MINGW</tt> subdirectory.</li>
|
||||
This will the user-mode library and sample programs which will be placed
|
||||
in the <tt>install\MINGW</tt> subdirectory.</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>
|
||||
The generated <tt>WinDivert.dll</tt>/<tt>WinDivert.lib</tt> files
|
||||
should be compatible with all major compilers, including both MinGW and
|
||||
Visual Studio.
|
||||
</p>
|
||||
|
||||
<a name="driver_signing"><h3>2.1 Driver Signing</h3></a>
|
||||
<p>
|
||||
If you built your own
|
||||
<tt>WinDivert32.sys</tt>/<tt>WinDivert64.sys</tt> drivers,
|
||||
they must be digitally signed before they can be used.
|
||||
See <a href="http://msdn.microsoft.com/en-us/windows/hardware/gg487317.aspx">Driver Signing Requirements for Windows</a>
|
||||
for more information.
|
||||
</p>
|
||||
<p>
|
||||
Note that the pre-built <tt>WinDivert32.sys</tt>/<tt>WinDivert64.sys</tt>
|
||||
drivers from the official WinDivert distribution are already digitally signed.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
@@ -221,60 +206,6 @@ whenever your application calls
|
||||
<a href="#divert_open"><tt>WinDivertOpen()</tt></a>.
|
||||
The calling application must have Administrator privileges.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>WinDivert.dll</tt> also depends on a C run-time library.
|
||||
This is not distributed with the WinDivert binaries, and must be
|
||||
installed/distributed separately if required.
|
||||
</p>
|
||||
<center>
|
||||
<table border="1" cellpadding="5" width="75%">
|
||||
<tr>
|
||||
<th>
|
||||
Build/Compiler
|
||||
</th>
|
||||
<th>
|
||||
C-Runtime Dependency
|
||||
</th>
|
||||
<th>
|
||||
Installed on Windows by Default?
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
WDDK (Windows Driver Kit 7.1)
|
||||
</td>
|
||||
<td>
|
||||
<tt>MSVCRT.dll</tt>
|
||||
</td>
|
||||
<td>
|
||||
Yes
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
MSVC (Visual Studio 2012)
|
||||
</td>
|
||||
<td>
|
||||
<tt>MSVCRT110.dll</tt>
|
||||
</td>
|
||||
<td>
|
||||
No.
|
||||
Must be installed separately or included with your application.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
MINGW
|
||||
</td>
|
||||
<td>
|
||||
<tt>MSVCRT.dll</tt>
|
||||
</td>
|
||||
<td>
|
||||
Yes
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<hr>
|
||||
<a name="uninstalling"><h2>4. Uninstalling</h2></a>
|
||||
@@ -286,8 +217,8 @@ uninstalled during the next machine reboot.
|
||||
The WinDivert driver can also be manually removed by issuing the following
|
||||
commands at the command prompt
|
||||
<pre>
|
||||
sc stop WinDivert1.4
|
||||
sc delete WinDivert1.4
|
||||
sc stop WinDivert2.0
|
||||
sc delete WinDivert2.0
|
||||
</pre>
|
||||
Note that this is not recommended as it will interfere with other
|
||||
applications that depend on WinDivert.
|
||||
@@ -392,18 +323,11 @@ For more information, see <a href="#divert_send"><tt>WinDivertSend()</tt></a>.
|
||||
</p><p>
|
||||
The <tt>Pseudo*Checksum</tt> flags indicate whether the packet uses
|
||||
<i>full</i> or <i>pseudo</i> checksums.
|
||||
Pseudo checksums will typically be used if the network adapter supports
|
||||
<i>IP/TCP/UDP checksum offloading</i>, which means that the network
|
||||
Pseudo checksums are used when
|
||||
<i>IP/TCP/UDP checksum offloading</i> is enabled, meaning that the network
|
||||
hardware calculates/validates checksums rather than the Windows TCP/IP stack.
|
||||
For outbound IPv4, the pseudo checksum is always <tt>0</tt>, and for
|
||||
TCP/UDP the pseudo checksum is the ones compliment sum over the
|
||||
corresponding TCP/UDP checksum <i>pseudo header</i>.
|
||||
For inbound packets, the pseudo checksums may be arbitrary values.
|
||||
Pseudo checksums are generally cheaper to calculate, but will only work
|
||||
if the underlying network hardware supports it.
|
||||
Typically modified packets should preserve these flags, and newly
|
||||
crafted packets should clear these flags unless the application manually
|
||||
verifies checksum offloading is enabled.
|
||||
Pseudo checksums may be arbitrary values.
|
||||
Typically, modified packets should preserve the <tt>Pseudo*Checksum</tt> flags.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -876,6 +800,13 @@ Note that packets returned by
|
||||
<a href="#divert_recv"><tt>WinDivertRecv()</tt></a> are
|
||||
guaranteed to have correct checksums.
|
||||
</p>
|
||||
<p>
|
||||
When pseudo checksums are used,
|
||||
the <a href="#divert_send"><tt>WinDivertSend()</tt></a> function may
|
||||
modify the contents of the memory pointed to by the <tt>pPacket</tt> and
|
||||
<tt>pAddr</tt> parameters.
|
||||
Thus, it is important that this memory is not read-only.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
<a name="divert_send_ex"><h3>5.6 WinDivertSendEx</h3></a>
|
||||
@@ -1329,8 +1260,8 @@ Use <tt>GetLastError()</tt> to get the reason for the error.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
Parses an IPv4 address stored in <tt>addrStr</tt>.
|
||||
If non-<tt>NULL</tt>, the result is stored in <tt>pAddr</tt>
|
||||
in host-byte-order.
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, the is be stored in
|
||||
host-byte-order.
|
||||
Use <tt>htonl()</tt> to convert the result into network-byte-order.
|
||||
</p>
|
||||
<dd></dl>
|
||||
@@ -1358,21 +1289,22 @@ Use <tt>GetLastError()</tt> to get the reason for the error.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
Parses an IPv6 address stored in <tt>addrStr</tt>.
|
||||
If non-<tt>NULL</tt>, the result is stored in <tt>pAddr</tt>.
|
||||
The <tt>pAddr</tt> parameter is assumed to point to a buffer large enough
|
||||
to hold a 16-byte IPv6 address.
|
||||
Given an IPv6 address of the form
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, the buffer assumed
|
||||
to be large enough to hold a 16-byte IPv6 address.
|
||||
The result is stored in host-byte-order.
|
||||
For example, given an IPv6 address of the form
|
||||
<tt>0011:2233:4455:6677:8899:aabb:ccdd:eeff</tt>, then
|
||||
the result is ordered as follows:
|
||||
<pre>
|
||||
pAddr[0] = 0x00112233
|
||||
pAddr[1] = 0x44556677
|
||||
pAddr[2] = 0x8899aabb
|
||||
pAddr[3] = 0xccddeeff
|
||||
pAddr[0] = 0xccddeeff
|
||||
pAddr[1] = 0x8899aabb
|
||||
pAddr[2] = 0x44556677
|
||||
pAddr[3] = 0x00112233
|
||||
</pre>
|
||||
where each <tt>pAddr[i]</tt> is in host-byte-order.
|
||||
The result can be converted into network-byte-order by setting
|
||||
<tt>pAddr[i] = htonl(pAddr[i])</tt> for each <tt>i</tt>.
|
||||
<tt>pAddr[i] = htonl(pAddr[i])</tt> for each <tt>i</tt> and
|
||||
swapping the array indexes.
|
||||
</p>
|
||||
<dd></dl>
|
||||
|
||||
@@ -1426,14 +1358,13 @@ This may be inefficient for some applications.
|
||||
For better performance, incremental checksum calculations should be used
|
||||
instead (not provided by this API).
|
||||
</p><p>
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, this function will calculate checksums
|
||||
based on the <tt>Pseudo*Checksum</tt> flags in the
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, this function will avoid calculating
|
||||
the full checksum if the <tt>Pseudo*Checksum</tt> flag is
|
||||
set in the corresponding
|
||||
<a href="#divert_address"><tt>WINDIVERT_ADDRESS</tt></a> structure.
|
||||
This involves calculating pseudo checksums instead of full checksums if
|
||||
the corresponding address flag is set.
|
||||
The address structure should be the same as
|
||||
the one passed to <a href="#divert_send"><tt>WinDivertSend()</tt></a> to
|
||||
inject the packet.
|
||||
the one passed to <a href="#divert_send"><tt>WinDivertSend()</tt></a> in
|
||||
order to (re)inject the packet.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
DIRS= \
|
||||
netdump \
|
||||
netfilter \
|
||||
passthru \
|
||||
webfilter \
|
||||
streamdump
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* flowtrack.c
|
||||
* (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* usage: flowtrack.exe [filter]
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAX_FLOWS 256
|
||||
#define INET6_ADDRSTRLEN 45
|
||||
|
||||
/*
|
||||
* Flow tracking.
|
||||
*/
|
||||
typedef struct FLOW
|
||||
{
|
||||
WINDIVERT_ADDRESS addr;
|
||||
struct FLOW *next;
|
||||
} FLOW, *PFLOW;
|
||||
|
||||
static HANDLE lock;
|
||||
static PFLOW flows = NULL;
|
||||
|
||||
/*
|
||||
* Draw flows to console in a delayed loop.
|
||||
*
|
||||
* This function does minimal error checking.
|
||||
*/
|
||||
static DWORD draw(LPVOID arg)
|
||||
{
|
||||
const COORD top_left = {0, 0};
|
||||
HANDLE process, console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO screen;
|
||||
char path[MAX_PATH+1];
|
||||
char addr_str[INET6_ADDRSTRLEN+1];
|
||||
char *filename;
|
||||
const char header[] = "PID PROGRAM PROT FLOW";
|
||||
DWORD rows, columns, written, fill_len, path_len, i;
|
||||
PFLOW flow;
|
||||
WINDIVERT_ADDRESS addrs[MAX_FLOWS], *addr;
|
||||
UINT num_addrs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GetConsoleScreenBufferInfo(console, &screen);
|
||||
SetConsoleCursorPosition(console, top_left);
|
||||
|
||||
rows = screen.srWindow.Bottom - screen.srWindow.Top + 1;
|
||||
columns = screen.srWindow.Right - screen.srWindow.Left + 1;
|
||||
|
||||
// Copy a snapshot of the current flows:
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow = flows;
|
||||
num_addrs = 0;
|
||||
for (i = 0; flow != NULL && i < rows && i < MAX_FLOWS; i++)
|
||||
{
|
||||
memcpy(&addrs[i], &flow->addr, sizeof(addrs[i]));
|
||||
num_addrs++;
|
||||
flow = flow->next;
|
||||
}
|
||||
ReleaseMutex(lock);
|
||||
|
||||
// Print the flows:
|
||||
SetConsoleTextAttribute(console, BACKGROUND_RED | BACKGROUND_GREEN |
|
||||
BACKGROUND_BLUE);
|
||||
WriteConsole(console, header, sizeof(header)-1, &written, NULL);
|
||||
fill_len = columns - (sizeof(header)-1);
|
||||
if (fill_len > 0)
|
||||
{
|
||||
COORD pos = {sizeof(header)-1, 0};
|
||||
FillConsoleOutputCharacterA(console, ' ', fill_len, pos,
|
||||
&written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
|
||||
fill_len, pos, &written);
|
||||
}
|
||||
putchar('\n');
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
for (i = 0; i < num_addrs && i < rows-1; i++)
|
||||
{
|
||||
COORD pos = {0, i+1};
|
||||
addr = &addrs[i];
|
||||
FillConsoleOutputCharacterA(console, ' ', columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
SetConsoleCursorPosition(console, pos);
|
||||
if (i == rows-2 && (i+1) < num_addrs)
|
||||
{
|
||||
fputs("...", stdout);
|
||||
fflush(stdout);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%-10d ", addr->Flow.ProcessId);
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
|
||||
addr->Flow.ProcessId);
|
||||
path_len = 0;
|
||||
if (process != NULL)
|
||||
{
|
||||
path_len = GetProcessImageFileName(process, path, sizeof(path));
|
||||
CloseHandle(process);
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
if (path_len != 0)
|
||||
{
|
||||
filename = PathFindFileName(path);
|
||||
printf("%-20.20s ", filename);
|
||||
}
|
||||
else if (addr->Flow.ProcessId == 4)
|
||||
{
|
||||
fputs("Windows ", stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs("??? ", stdout);
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
switch (addr->Flow.Protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("TCP ");
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("UDP ");
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("ICMP ");
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("ICMPV6 ");
|
||||
break;
|
||||
default:
|
||||
printf("%-6u ", addr->Flow.Protocol);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
WinDivertHelperFormatIPv6Address(addr->Flow.LocalAddr, addr_str,
|
||||
sizeof(addr_str));
|
||||
printf("%s:%u %s ", addr_str, addr->Flow.LocalPort,
|
||||
(addr->Outbound? "---->": "<----"));
|
||||
WinDivertHelperFormatIPv6Address(addr->Flow.RemoteAddr, addr_str,
|
||||
sizeof(addr_str));
|
||||
printf("%s:%u", addr_str, addr->Flow.RemotePort);
|
||||
fflush(stdout);
|
||||
}
|
||||
for (; i < rows-1; i++)
|
||||
{
|
||||
COORD pos = {0, i+1};
|
||||
FillConsoleOutputCharacterA(console, ' ', columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
*/
|
||||
int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle, thread;
|
||||
INT16 priority = 776; // Arbitrary.
|
||||
const char *filter = "true", *err_str;
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
PFLOW flow, prev;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
filter = argv[1];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [filter]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Open WinDivert FLOW handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_FLOW, priority,
|
||||
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_FLOW,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Spawn the draw() thread.
|
||||
lock = CreateMutex(NULL, FALSE, NULL);
|
||||
thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)draw, NULL, 0,
|
||||
NULL);
|
||||
if (thread == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to create thread (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
CloseHandle(thread);
|
||||
|
||||
// Main loop:
|
||||
while (TRUE)
|
||||
{
|
||||
if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_FLOW_ESTABLISHED:
|
||||
|
||||
// Flow established:
|
||||
flow = (PFLOW)malloc(sizeof(FLOW));
|
||||
if (flow == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to allocate memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memcpy(&flow->addr, &addr, sizeof(flow->addr));
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow->next = flows;
|
||||
flows = flow;
|
||||
ReleaseMutex(lock);
|
||||
break;
|
||||
|
||||
case WINDIVERT_EVENT_FLOW_DELETED:
|
||||
|
||||
// Flow deleted:
|
||||
prev = NULL;
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow = flows;
|
||||
while (flow != NULL)
|
||||
{
|
||||
if (memcmp(&addr.Flow, &flow->addr.Flow,
|
||||
sizeof(addr.Flow)) == 0)
|
||||
{
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = flow->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
flows = flow->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = flow;
|
||||
flow = flow->next;
|
||||
}
|
||||
ReleaseMutex(lock);
|
||||
free(flow);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
+30
-32
@@ -41,7 +41,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -49,7 +48,11 @@
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define ntohs(x) WinDivertHelperNtohs(x)
|
||||
#define ntohl(x) WinDivertHelperNtohl(x)
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define INET6_ADDRSTRLEN 45
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
@@ -68,6 +71,9 @@ int __cdecl main(int argc, char **argv)
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT32 src_addr[4], dst_addr[4];
|
||||
UINT64 hash;
|
||||
char src_str[INET6_ADDRSTRLEN+1], dst_str[INET6_ADDRSTRLEN+1];
|
||||
const char *err_str;
|
||||
LARGE_INTEGER base, freq;
|
||||
double time_passed;
|
||||
@@ -100,8 +106,8 @@ int __cdecl main(int argc, char **argv)
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCheckFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
&err_str, NULL))
|
||||
!WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -154,57 +160,49 @@ int __cdecl main(int argc, char **argv)
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
time_passed = (double)(addr.Timestamp - base.QuadPart) /
|
||||
(double)freq.QuadPart;
|
||||
hash = WinDivertHelperHashPacket(packet, packet_len, 0);
|
||||
printf("Packet [Timestamp=%.8g, Direction=%s IfIdx=%u SubIfIdx=%u "
|
||||
"Loopback=%u]\n",
|
||||
time_passed, (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND?
|
||||
"outbound": "inbound"), addr.IfIdx, addr.SubIfIdx,
|
||||
addr.Loopback);
|
||||
"Loopback=%u Hash=0x%.16llX]\n",
|
||||
time_passed, (addr.Outbound? "outbound": "inbound"),
|
||||
addr.Network.IfIdx, addr.Network.SubIfIdx, addr.Loopback, hash);
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr;
|
||||
UINT8 *dst_addr = (UINT8 *)&ip_header->DstAddr;
|
||||
WinDivertHelperFormatIPv4Address(ntohl(ip_header->SrcAddr),
|
||||
src_str, sizeof(src_str));
|
||||
WinDivertHelperFormatIPv4Address(ntohl(ip_header->DstAddr),
|
||||
dst_str, sizeof(dst_str));
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
printf("IPv4 [Version=%u HdrLength=%u TOS=%u Length=%u Id=0x%.4X "
|
||||
"Reserved=%u DF=%u MF=%u FragOff=%u TTL=%u Protocol=%u "
|
||||
"Checksum=0x%.4X SrcAddr=%u.%u.%u.%u DstAddr=%u.%u.%u.%u]\n",
|
||||
"Checksum=0x%.4X SrcAddr=%s DstAddr=%s]\n",
|
||||
ip_header->Version, ip_header->HdrLength,
|
||||
ntohs(ip_header->TOS), ntohs(ip_header->Length),
|
||||
ntohs(ip_header->Id), WINDIVERT_IPHDR_GET_RESERVED(ip_header),
|
||||
WINDIVERT_IPHDR_GET_DF(ip_header),
|
||||
WINDIVERT_IPHDR_GET_MF(ip_header),
|
||||
ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header)), ip_header->TTL,
|
||||
ip_header->Protocol, ntohs(ip_header->Checksum),
|
||||
src_addr[0], src_addr[1], src_addr[2], src_addr[3],
|
||||
dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3]);
|
||||
ip_header->Protocol, ntohs(ip_header->Checksum), src_str,
|
||||
dst_str);
|
||||
|
||||
}
|
||||
if (ipv6_header != NULL)
|
||||
{
|
||||
UINT16 *src_addr = (UINT16 *)&ipv6_header->SrcAddr;
|
||||
UINT16 *dst_addr = (UINT16 *)&ipv6_header->DstAddr;
|
||||
WinDivertHelperNtohIpv6Address(ipv6_header->SrcAddr, src_addr);
|
||||
WinDivertHelperNtohIpv6Address(ipv6_header->DstAddr, dst_addr);
|
||||
WinDivertHelperFormatIPv6Address(src_addr, src_str,
|
||||
sizeof(src_str));
|
||||
WinDivertHelperFormatIPv6Address(dst_addr, dst_str,
|
||||
sizeof(dst_str));
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
printf("IPv6 [Version=%u TrafficClass=%u FlowLabel=%u Length=%u "
|
||||
"NextHdr=%u HopLimit=%u SrcAddr=",
|
||||
"NextHdr=%u HopLimit=%u SrcAddr=%s DstAddr=%s]\n",
|
||||
ipv6_header->Version,
|
||||
WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(ipv6_header),
|
||||
ntohl(WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6_header)),
|
||||
ntohs(ipv6_header->Length), ipv6_header->NextHdr,
|
||||
ipv6_header->HopLimit);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
printf("%x%c", ntohs(src_addr[i]), (i == 7? ' ': ':'));
|
||||
}
|
||||
fputs("DstAddr=", stdout);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
printf("%x", ntohs(dst_addr[i]));
|
||||
if (i != 7)
|
||||
{
|
||||
putchar(':');
|
||||
}
|
||||
}
|
||||
fputs("]\n", stdout);
|
||||
ipv6_header->HopLimit, src_str, dst_str);
|
||||
}
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TARGETNAME>netdump</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;..\..\install\MSVC\WinDivert.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="netdump.c"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
!IF "$(_BUILDARCH)" == "x86"
|
||||
CPU=i386
|
||||
!ELSE
|
||||
CPU=$(_BUILDARCH)
|
||||
!ENDIF
|
||||
|
||||
TARGETNAME=netdump
|
||||
TARGETTYPE=PROGRAM
|
||||
TARGETPATH=..\..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib \
|
||||
$(TARGETPATH)\$(CPU)\WinDivert.lib
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\..\include
|
||||
SOURCES=netdump.c
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
@@ -47,7 +47,6 @@
|
||||
* This program is similar to Linux's iptables with the "-j REJECT" target.
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -55,7 +54,14 @@
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define ntohs(x) WinDivertHelperNtohs(x)
|
||||
#define ntohl(x) WinDivertHelperNtohl(x)
|
||||
#define htons(x) WinDivertHelperHtons(x)
|
||||
#define htonl(x) WinDivertHelperHtonl(x)
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define INET6_ADDRSTRLEN 45
|
||||
#define IPPROTO_ICMPV6 58
|
||||
|
||||
/*
|
||||
* Pre-fabricated packets.
|
||||
@@ -113,6 +119,8 @@ int __cdecl main(int argc, char **argv)
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT32 src_addr[4], dst_addr[4];
|
||||
char src_str[INET6_ADDRSTRLEN+1], dst_str[INET6_ADDRSTRLEN+1];
|
||||
UINT payload_len;
|
||||
const char *err_str;
|
||||
|
||||
@@ -170,8 +178,8 @@ int __cdecl main(int argc, char **argv)
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCheckFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
&err_str, NULL))
|
||||
!WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -208,28 +216,21 @@ int __cdecl main(int argc, char **argv)
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr;
|
||||
UINT8 *dst_addr = (UINT8 *)&ip_header->DstAddr;
|
||||
printf("ip.SrcAddr=%u.%u.%u.%u ip.DstAddr=%u.%u.%u.%u ",
|
||||
src_addr[0], src_addr[1], src_addr[2], src_addr[3],
|
||||
dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3]);
|
||||
WinDivertHelperFormatIPv4Address(ntohl(ip_header->SrcAddr),
|
||||
src_str, sizeof(src_str));
|
||||
WinDivertHelperFormatIPv4Address(ntohl(ip_header->DstAddr),
|
||||
dst_str, sizeof(dst_str));
|
||||
}
|
||||
if (ipv6_header != NULL)
|
||||
{
|
||||
UINT16 *src_addr = (UINT16 *)&ipv6_header->SrcAddr;
|
||||
UINT16 *dst_addr = (UINT16 *)&ipv6_header->DstAddr;
|
||||
fputs("ipv6.SrcAddr=", stdout);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
printf("%x%c", ntohs(src_addr[i]), (i == 7? ' ': ':'));
|
||||
}
|
||||
fputs(" ipv6.DstAddr=", stdout);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
printf("%x%c", ntohs(dst_addr[i]), (i == 7? ' ': ':'));
|
||||
}
|
||||
putchar(' ');
|
||||
WinDivertHelperNtohIpv6Address(ipv6_header->SrcAddr, src_addr);
|
||||
WinDivertHelperNtohIpv6Address(ipv6_header->DstAddr, dst_addr);
|
||||
WinDivertHelperFormatIPv6Address(src_addr, src_str,
|
||||
sizeof(src_str));
|
||||
WinDivertHelperFormatIPv6Address(dst_addr, dst_str,
|
||||
sizeof(dst_str));
|
||||
}
|
||||
printf("ip.SrcAddr=%s ip.DstAddr=%s ", src_str, dst_str);
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
printf("icmp.Type=%u icmp.Code=%u ",
|
||||
@@ -287,7 +288,7 @@ int __cdecl main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET),
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)reset, sizeof(TCPPACKET),
|
||||
@@ -314,7 +315,7 @@ int __cdecl main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)resetv6,
|
||||
sizeof(TCPV6PACKET), &send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET),
|
||||
@@ -340,7 +341,7 @@ int __cdecl main(int argc, char **argv)
|
||||
dnr->ip.DstAddr = ip_header->SrcAddr;
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)dnr, icmp_length,
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, &send_addr,
|
||||
@@ -363,7 +364,7 @@ int __cdecl main(int argc, char **argv)
|
||||
sizeof(dnrv6->ipv6.DstAddr));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length,
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)dnrv6, icmpv6_length,
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TARGETNAME>netfilter</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;..\..\install\MSVC\WinDivert.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="netfilter.c"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
!IF "$(_BUILDARCH)" == "x86"
|
||||
CPU=i386
|
||||
!ELSE
|
||||
CPU=$(_BUILDARCH)
|
||||
!ENDIF
|
||||
|
||||
TARGETNAME=netfilter
|
||||
TARGETTYPE=PROGRAM
|
||||
TARGETPATH=..\..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib \
|
||||
$(TARGETPATH)\$(CPU)\WinDivert.lib
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\..\include
|
||||
SOURCES=netfilter.c
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
@@ -47,7 +47,10 @@
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define MAXBUF 400000
|
||||
#define MAXBATCH 0xFF
|
||||
|
||||
static int batch = 1;
|
||||
|
||||
static DWORD passthru(LPVOID arg);
|
||||
|
||||
@@ -59,9 +62,10 @@ int __cdecl main(int argc, char **argv)
|
||||
int num_threads, priority = 0, i;
|
||||
HANDLE handle, thread;
|
||||
|
||||
if (argc != 3 && argc != 4)
|
||||
if (argc < 3 || argc > 5)
|
||||
{
|
||||
fprintf(stderr, "usage: %s filter num-threads [priority]\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s filter num-threads [batch] [priority]\n",
|
||||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
num_threads = atoi(argv[2]);
|
||||
@@ -70,9 +74,18 @@ int __cdecl main(int argc, char **argv)
|
||||
fprintf(stderr, "error: invalid number of threads\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (argc == 4)
|
||||
if (argc >= 4)
|
||||
{
|
||||
priority = atoi(argv[3]);
|
||||
batch = atoi(argv[3]);
|
||||
}
|
||||
if (batch <= 0 || batch > MAXBATCH)
|
||||
{
|
||||
fprintf(stderr, "error: invalid batch size\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (argc >= 5)
|
||||
{
|
||||
priority = atoi(argv[4]);
|
||||
}
|
||||
|
||||
// Divert traffic matching the filter:
|
||||
@@ -112,16 +125,18 @@ int __cdecl main(int argc, char **argv)
|
||||
// Passthru thread.
|
||||
static DWORD passthru(LPVOID arg)
|
||||
{
|
||||
unsigned char packet[MAXBUF];
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
UINT8 packet[MAXBUF];
|
||||
UINT packet_len, addr_len;
|
||||
WINDIVERT_ADDRESS addr[MAXBATCH];
|
||||
HANDLE handle = (HANDLE)arg;
|
||||
|
||||
// Main loop:
|
||||
while (TRUE)
|
||||
{
|
||||
// Read a matching packet.
|
||||
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), &packet_len, 0,
|
||||
addr, &addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet (%d)\n",
|
||||
GetLastError());
|
||||
@@ -129,7 +144,8 @@ static DWORD passthru(LPVOID arg)
|
||||
}
|
||||
|
||||
// Re-inject the matching packet.
|
||||
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
|
||||
addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
GetLastError());
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TARGETNAME>passthru</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;..\..\install\MSVC\WinDivert.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="passthru.c"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
!IF "$(_BUILDARCH)" == "x86"
|
||||
CPU=i386
|
||||
!ELSE
|
||||
CPU=$(_BUILDARCH)
|
||||
!ENDIF
|
||||
|
||||
TARGETNAME=passthru
|
||||
TARGETTYPE=PROGRAM
|
||||
TARGETPATH=..\..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib \
|
||||
$(TARGETPATH)\$(CPU)\WinDivert.lib
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\..\include
|
||||
SOURCES=passthru.c
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* socketdump.c
|
||||
* (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* usage: socketdump.exe [filter]
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define INET6_ADDRSTRLEN 45
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
*/
|
||||
int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle, process, console;
|
||||
INT16 priority = 1121; // Arbitrary.
|
||||
const char *filter = "true", *err_str;
|
||||
char path[MAX_PATH+1];
|
||||
char local_str[INET6_ADDRSTRLEN+1], remote_str[INET6_ADDRSTRLEN+1];
|
||||
char *filename;
|
||||
DWORD path_len;
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
filter = argv[1];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [filter]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Open WinDivert SOCKET handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_SOCKET, priority,
|
||||
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_SOCKET,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Main loop:
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
while (TRUE)
|
||||
{
|
||||
if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_SOCKET_BIND:
|
||||
printf("BIND");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_LISTEN:
|
||||
printf("LISTEN");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_CONNECT:
|
||||
printf("CONNECT");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_ACCEPT:
|
||||
printf("ACCEPT");
|
||||
break;
|
||||
default:
|
||||
printf("???");
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
|
||||
printf(" pid=");
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%u", addr.Socket.ProcessId);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
|
||||
printf(" program=");
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
|
||||
addr.Socket.ProcessId);
|
||||
path_len = 0;
|
||||
if (process != NULL)
|
||||
{
|
||||
path_len = GetProcessImageFileName(process, path, sizeof(path));
|
||||
CloseHandle(process);
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
if (path_len != 0)
|
||||
{
|
||||
filename = PathFindFileName(path);
|
||||
printf("%s", filename);
|
||||
}
|
||||
else if (addr.Socket.ProcessId == 4)
|
||||
{
|
||||
printf("Windows");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("???");
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
|
||||
printf(" protocol=");
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
switch (addr.Socket.Protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
printf("TCP");
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
printf("UDP");
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
printf("ICMP");
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
printf("ICMPV6");
|
||||
break;
|
||||
default:
|
||||
printf("%u", addr.Socket.Protocol);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
|
||||
WinDivertHelperFormatIPv6Address(addr.Socket.LocalAddr, local_str,
|
||||
sizeof(local_str));
|
||||
if (addr.Socket.LocalPort != 0 || strcmp(local_str, "::") != 0)
|
||||
{
|
||||
printf(" local=");
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("[%s]:%u", local_str, addr.Socket.LocalPort);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
}
|
||||
|
||||
WinDivertHelperFormatIPv6Address(addr.Socket.RemoteAddr, remote_str,
|
||||
sizeof(remote_str));
|
||||
if (addr.Socket.RemotePort != 0 || strcmp(remote_str, "::") != 0)
|
||||
{
|
||||
printf(" remote=");
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("[%s]:%u", remote_str, addr.Socket.RemotePort);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
!IF "$(_BUILDARCH)" == "x86"
|
||||
CPU=i386
|
||||
!ELSE
|
||||
CPU=$(_BUILDARCH)
|
||||
!ENDIF
|
||||
|
||||
TARGETNAME=streamdump
|
||||
TARGETTYPE=PROGRAM
|
||||
TARGETPATH=..\..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib \
|
||||
$(TARGETPATH)\$(CPU)\WinDivert.lib
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\..\include
|
||||
SOURCES=streamdump.c
|
||||
|
||||
@@ -186,7 +186,7 @@ int __cdecl main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// Divert all traffic to/from `port', `proxy_port' and `alt_port'.
|
||||
r = sprintf_s(filter, sizeof(filter),
|
||||
r = snprintf(filter, sizeof(filter),
|
||||
"tcp and "
|
||||
"(tcp.DstPort == %d or tcp.DstPort == %d or tcp.DstPort == %d or "
|
||||
"tcp.SrcPort == %d or tcp.SrcPort == %d or tcp.SrcPort == %d)",
|
||||
@@ -227,8 +227,8 @@ int __cdecl main(int argc, char **argv)
|
||||
memset(&overlapped, 0, sizeof(overlapped));
|
||||
ResetEvent(event);
|
||||
overlapped.hEvent = event;
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), 0, &addr,
|
||||
&packet_len, &overlapped))
|
||||
if (!WinDivertRecvEx(handle, packet, sizeof(packet), &packet_len, 0,
|
||||
&addr, NULL, &overlapped))
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
@@ -257,41 +257,39 @@ read_failed:
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Direction)
|
||||
if (addr.Outbound)
|
||||
{
|
||||
case WINDIVERT_DIRECTION_OUTBOUND:
|
||||
if (tcp_header->DstPort == htons(port))
|
||||
{
|
||||
// Reflect: PORT ---> PROXY
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->DstPort = htons(proxy_port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Direction = WINDIVERT_DIRECTION_INBOUND;
|
||||
}
|
||||
else if (tcp_header->SrcPort == htons(proxy_port))
|
||||
{
|
||||
// Reflect: PROXY ---> PORT
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->SrcPort = htons(port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Direction = WINDIVERT_DIRECTION_INBOUND;
|
||||
}
|
||||
else if (tcp_header->DstPort == htons(alt_port))
|
||||
{
|
||||
// Redirect: ALT ---> PORT
|
||||
tcp_header->DstPort = htons(port);
|
||||
}
|
||||
break;
|
||||
|
||||
case WINDIVERT_DIRECTION_INBOUND:
|
||||
if (tcp_header->SrcPort == htons(port))
|
||||
{
|
||||
// Redirect: PORT ---> ALT
|
||||
tcp_header->SrcPort = htons(alt_port);
|
||||
}
|
||||
break;
|
||||
if (tcp_header->DstPort == htons(port))
|
||||
{
|
||||
// Reflect: PORT ---> PROXY
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->DstPort = htons(proxy_port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Outbound = FALSE;
|
||||
}
|
||||
else if (tcp_header->SrcPort == htons(proxy_port))
|
||||
{
|
||||
// Reflect: PROXY ---> PORT
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->SrcPort = htons(port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Outbound = FALSE;
|
||||
}
|
||||
else if (tcp_header->DstPort == htons(alt_port))
|
||||
{
|
||||
// Redirect: ALT ---> PORT
|
||||
tcp_header->DstPort = htons(port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tcp_header->SrcPort == htons(port))
|
||||
{
|
||||
// Redirect: PORT ---> ALT
|
||||
tcp_header->SrcPort = htons(alt_port);
|
||||
}
|
||||
}
|
||||
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, &addr, 0);
|
||||
@@ -301,8 +299,8 @@ read_failed:
|
||||
error("failed to allocate memory");
|
||||
}
|
||||
memset(poverlapped, 0, sizeof(OVERLAPPED));
|
||||
if (WinDivertSendEx(handle, packet, packet_len, 0, &addr, NULL,
|
||||
poverlapped))
|
||||
if (WinDivertSendEx(handle, packet, packet_len, NULL, 0, &addr,
|
||||
sizeof(WINDIVERT_ADDRESS), poverlapped))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TARGETNAME>streamdump</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;..\..\install\MSVC\WinDivert.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="streamdump.c"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -1 +0,0 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
!IF "$(_BUILDARCH)" == "x86"
|
||||
CPU=i386
|
||||
!ELSE
|
||||
CPU=$(_BUILDARCH)
|
||||
!ENDIF
|
||||
|
||||
TARGETNAME=webfilter
|
||||
TARGETTYPE=PROGRAM
|
||||
TARGETPATH=..\..\install\WDDK
|
||||
TARGETLIBS=\
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib \
|
||||
$(SDK_LIB_PATH)\ws2_32.lib \
|
||||
$(TARGETPATH)\$(CPU)\WinDivert.lib
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
USE_MSVCRT=1
|
||||
INCLUDES=$(DDK_INC_PATH);$(KMDF_INC_PATH)\$(KMDF_VER_PATH);..\..\include
|
||||
SOURCES=webfilter.c
|
||||
|
||||
@@ -42,13 +42,17 @@
|
||||
* blockpage to the browser.
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define ntohs(x) WinDivertHelperNtohs(x)
|
||||
#define ntohl(x) WinDivertHelperNtohl(x)
|
||||
#define htons(x) WinDivertHelperHtons(x)
|
||||
#define htonl(x) WinDivertHelperHtonl(x)
|
||||
|
||||
#define MAXBUF 0xFFFF
|
||||
#define MAXURL 4096
|
||||
|
||||
@@ -238,7 +242,7 @@ int __cdecl main(int argc, char **argv)
|
||||
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
|
||||
blockpage->header.tcp.AckNum =
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len);
|
||||
addr.Direction = !addr.Direction; // Reverse direction.
|
||||
addr.Outbound = !addr.Outbound; // Reverse direction.
|
||||
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, &addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
|
||||
NULL))
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TARGETNAME>webfilter</TARGETNAME>
|
||||
<Configuration>Release</Configuration>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;..\..\install\MSVC\WinDivert.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="webfilter.c"/>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
</Project>
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* windivertctl.c
|
||||
* (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* usage: windivertctl.exe list
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAX_PACKET 0xFFFF
|
||||
#define MAX_FILTER_LEN 30000
|
||||
|
||||
/*
|
||||
* Process info.
|
||||
*/
|
||||
typedef struct INFO
|
||||
{
|
||||
UINT32 process_id;
|
||||
UINT32 ref_count;
|
||||
HANDLE process;
|
||||
struct INFO *next;
|
||||
} INFO, *PINFO;
|
||||
|
||||
static INFO *open = NULL; // All open handles
|
||||
|
||||
/*
|
||||
* Modes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LIST,
|
||||
WATCH,
|
||||
KILLALL
|
||||
} MODE;
|
||||
|
||||
/*
|
||||
* Add a new process.
|
||||
*/
|
||||
static HANDLE add_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open;
|
||||
HANDLE process;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
info->ref_count++;
|
||||
return info->process;
|
||||
}
|
||||
info = info->next;
|
||||
}
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE,
|
||||
FALSE, process_id);
|
||||
info = (INFO *)malloc(sizeof(INFO));
|
||||
if (info == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to allocate memory (%d)\n",
|
||||
GetLastError());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
info->process_id = process_id;
|
||||
info->process = process;
|
||||
info->ref_count = 1;
|
||||
info->next = open;
|
||||
open = info;
|
||||
return process;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a process.
|
||||
*/
|
||||
static HANDLE lookup_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
return info->process;
|
||||
}
|
||||
info = info->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an old process.
|
||||
*/
|
||||
static void remove_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open, prev = NULL;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
info->ref_count--;
|
||||
if (info->ref_count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = info;
|
||||
info = info->next;
|
||||
}
|
||||
|
||||
if (info->process != NULL)
|
||||
{
|
||||
CloseHandle(info->process);
|
||||
}
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = info->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
open = info->next;
|
||||
}
|
||||
free(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
*/
|
||||
int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle, process, console;
|
||||
INT16 priority = -333; // Arbitrary.
|
||||
UINT packet_len;
|
||||
static UINT8 packet[MAX_PACKET];
|
||||
static char path[MAX_PATH+1];
|
||||
static char filter_str[MAX_FILTER_LEN];
|
||||
PVOID object;
|
||||
DWORD path_len;
|
||||
BOOL or;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
ULONGLONG freq, start_count;
|
||||
LARGE_INTEGER li;
|
||||
MODE mode;
|
||||
const char *filter = "true";
|
||||
const char *err_str = NULL;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
{
|
||||
usage:
|
||||
fprintf(stderr, "usage: %s (list|watch|killall) [filter]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (strcmp(argv[1], "list") == 0)
|
||||
{
|
||||
mode = LIST;
|
||||
}
|
||||
else if (strcmp(argv[1], "watch") == 0)
|
||||
{
|
||||
mode = WATCH;
|
||||
}
|
||||
else if (strcmp(argv[1], "killall") == 0)
|
||||
{
|
||||
mode = KILLALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
if (argc == 3)
|
||||
{
|
||||
filter = argv[2];
|
||||
}
|
||||
|
||||
// Time management
|
||||
QueryPerformanceFrequency(&li);
|
||||
freq = li.QuadPart;
|
||||
QueryPerformanceCounter(&li);
|
||||
start_count = li.QuadPart;
|
||||
|
||||
// Open WinDivert REFLECT handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_REFLECT, priority,
|
||||
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY |
|
||||
(mode == WATCH? 0: WINDIVERT_FLAG_NO_INSTALL));
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (mode != WATCH && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
|
||||
{
|
||||
// WinDivert driver is not running, so no open handles.
|
||||
return 0;
|
||||
}
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_FLOW,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (mode != WATCH && !WinDivertShutdown(handle, WINDIVERT_SHUTDOWN_BOTH))
|
||||
{
|
||||
fprintf(stderr, "error: failed to shutdown WinDivert handle (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Main loop:
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
while (TRUE)
|
||||
{
|
||||
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
{
|
||||
if (mode != WATCH && GetLastError() == ERROR_NO_DATA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "failed to event (%d)\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_REFLECT_OPEN:
|
||||
// Open handle:
|
||||
process = add_process(addr.Reflect.ProcessId);
|
||||
if (mode == KILLALL)
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
fputs("KILL", stdout);
|
||||
TerminateProcess(process, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
fputs("OPEN", stdout);
|
||||
}
|
||||
break;
|
||||
|
||||
case WINDIVERT_EVENT_REFLECT_CLOSE:
|
||||
// Close handle:
|
||||
if (mode != WATCH)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
process = lookup_process(addr.Reflect.ProcessId);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
fputs("CLOSE", stdout);
|
||||
break;
|
||||
|
||||
default:
|
||||
fputs("???", stdout);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" time=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%.3fs", (double)(addr.Reflect.Timestamp - (INT64)start_count) /
|
||||
(double)freq);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" pid=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%u", addr.Reflect.ProcessId);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" exe=", stdout);
|
||||
path_len = 0;
|
||||
if (process != NULL)
|
||||
{
|
||||
path_len = GetProcessImageFileName(process, path, sizeof(path));
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%s", (path_len != 0? path: "???"));
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" layer=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
switch (addr.Reflect.Layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
fputs("NETWORK", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
fputs("NETWORK_FORWARD", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
fputs("FLOW", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_SOCKET:
|
||||
fputs("SOCKET", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
fputs("REFLECT", stdout);
|
||||
break;
|
||||
default:
|
||||
fputs("???", stdout);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" flags=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
if (addr.Reflect.Flags == 0)
|
||||
{
|
||||
fputs("0", stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
or = FALSE;
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_SNIFF) != 0)
|
||||
{
|
||||
fputs("SNIFF", stdout);
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_DROP) != 0)
|
||||
{
|
||||
printf("%sDROP", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_RECV_ONLY) != 0)
|
||||
{
|
||||
printf("%sRECV_ONLY", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_SEND_ONLY) != 0)
|
||||
{
|
||||
printf("%sSEND_ONLY", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_RECV_PARTIAL) != 0)
|
||||
{
|
||||
printf("%sRECV_PARTIAL", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_NO_INSTALL) != 0)
|
||||
{
|
||||
printf("%sNO_INSTALL", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" priority=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%d", addr.Reflect.Priority);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" filter=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, &object, NULL);
|
||||
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
|
||||
filter_str, sizeof(filter_str)))
|
||||
{
|
||||
printf("\"%s\"", filter_str);
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
putchar('\n');
|
||||
|
||||
if (addr.Event == WINDIVERT_EVENT_REFLECT_CLOSE)
|
||||
{
|
||||
remove_process(addr.Reflect.ProcessId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!WinDivertClose(handle))
|
||||
{
|
||||
fprintf(stderr, "error: failed to close WinDivert handle (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+206
-49
@@ -70,52 +70,140 @@ extern "C" {
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Divert address.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Packet's timestamp. */
|
||||
UINT32 IfIdx; /* Packet's interface index. */
|
||||
UINT32 SubIfIdx; /* Packet's sub-interface index. */
|
||||
UINT8 Direction:1; /* Packet's direction. */
|
||||
UINT8 Loopback:1; /* Packet is loopback? */
|
||||
UINT8 Impostor:1; /* Packet is impostor? */
|
||||
UINT8 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
|
||||
UINT8 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
|
||||
UINT8 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
|
||||
UINT8 Reserved:2;
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
|
||||
#define WINDIVERT_DIRECTION_OUTBOUND 0
|
||||
#define WINDIVERT_DIRECTION_INBOUND 1
|
||||
|
||||
/*
|
||||
* Divert layers.
|
||||
* WinDivert layers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 1 /* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
|
||||
WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
|
||||
WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
|
||||
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
|
||||
|
||||
/*
|
||||
* Divert flags.
|
||||
* WinDivert NETWORK and NETWORK_FORWARD layer data.
|
||||
*/
|
||||
#define WINDIVERT_FLAG_SNIFF 1
|
||||
#define WINDIVERT_FLAG_DROP 2
|
||||
#define WINDIVERT_FLAG_DEBUG 4
|
||||
typedef struct
|
||||
{
|
||||
UINT32 IfIdx; /* Packet's interface index. */
|
||||
UINT32 SubIfIdx; /* Packet's sub-interface index. */
|
||||
} WINDIVERT_DATA_NETWORK, *PWINDIVERT_DATA_NETWORK;
|
||||
|
||||
/*
|
||||
* Divert parameters.
|
||||
* WinDivert FLOW layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ProcessId; /* Process ID. */
|
||||
UINT32 LocalAddr[4]; /* Local address. */
|
||||
UINT32 RemoteAddr[4]; /* Remote address. */
|
||||
UINT16 LocalPort; /* Local port. */
|
||||
UINT16 RemotePort; /* Remote port. */
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_DATA_FLOW, *PWINDIVERT_DATA_FLOW;
|
||||
|
||||
/*
|
||||
* WinDivert SOCKET layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ProcessId; /* Process ID. */
|
||||
UINT32 LocalAddr[4]; /* Local address. */
|
||||
UINT32 RemoteAddr[4]; /* Remote address. */
|
||||
UINT16 LocalPort; /* Local port. */
|
||||
UINT16 RemotePort; /* Remote port. */
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_DATA_SOCKET, *PWINDIVERT_DATA_SOCKET;
|
||||
|
||||
/*
|
||||
* WinDivert REFLECTION layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Handle open time. */
|
||||
UINT32 ProcessId; /* Handle process ID. */
|
||||
WINDIVERT_LAYER Layer; /* Handle layer. */
|
||||
UINT64 Flags; /* Handle flags. */
|
||||
INT16 Priority; /* Handle priority. */
|
||||
} WINDIVERT_DATA_REFLECT, *PWINDIVERT_DATA_REFLECT;
|
||||
|
||||
/*
|
||||
* WinDivert address.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Packet's timestamp. */
|
||||
UINT64 Layer:8; /* Packet's layer. */
|
||||
UINT64 Event:8; /* Packet event. */
|
||||
UINT64 Outbound:1; /* Packet is outound? */
|
||||
UINT64 Loopback:1; /* Packet is loopback? */
|
||||
UINT64 Impostor:1; /* Packet is impostor? */
|
||||
UINT64 IPv6:1; /* Packet is IPv6? */
|
||||
UINT64 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
|
||||
UINT64 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
|
||||
UINT64 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
|
||||
UINT64 Reserved:41;
|
||||
union
|
||||
{
|
||||
WINDIVERT_DATA_NETWORK Network; /* Network layer data. */
|
||||
WINDIVERT_DATA_FLOW Flow; /* Flow layer data. */
|
||||
WINDIVERT_DATA_SOCKET Socket; /* Socket layer data. */
|
||||
WINDIVERT_DATA_REFLECT Reflect; /* Reflect layer data. */
|
||||
};
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
|
||||
/*
|
||||
* WinDivert events.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_EVENT_NETWORK_PACKET = 0, /* Network packet. */
|
||||
WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
|
||||
/* Flow established. */
|
||||
WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
|
||||
WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */
|
||||
WINDIVERT_EVENT_SOCKET_LISTEN = 4, /* Socket listen. */
|
||||
WINDIVERT_EVENT_SOCKET_CONNECT = 5, /* Socket connect. */
|
||||
WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */
|
||||
WINDIVERT_EVENT_REFLECT_OPEN = 7, /* WinDivert handle opened. */
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE = 8, /* WinDivert handle closed. */
|
||||
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAG_SNIFF 0x0001
|
||||
#define WINDIVERT_FLAG_DROP 0x0002
|
||||
#define WINDIVERT_FLAG_RECV_ONLY 0x0004
|
||||
#define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY
|
||||
#define WINDIVERT_FLAG_SEND_ONLY 0x0008
|
||||
#define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY
|
||||
#define WINDIVERT_FLAG_RECV_PARTIAL 0x0010
|
||||
#define WINDIVERT_FLAG_NO_INSTALL 0x0020
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_PARAM_QUEUE_LEN = 0, /* Packet queue length. */
|
||||
WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */
|
||||
WINDIVERT_PARAM_QUEUE_SIZE = 2 /* Packet queue size. */
|
||||
WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */
|
||||
} WINDIVERT_PARAM, *PWINDIVERT_PARAM;
|
||||
#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_QUEUE_SIZE
|
||||
|
||||
/*
|
||||
* WinDivert shutdown parameter.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_SHUTDOWN_RECV = 0x1, /* Shutdown recv. */
|
||||
WINDIVERT_SHUTDOWN_SEND = 0x2, /* Shutdown send. */
|
||||
WINDIVERT_SHUTDOWN_BOTH = 0x3, /* Shutdown recv and send. */
|
||||
} WINDIVERT_SHUTDOWN, *PWINDIVERT_SHUTDOWN;
|
||||
#define WINDIVERT_SHUTDOWN_MAX WINDIVERT_SHUTDOWN_BOTH
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
@@ -132,10 +220,10 @@ extern WINDIVERTEXPORT HANDLE WinDivertOpen(
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertRecv(
|
||||
__in HANDLE handle,
|
||||
__out PVOID pPacket,
|
||||
__out VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt PWINDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *readLen);
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr,
|
||||
__out_opt UINT *pReadLen);
|
||||
|
||||
/*
|
||||
* Receive (read) a packet from a WinDivert handle.
|
||||
@@ -144,9 +232,10 @@ extern WINDIVERTEXPORT BOOL WinDivertRecvEx(
|
||||
__in HANDLE handle,
|
||||
__out PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pReadLen,
|
||||
__in UINT64 flags,
|
||||
__out_opt PWINDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *readLen,
|
||||
__out WINDIVERT_ADDRESS *pAddr,
|
||||
__inout_opt UINT *pAddrLen,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped);
|
||||
|
||||
/*
|
||||
@@ -154,23 +243,31 @@ extern WINDIVERTEXPORT BOOL WinDivertRecvEx(
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertSend(
|
||||
__in HANDLE handle,
|
||||
__in PVOID pPacket,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in PWINDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *writeLen);
|
||||
__in const WINDIVERT_ADDRESS *pAddr,
|
||||
__out_opt UINT *pWriteLen);
|
||||
|
||||
/*
|
||||
* Send (write/inject) a packet to a WinDivert handle.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertSendEx(
|
||||
__in HANDLE handle,
|
||||
__in PVOID pPacket,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pWriteLen,
|
||||
__in UINT64 flags,
|
||||
__in PWINDIVERT_ADDRESS pAddr,
|
||||
__out_opt UINT *writeLen,
|
||||
__in const WINDIVERT_ADDRESS *pAddr,
|
||||
__in UINT addrLen,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped);
|
||||
|
||||
/*
|
||||
* Shutdown a WinDivert handle.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertShutdown(
|
||||
__in HANDLE handle,
|
||||
__in WINDIVERT_SHUTDOWN how);
|
||||
|
||||
/*
|
||||
* Close a WinDivert handle.
|
||||
*/
|
||||
@@ -333,8 +430,6 @@ typedef struct
|
||||
UINT16 Checksum;
|
||||
} WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR;
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Flags for WinDivertHelperCalcChecksums()
|
||||
*/
|
||||
@@ -344,11 +439,25 @@ typedef struct
|
||||
#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8
|
||||
#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Hash a packet.
|
||||
*/
|
||||
extern WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in UINT64 seed
|
||||
#ifdef __cplusplus
|
||||
= 0
|
||||
#endif
|
||||
);
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
|
||||
__in PVOID pPacket,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
|
||||
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
@@ -373,21 +482,39 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address(
|
||||
__in const char *addrStr,
|
||||
__out_opt UINT32 *pAddr);
|
||||
|
||||
/*
|
||||
* Format an IPv4 address.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv4Address(
|
||||
__in UINT32 addr,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Format an IPv6 address.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
|
||||
__in const UINT32 *pAddr,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums(
|
||||
__inout PVOID pPacket,
|
||||
__inout VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in_opt PWINDIVERT_ADDRESS pAddr,
|
||||
__in_opt const WINDIVERT_ADDRESS *pAddr,
|
||||
__in UINT64 flags);
|
||||
|
||||
/*
|
||||
* Check the given filter string.
|
||||
* Compile the given filter string.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperCheckFilter(
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperCompileFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out_opt char *object,
|
||||
__in UINT objLen,
|
||||
__out_opt const char **errorStr,
|
||||
__out_opt UINT *errorPos);
|
||||
|
||||
@@ -396,10 +523,40 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperCheckFilter(
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__in PVOID pPacket,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in PWINDIVERT_ADDRESS pAddr);
|
||||
__in const WINDIVERT_ADDRESS *pAddr);
|
||||
|
||||
/*
|
||||
* Format the given filter string.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperFormatFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Byte ordering.
|
||||
*/
|
||||
extern WINDIVERTEXPORT UINT16 WinDivertHelperNtohs(
|
||||
__in UINT16 x);
|
||||
extern WINDIVERTEXPORT UINT16 WinDivertHelperHtons(
|
||||
__in UINT16 x);
|
||||
extern WINDIVERTEXPORT UINT32 WinDivertHelperNtohl(
|
||||
__in UINT32 x);
|
||||
extern WINDIVERTEXPORT UINT32 WinDivertHelperHtonl(
|
||||
__in UINT32 x);
|
||||
extern WINDIVERTEXPORT UINT64 WinDivertHelperNtohll(
|
||||
__in UINT64 x);
|
||||
extern WINDIVERTEXPORT UINT64 WinDivertHelperHtonll(
|
||||
__in UINT64 x);
|
||||
extern WINDIVERTEXPORT void WinDivertHelperNtohIpv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
extern WINDIVERTEXPORT void WinDivertHelperHtonIpv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
|
||||
+95
-37
@@ -44,8 +44,8 @@
|
||||
#define WINDIVERT_KERNEL
|
||||
#include "windivert.h"
|
||||
|
||||
#define WINDIVERT_VERSION 1
|
||||
#define WINDIVERT_VERSION_MINOR 4
|
||||
#define WINDIVERT_VERSION 2
|
||||
#define WINDIVERT_VERSION_MINOR 0
|
||||
|
||||
#define WINDIVERT_STR2(s) #s
|
||||
#define WINDIVERT_STR(s) WINDIVERT_STR2(s)
|
||||
@@ -59,9 +59,6 @@
|
||||
#define WINDIVERT_DEVICE_NAME \
|
||||
L"WinDivert" WINDIVERT_VERSION_LSTR
|
||||
|
||||
#define WINDIVERT_IOCTL_VERSION 6
|
||||
#define WINDIVERT_IOCTL_MAGIC 0xA2BF
|
||||
|
||||
#define WINDIVERT_FILTER_FIELD_ZERO 0
|
||||
#define WINDIVERT_FILTER_FIELD_INBOUND 1
|
||||
#define WINDIVERT_FILTER_FIELD_OUTBOUND 2
|
||||
@@ -122,8 +119,28 @@
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH 57
|
||||
#define WINDIVERT_FILTER_FIELD_LOOPBACK 58
|
||||
#define WINDIVERT_FILTER_FIELD_IMPOSTOR 59
|
||||
#define WINDIVERT_FILTER_FIELD_PROCESSID 60
|
||||
#define WINDIVERT_FILTER_FIELD_LOCALADDR 61
|
||||
#define WINDIVERT_FILTER_FIELD_REMOTEADDR 62
|
||||
#define WINDIVERT_FILTER_FIELD_LOCALPORT 63
|
||||
#define WINDIVERT_FILTER_FIELD_REMOTEPORT 64
|
||||
#define WINDIVERT_FILTER_FIELD_PROTOCOL 65
|
||||
#define WINDIVERT_FILTER_FIELD_LAYER 66
|
||||
#define WINDIVERT_FILTER_FIELD_EVENT 67
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET 68
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET16 69
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET32 70
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 71
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 72
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 73
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 74
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 75
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 76
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM8 77
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM16 78
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM32 79
|
||||
#define WINDIVERT_FILTER_FIELD_MAX \
|
||||
WINDIVERT_FILTER_FIELD_IMPOSTOR
|
||||
WINDIVERT_FILTER_FIELD_RANDOM32
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
@@ -133,7 +150,7 @@
|
||||
#define WINDIVERT_FILTER_TEST_GEQ 5
|
||||
#define WINDIVERT_FILTER_TEST_MAX WINDIVERT_FILTER_TEST_GEQ
|
||||
|
||||
#define WINDIVERT_FILTER_MAXLEN 128
|
||||
#define WINDIVERT_FILTER_MAXLEN (0xFF-2)
|
||||
|
||||
#define WINDIVERT_FILTER_RESULT_ACCEPT (WINDIVERT_FILTER_MAXLEN+1)
|
||||
#define WINDIVERT_FILTER_RESULT_REJECT (WINDIVERT_FILTER_MAXLEN+2)
|
||||
@@ -142,29 +159,60 @@
|
||||
* WinDivert layers.
|
||||
*/
|
||||
#define WINDIVERT_LAYER_DEFAULT WINDIVERT_LAYER_NETWORK
|
||||
#define WINDIVERT_LAYER_MAX \
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD
|
||||
#define WINDIVERT_LAYER_MAX WINDIVERT_LAYER_REFLECT
|
||||
|
||||
/*
|
||||
* WinDivert events.
|
||||
*/
|
||||
#define WINDIVERT_EVENT_MAX \
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAGS_ALL \
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_DEBUG)
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_RECV_PARTIAL | \
|
||||
WINDIVERT_FLAG_NO_INSTALL)
|
||||
#define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \
|
||||
(((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2)))
|
||||
#define WINDIVERT_FLAGS_VALID(flags) \
|
||||
((((flags) & ~WINDIVERT_FLAGS_ALL) == 0) && \
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_SNIFF, \
|
||||
WINDIVERT_FLAG_DROP))
|
||||
WINDIVERT_FLAG_DROP) && \
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_RECV_ONLY, \
|
||||
WINDIVERT_FLAG_SEND_ONLY) && \
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_RECV_PARTIAL, \
|
||||
WINDIVERT_FLAG_SEND_ONLY))
|
||||
|
||||
/*
|
||||
* WinDivert filter flags.
|
||||
*/
|
||||
#define WINDIVERT_FILTER_FLAG_INBOUND 0x0000000000000001ull
|
||||
#define WINDIVERT_FILTER_FLAG_OUTBOUND 0x0000000000000002ull
|
||||
#define WINDIVERT_FILTER_FLAG_IP 0x0000000000000004ull
|
||||
#define WINDIVERT_FILTER_FLAG_IPV6 0x0000000000000008ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_FLOW_DELETED 0x0000000000000010ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND 0x0000000000000020ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT 0x0000000000000040ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN 0x0000000000000080ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT 0x0000000000000100ull
|
||||
|
||||
#define WINDIVERT_FILTER_FLAGS_ALL \
|
||||
(WINDIVERT_FILTER_FLAG_INBOUND | WINDIVERT_FILTER_FLAG_OUTBOUND | \
|
||||
WINDIVERT_FILTER_FLAG_IP | WINDIVERT_FILTER_FLAG_IPV6 | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_FLOW_DELETED | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT)
|
||||
|
||||
/*
|
||||
* WinDivert priorities.
|
||||
*/
|
||||
#define WINDIVERT_PRIORITY(priority16) \
|
||||
((UINT32)((INT32)(priority16) + 0x7FFF + 1))
|
||||
#define WINDIVERT_PRIORITY_DEFAULT WINDIVERT_PRIORITY(0)
|
||||
#define WINDIVERT_PRIORITY_MAX WINDIVERT_PRIORITY(1000)
|
||||
#define WINDIVERT_PRIORITY_MIN WINDIVERT_PRIORITY(-1000)
|
||||
#define WINDIVERT_PRIORITY_DEFAULT 0
|
||||
#define WINDIVERT_PRIORITY_MAX 30000
|
||||
#define WINDIVERT_PRIORITY_MIN -WINDIVERT_PRIORITY_MAX
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
@@ -179,51 +227,61 @@
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 // 32MB
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 // 4MB
|
||||
|
||||
/*
|
||||
* WinDivert batch limits.
|
||||
*/
|
||||
#define WINDIVERT_BATCH_MAX 0xFF
|
||||
|
||||
/*
|
||||
* WinDivert message definitions.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct windivert_ioctl_s
|
||||
typedef struct
|
||||
{
|
||||
UINT16 magic; // WINDIVERT_IOCTL_MAGIC
|
||||
UINT8 version; // WINDIVERT_IOCTL_VERSION
|
||||
UINT8 arg8; // 8-bit argument
|
||||
UINT64 arg; // 64-bit argument
|
||||
};
|
||||
typedef struct windivert_ioctl_s *windivert_ioctl_t;
|
||||
UINT64 arg1; // argument #1
|
||||
UINT64 arg2; // argument #2
|
||||
} WINDIVERT_IOCTL, *PWINDIVERT_IOCTL;
|
||||
|
||||
/*
|
||||
* WinDivert IOCTL structures.
|
||||
*/
|
||||
struct windivert_ioctl_filter_s
|
||||
typedef struct
|
||||
{
|
||||
UINT8 field; // WINDIVERT_FILTER_FIELD_IP_*
|
||||
UINT8 field; // WINDIVERT_FILTER_FIELD_*
|
||||
UINT8 test; // WINDIVERT_FILTER_TEST_*
|
||||
UINT16 success; // Success continuation.
|
||||
UINT16 failure; // Fail continuation.
|
||||
UINT8 success; // Success continuation.
|
||||
UINT8 failure; // Fail continuation.
|
||||
UINT32 arg[4]; // Argument.
|
||||
};
|
||||
typedef struct windivert_ioctl_filter_s *windivert_ioctl_filter_t;
|
||||
} WINDIVERT_FILTER, *PWINDIVERT_FILTER;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
* IOCTL codes.
|
||||
*/
|
||||
#define IOCTL_WINDIVERT_SHUTDOWN \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x917, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_RECV \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x908, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x918, METHOD_OUT_DIRECT, FILE_READ_DATA)
|
||||
#define IOCTL_WINDIVERT_SEND \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x909, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x919, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_START_FILTER \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90A, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91A, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_SET_LAYER \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90B, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91B, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_SET_PRIORITY \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90C, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91C, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_SET_FLAGS \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90D, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91D, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_SET_PARAM \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90E, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91E, METHOD_IN_DIRECT, FILE_READ_DATA | \
|
||||
FILE_WRITE_DATA)
|
||||
#define IOCTL_WINDIVERT_GET_PARAM \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90F, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91F, METHOD_OUT_DIRECT, FILE_READ_DATA)
|
||||
|
||||
#endif /* __WINDIVERT_DEVICE_H */
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
|
||||
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
|
||||
Provider = %Basil%
|
||||
CatalogFile = WinDivert32.Cat
|
||||
DriverVer = 10/22/2017,1.4.0
|
||||
DriverVer = 01/01/2019,2.0.0
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
|
||||
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
|
||||
Provider = %Basil%
|
||||
CatalogFile = WinDivert64.Cat
|
||||
DriverVer = 10/22/2017,1.4.0
|
||||
DriverVer = 01/01/2019,2.0.0
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%
|
||||
|
||||
+25
-8
@@ -54,15 +54,16 @@ do
|
||||
if [ ! -d install/WDDK/$CPU ]
|
||||
then
|
||||
echo "WARNING: missing WDDK build; run wddk-build.bat first"
|
||||
echo "SKIP WDDK-$CPU"
|
||||
echo "SKIP MINGW-$CPU"
|
||||
continue
|
||||
fi
|
||||
echo "BUILD WDDK-$CPU"
|
||||
echo "BUILD MINGW-$CPU"
|
||||
CC="$ENV-gcc"
|
||||
COPTS="-shared -Wall -Wno-pointer-to-int-cast -O2 -Iinclude/
|
||||
COPTS="-fno-ident -shared -Wall -Wno-pointer-to-int-cast -Os -Iinclude/
|
||||
-Wl,--enable-stdcall-fixup -Wl,--entry=${MANGLE}WinDivertDllEntry"
|
||||
CLIBS="-lgcc -lmsvcrt -lkernel32 -ladvapi32"
|
||||
CLIBS="-lgcc -lkernel32 -ladvapi32"
|
||||
STRIP="$ENV-strip"
|
||||
DLLTOOL="$ENV-dlltool"
|
||||
if [ -x "`which $CC`" ]
|
||||
then
|
||||
echo "\tmake install/MINGW/$CPU..."
|
||||
@@ -72,26 +73,42 @@ do
|
||||
$CC $COPTS -o "install/MINGW/$CPU/WinDivert.dll" \
|
||||
dll/windivert.o dll/windivert.def -nostdlib $CLIBS
|
||||
$STRIP "install/MINGW/$CPU/WinDivert.dll"
|
||||
echo "\tbuild install/MINGW/$CPU/WinDivert.lib..."
|
||||
$DLLTOOL --dllname install/MINGW/$CPU/WinDivert.dll \
|
||||
--def dll/windivert.def \
|
||||
--output-lib install/MINGW/$CPU/WinDivert.lib 2>/dev/null
|
||||
echo "\tbuild install/MINGW/$CPU/netdump.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/netdump/netdump.c \
|
||||
-o "install/MINGW/$CPU/netdump.exe" -lWinDivert -lws2_32 \
|
||||
-o "install/MINGW/$CPU/netdump.exe" -lWinDivert \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tbuild install/MINGW/$CPU/netfilter.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/netfilter/netfilter.c \
|
||||
-o "install/MINGW/$CPU/netfilter.exe" -lWinDivert -lws2_32 \
|
||||
-o "install/MINGW/$CPU/netfilter.exe" -lWinDivert \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tbuild install/MINGW/$CPU/passthru.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/passthru/passthru.c \
|
||||
-o "install/MINGW/$CPU/passthru.exe" -lWinDivert -lws2_32 \
|
||||
-o "install/MINGW/$CPU/passthru.exe" -lWinDivert \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tbuild install/MINGW/$CPU/webfilter.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/webfilter/webfilter.c \
|
||||
-o "install/MINGW/$CPU/webfilter.exe" -lWinDivert -lws2_32 \
|
||||
-o "install/MINGW/$CPU/webfilter.exe" -lWinDivert \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tbuild install/MINGW/$CPU/streamdump.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/streamdump/streamdump.c \
|
||||
-o "install/MINGW/$CPU/streamdump.exe" -lWinDivert -lws2_32 \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/flowtrack.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/flowtrack/flowtrack.c \
|
||||
-o "install/MINGW/$CPU/flowtrack.exe" -lWinDivert -lpsapi \
|
||||
-lshlwapi -L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/windivertctl.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/windivertctl/windivertctl.c \
|
||||
-o "install/MINGW/$CPU/windivertctl.exe" -lWinDivert \
|
||||
-lpsapi -lshlwapi -L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/socketdump.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/socketdump/socketdump.c \
|
||||
-o "install/MINGW/$CPU/socketdump.exe" -lWinDivert \
|
||||
-lpsapi -lshlwapi -L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/WinDivert$BITS.sys..."
|
||||
cp install/WDDK/$CPU/WinDivert$BITS.sys install/MINGW/$CPU
|
||||
else
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
:: msvc-build.bat
|
||||
:: (C) 2018, 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 <http://www.gnu.org/licenses/>.
|
||||
::
|
||||
:: 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.
|
||||
::
|
||||
:: Script for MSVC (Microsoft Visual Studio 2012) compilation.
|
||||
:: NOTE: run wddk-build.bat before this script.
|
||||
|
||||
@echo off
|
||||
|
||||
:: Determine target CPU.
|
||||
|
||||
cl 2>&1 | findstr "x86" > NUL
|
||||
|
||||
if %ERRORLEVEL% == 0 (
|
||||
set TARGET=i386
|
||||
set PLATFORM=Win32
|
||||
set BITS=32
|
||||
) ELSE (
|
||||
set TARGET=amd64
|
||||
set PLATFORM=x64
|
||||
set BITS=64
|
||||
)
|
||||
|
||||
set WDDK_INSTALL=install\WDDK\%TARGET%\
|
||||
set MSVC_INSTALL=install\MSVC\%TARGET%\
|
||||
|
||||
if not exist %WDDK_INSTALL% (
|
||||
echo ERROR: Missing WDDK build; run wddk-build.bat first
|
||||
exit /B
|
||||
)
|
||||
mkdir %MSVC_INSTALL%
|
||||
|
||||
:: Build WinDivert.dll
|
||||
cd dll
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\WinDivert.dll ..\%MSVC_INSTALL%
|
||||
copy /Y build\WinDivert.lib ..\%MSVC_INSTALL%
|
||||
copy /Y build\WinDivert.lib ..\%MSVC_INSTALL%..
|
||||
rd /s /q build\
|
||||
cd ..
|
||||
|
||||
:: Build netdump
|
||||
cd examples\netdump
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\netdump.exe ..\..\%MSVC_INSTALL%
|
||||
rd /s /q build\
|
||||
cd ..\..
|
||||
|
||||
:: Build netfilter
|
||||
cd examples\netfilter
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\netfilter.exe ..\..\%MSVC_INSTALL%
|
||||
rd /s /q build\
|
||||
cd ..\..
|
||||
|
||||
:: Build passthru
|
||||
cd examples\passthru
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\passthru.exe ..\..\%MSVC_INSTALL%
|
||||
rd /s /q build\
|
||||
cd ..\..
|
||||
|
||||
:: Build webfilter
|
||||
cd examples\webfilter
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\webfilter.exe ..\..\%MSVC_INSTALL%
|
||||
rd /s /q build\
|
||||
cd ..\..
|
||||
|
||||
:: Build streamdump
|
||||
cd examples\streamdump
|
||||
msbuild /p:Platform=%PLATFORM% /p:OutDir=build\
|
||||
copy /Y build\streamdump.exe ..\..\%MSVC_INSTALL%
|
||||
rd /s /q build\
|
||||
cd ..\..
|
||||
|
||||
:: Copy files
|
||||
copy /Y %WDDK_INSTALL%\WinDivert%BITS%.sys %MSVC_INSTALL%
|
||||
|
||||
:: Clean-up
|
||||
del %MSVC_INSTALL%..\WinDivert.lib
|
||||
|
||||
+13
-21
@@ -40,15 +40,15 @@ set -e
|
||||
VERSION=`cat ./VERSION`
|
||||
NAME=WinDivert-$VERSION
|
||||
|
||||
for TARGET in WDDK MSVC MINGW
|
||||
for TARGET in MINGW
|
||||
do
|
||||
if [ ! -d "install/$TARGET" ]
|
||||
then
|
||||
echo "SKIP $NAME-$TARGET"
|
||||
continue
|
||||
fi
|
||||
echo "BUILD $NAME-$TARGET"
|
||||
INSTALL=install/$NAME-$TARGET
|
||||
echo "BUILD $NAME"
|
||||
INSTALL=install/$NAME
|
||||
echo "\tmake $INSTALL..."
|
||||
mkdir -p $INSTALL
|
||||
echo "\tcopy $INSTALL/README..."
|
||||
@@ -76,11 +76,8 @@ do
|
||||
then
|
||||
echo "\t\033[33mWARNING\033[0m: unsigned WinDivert32.sys..."
|
||||
fi
|
||||
if [ $TARGET != MINGW ]
|
||||
then
|
||||
echo "\tcopy $INSTALL/x86/WinDivert.lib..."
|
||||
cp install/$TARGET/i386/WinDivert.lib $INSTALL/x86
|
||||
fi
|
||||
echo "\tcopy $INSTALL/x86/WinDivert.lib..."
|
||||
cp install/$TARGET/i386/WinDivert.lib $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/x86/WinDivert.dll..."
|
||||
cp install/$TARGET/i386/WinDivert.dll $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/x86/netdump.exe..."
|
||||
@@ -93,6 +90,8 @@ do
|
||||
cp install/$TARGET/i386/webfilter.exe $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/x86/streamdump.exe..."
|
||||
cp install/$TARGET/i386/streamdump.exe $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/i386/flowtrack.exe..."
|
||||
cp install/$TARGET/i386/flowtrack.exe $INSTALL/amd64
|
||||
if [ -d "install/$TARGET/amd64" ]
|
||||
then
|
||||
echo "\tmake $INSTALL/amd64..."
|
||||
@@ -104,11 +103,8 @@ do
|
||||
then
|
||||
echo -e "\t\033[33mWARNING\033[0m: unsigned WinDivert64.sys..."
|
||||
fi
|
||||
if [ $TARGET != MINGW ]
|
||||
then
|
||||
echo "\tcopy $INSTALL/amd64/WinDivert.lib..."
|
||||
cp install/$TARGET/amd64/WinDivert.lib $INSTALL/amd64
|
||||
fi
|
||||
echo "\tcopy $INSTALL/amd64/WinDivert.lib..."
|
||||
cp install/$TARGET/amd64/WinDivert.lib $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/WinDivert.dll..."
|
||||
cp install/$TARGET/amd64/WinDivert.dll $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/netdump.exe..."
|
||||
@@ -121,20 +117,16 @@ do
|
||||
cp install/$TARGET/amd64/webfilter.exe $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/streamdump.exe..."
|
||||
cp install/$TARGET/amd64/streamdump.exe $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/flowtrack.exe..."
|
||||
cp install/$TARGET/amd64/flowtrack.exe $INSTALL/amd64
|
||||
else
|
||||
echo "\tWARNING: skipping missing AMD64 build..."
|
||||
fi
|
||||
PACKAGE=$NAME-$TARGET.tar.gz
|
||||
PACKAGE=$NAME.zip
|
||||
echo "\tbuilding $PACKAGE..."
|
||||
(
|
||||
cd install;
|
||||
tar cvz --owner root --group root -f $PACKAGE $NAME-$TARGET > /dev/null
|
||||
)
|
||||
PACKAGE=$NAME-$TARGET.zip
|
||||
echo "\tbuilding $PACKAGE..."
|
||||
(
|
||||
cd install;
|
||||
zip -r $PACKAGE $NAME-$TARGET > /dev/null
|
||||
zip -r $PACKAGE $NAME > /dev/null
|
||||
)
|
||||
echo -n "\tclean $INSTALL..."
|
||||
rm -rf $INSTALL
|
||||
|
||||
+1
-1
@@ -19,6 +19,6 @@ NTTARGETFILES=
|
||||
KMDF_VERSION_MAJOR=1
|
||||
C_DEFINES=$(C_DEFINES) -DBINARY_COMPATIBLE=0 -DNT -DUNICODE -D_UNICODE \
|
||||
-DNDIS60 -DNDIS_SUPPORT_NDIS60
|
||||
INCLUDES=$(DDK_INC_PATH);..\include
|
||||
INCLUDES=$(DDK_INC_PATH);..\include;..\dll
|
||||
SOURCES=windivert.rc windivert.c
|
||||
|
||||
|
||||
+3530
-1161
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -43,15 +43,15 @@
|
||||
"[Bitcoin: 1C5vZVSbizPeZ8ydTYhUfm4LA2cNwBfcYh]"
|
||||
#define VER_INTERNALNAME_STR "WinDivert.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "WinDivert.sys"
|
||||
#define VER_PRODUCTVERSION 1.4
|
||||
#define VER_PRODUCTVERSION_STR "1.4"
|
||||
#define VER_COMPANYNAME_STR "Basil's Projects"
|
||||
#define VER_LEGALCOPYRIGHT_YEARS "2011-2017"
|
||||
#define VER_PRODUCTVERSION 2.0
|
||||
#define VER_PRODUCTVERSION_STR "2.0"
|
||||
#define VER_COMPANYNAME_STR "Basil"
|
||||
#define VER_LEGALCOPYRIGHT_YEARS "2011-2019"
|
||||
#define VER_LEGALCOPYRIGHT_STR \
|
||||
"Copyright \251 " VER_COMPANYNAME_STR " " VER_LEGALCOPYRIGHT_YEARS
|
||||
#define VER_FILEVERSION VER_PRODUCTVERSION
|
||||
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTNAME_STR "WinDivert 1.4 driver"
|
||||
#define VER_PRODUCTNAME_STR "WinDivert 2.0 driver"
|
||||
|
||||
#include "common.ver"
|
||||
|
||||
|
||||
+1
-1
@@ -37,6 +37,6 @@
|
||||
|
||||
CC=x86_64-w64-mingw32-gcc
|
||||
|
||||
$CC -s -O2 -I../include/ test.c -o test.exe -lWinDivert \
|
||||
$CC -fno-ident -s -O2 -I../include/ test.c -o test.exe -lWinDivert \
|
||||
-L"../install/MINGW/amd64/"
|
||||
|
||||
|
||||
+297
-129
@@ -54,15 +54,15 @@
|
||||
*/
|
||||
struct packet
|
||||
{
|
||||
char *packet;
|
||||
const char *packet;
|
||||
size_t packet_len;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct test
|
||||
{
|
||||
char *filter;
|
||||
struct packet *packet;
|
||||
const char *filter;
|
||||
const struct packet *packet;
|
||||
BOOL match;
|
||||
};
|
||||
|
||||
@@ -70,49 +70,78 @@ struct test
|
||||
* Prototypes.
|
||||
*/
|
||||
static BOOL run_test(HANDLE inject_handle, const char *filter,
|
||||
const char *packet, const size_t packet_len, BOOL match);
|
||||
const char *packet, const size_t packet_len, BOOL match, INT64 *diff);
|
||||
|
||||
/*
|
||||
* Test data.
|
||||
*/
|
||||
static struct packet pkt_echo_request =
|
||||
static const struct packet pkt_echo_request =
|
||||
{
|
||||
echo_request,
|
||||
sizeof(echo_request),
|
||||
"ipv4_icmp_echo_req"
|
||||
};
|
||||
static struct packet pkt_http_request =
|
||||
static const struct packet pkt_http_request =
|
||||
{
|
||||
http_request,
|
||||
sizeof(http_request),
|
||||
"ipv4_tcp_http_req"
|
||||
};
|
||||
static struct packet pkt_dns_request =
|
||||
static const struct packet pkt_dns_request =
|
||||
{
|
||||
dns_request,
|
||||
sizeof(dns_request),
|
||||
"ipv4_udp_dns_req"
|
||||
};
|
||||
static struct packet pkt_ipv6_tcp_syn =
|
||||
static const struct packet pkt_ipv6_tcp_syn =
|
||||
{
|
||||
ipv6_tcp_syn,
|
||||
sizeof(ipv6_tcp_syn),
|
||||
"ipv6_tcp_syn"
|
||||
};
|
||||
static struct packet pkt_ipv6_echo_reply =
|
||||
static const struct packet pkt_ipv6_echo_reply =
|
||||
{
|
||||
ipv6_echo_reply,
|
||||
sizeof(ipv6_echo_reply),
|
||||
"ipv6_icmpv6_echo_rep"
|
||||
};
|
||||
static struct packet pkt_ipv6_exthdrs_udp =
|
||||
static const struct packet pkt_ipv6_exthdrs_udp =
|
||||
{
|
||||
ipv6_exthdrs_udp,
|
||||
sizeof(ipv6_exthdrs_udp),
|
||||
"ipv6_exthdrs_udp"
|
||||
};
|
||||
static struct test tests[] =
|
||||
static const struct test tests[] =
|
||||
{
|
||||
{"event = PACKET", &pkt_echo_request, TRUE},
|
||||
{"packet[0] == 0x45", &pkt_echo_request, TRUE},
|
||||
{"packet[0] == 0x33", &pkt_echo_request, FALSE},
|
||||
{"packet[55] == 0x1b", &pkt_echo_request, TRUE},
|
||||
{"packet[55b] == 0x1b", &pkt_echo_request, TRUE},
|
||||
{"packet[1000] <= 0 || packet[-1000] = 7", &pkt_echo_request, FALSE},
|
||||
{"packet[-1] == 0x37 && packet[-2] == 0x36 && packet[-3] == 0x35 && "
|
||||
"packet[-4] == 0x34", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x4500", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x0045", &pkt_echo_request, FALSE},
|
||||
{"packet16[2b] == 0x0054", &pkt_echo_request, TRUE},
|
||||
{"packet16[1] == 0x0054", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x4500 && packet16[1] == 0x0054 && "
|
||||
"packet16[-1] == 0x3637", &pkt_echo_request, TRUE},
|
||||
{"packet32[0b] == 0x45000054 && packet32[3b] == 0x54123440 && "
|
||||
"packet32[-4b] == 0x34353637 && packet32[-5b] == 0x33343536",
|
||||
&pkt_echo_request, TRUE},
|
||||
{"random8 < 10", &pkt_echo_request, TRUE},
|
||||
{"random16 >= 2222", &pkt_echo_request, TRUE},
|
||||
{"random32 <= 0x80000000", &pkt_echo_request, TRUE},
|
||||
{"(random8 < 128? icmp: udp)", &pkt_echo_request, TRUE},
|
||||
{"(random8 <= 128? "
|
||||
"(random16 <= 0x8000?"
|
||||
"(random32 <= 0x80000000? ip: ipv6): "
|
||||
"(random32 <= 0x80000000? icmpv6: icmp)): "
|
||||
"(random16 <= 0x8000?"
|
||||
"(random32 <= 0x80000000? tcp: icmp.Type >= 8): "
|
||||
"(random32 <= 0x80000000? outbound: loopback)))",
|
||||
&pkt_echo_request, TRUE},
|
||||
{"outbound and icmp", &pkt_echo_request, TRUE},
|
||||
{"outbound", &pkt_echo_request, TRUE},
|
||||
{"outbound and inbound", &pkt_echo_request, FALSE},
|
||||
@@ -241,6 +270,82 @@ static struct test tests[] =
|
||||
"false): false): false): false)", &pkt_http_request, TRUE},
|
||||
{"(outbound? (ip? (tcp.DstPort == 80? (tcp.PayloadLength == 0? true: "
|
||||
"false): false): false): false)", &pkt_http_request, FALSE},
|
||||
{"(ipv6? tcp and tcp.DstPort = 1234 and (tcp.SrcPort = 999? !tcp.UrgPtr: "
|
||||
"tcp.Syn) or udp: ip and tcp.DstPort == 80)",
|
||||
&pkt_http_request, TRUE},
|
||||
{"packet32[0] = 0x45000209 && packet32[1] = 0x482d4000 && "
|
||||
"packet16[8b] = 0x4006 && packet32[3] = 0x0a0a0a0a && "
|
||||
"packet32[4] = 0x5db8d877 && packet32[5] = 0xa31a0050 && "
|
||||
"packet32[6] = 0x5338ccc2 && packet32[7] = 0x5637b355 && "
|
||||
"packet32[8] = 0x80180073 && packet16[38b] = 0x0000 && "
|
||||
"packet32[10] = 0x0101080a && packet32[11] = 0x002c851b && "
|
||||
"packet32[12] = 0x1b7f3a71 && packet32[13] = 0x47455420 && "
|
||||
"packet32[14] = 0x2f204854 && packet32[15] = 0x54502f31 && "
|
||||
"packet32[16] = 0x2e310d0a && packet32[17] = 0x486f7374 && "
|
||||
"packet32[18] = 0x3a207777 && packet32[19] = 0x772e6578 && "
|
||||
"packet32[20] = 0x616d706c && packet32[21] = 0x652e636f && "
|
||||
"packet32[22] = 0x6d0d0a43 && packet32[23] = 0x6f6e6e65 && "
|
||||
"packet32[24] = 0x6374696f && packet32[25] = 0x6e3a206b && "
|
||||
"packet32[26] = 0x6565702d && packet32[27] = 0x616c6976 && "
|
||||
"packet32[28] = 0x650d0a43 && packet32[29] = 0x61636865 && "
|
||||
"packet32[30] = 0x2d436f6e && packet32[31] = 0x74726f6c && "
|
||||
"packet32[32] = 0x3a206d61 && packet32[33] = 0x782d6167 && "
|
||||
"packet32[34] = 0x653d300d && packet32[35] = 0x0a416363 && "
|
||||
"packet32[36] = 0x6570743a && packet32[37] = 0x20746578 && "
|
||||
"packet32[38] = 0x742f6874 && packet32[39] = 0x6d6c2c61 && "
|
||||
"packet32[40] = 0x70706c69 && packet32[41] = 0x63617469 && "
|
||||
"packet32[42] = 0x6f6e2f78 && packet32[43] = 0x68746d6c && "
|
||||
"packet32[44] = 0x2b786d6c && packet32[45] = 0x2c617070 && "
|
||||
"packet32[46] = 0x6c696361 && packet32[47] = 0x74696f6e && "
|
||||
"packet32[48] = 0x2f786d6c && packet32[49] = 0x3b713d30 && "
|
||||
"packet32[50] = 0x2e392c69 && packet32[51] = 0x6d616765 && "
|
||||
"packet32[52] = 0x2f776562 && packet32[53] = 0x702c2a2f && "
|
||||
"packet32[54] = 0x2a3b713d && packet32[55] = 0x302e380d && "
|
||||
"packet32[56] = 0x0a557365 && packet32[57] = 0x722d4167 && "
|
||||
"packet32[58] = 0x656e743a && packet32[59] = 0x20585858 && "
|
||||
"packet32[60] = 0x58585858 && packet32[61] = 0x58585858 && "
|
||||
"packet32[62] = 0x58585858 && packet32[63] = 0x58585858 && "
|
||||
"packet32[64] = 0x58585858 && packet32[65] = 0x58585858 && "
|
||||
"packet32[66] = 0x58585858 && packet32[67] = 0x58585858 && "
|
||||
"packet32[68] = 0x58585858 && packet32[69] = 0x58585858 && "
|
||||
"packet32[70] = 0x58585858 && packet32[71] = 0x58585858 && "
|
||||
"packet32[72] = 0x58585858 && packet32[73] = 0x58585858 && "
|
||||
"packet32[74] = 0x58585858 && packet32[75] = 0x58585858 && "
|
||||
"packet32[76] = 0x58585858 && packet32[77] = 0x58585858 && "
|
||||
"packet32[78] = 0x58585858 && packet32[79] = 0x58585858 && "
|
||||
"packet32[80] = 0x58585858 && packet32[81] = 0x58585858 && "
|
||||
"packet32[82] = 0x58585858 && packet32[83] = 0x58585858 && "
|
||||
"packet32[84] = 0x58585858 && packet32[85] = 0x58585858 && "
|
||||
"packet32[86] = 0x58585858 && packet32[87] = 0x58585858 && "
|
||||
"packet32[88] = 0x58585858 && packet32[89] = 0x58585858 && "
|
||||
"packet32[90] = 0x58585858 && packet32[91] = 0x58585858 && "
|
||||
"packet32[92] = 0x58580d0a && packet32[93] = 0x41636365 && "
|
||||
"packet32[94] = 0x70742d45 && packet32[95] = 0x6e636f64 && "
|
||||
"packet32[96] = 0x696e673a && packet32[97] = 0x20677a69 && "
|
||||
"packet32[98] = 0x702c6465 && packet32[99] = 0x666c6174 && "
|
||||
"packet32[100] = 0x652c7364 && packet32[101] = 0x63680d0a && "
|
||||
"packet32[102] = 0x41636365 && packet32[103] = 0x70742d4c && "
|
||||
"packet32[104] = 0x616e6775 && packet32[105] = 0x6167653a && "
|
||||
"packet32[106] = 0x20656e2d && packet32[107] = 0x55532c65 && "
|
||||
"packet32[108] = 0x6e3b713d && packet32[109] = 0x302e380d && "
|
||||
"packet32[110] = 0x0a49662d && packet32[111] = 0x4e6f6e65 && "
|
||||
"packet32[112] = 0x2d4d6174 && packet32[113] = 0x63683a20 && "
|
||||
"packet32[114] = 0x22333333 && packet32[115] = 0x33333333 && "
|
||||
"packet32[116] = 0x3333220d && packet32[117] = 0x0a49662d && "
|
||||
"packet32[118] = 0x4d6f6469 && packet32[119] = 0x66696564 && "
|
||||
"packet32[120] = 0x2d53696e && packet32[121] = 0x63653a20 && "
|
||||
"packet32[122] = 0x4672692c && packet32[123] = 0x20303320 && "
|
||||
"packet32[124] = 0x41756720 && packet32[125] = 0x32303134 && "
|
||||
"packet32[126] = 0x2031333a && packet32[127] = 0x33333a33 && "
|
||||
"packet32[128] = 0x3320474d && packet32[129] = 0x540d0a0d && "
|
||||
"packet[-1] = 0x0a", &pkt_http_request, TRUE},
|
||||
{"tcp.Payload16[-1] == 0x0d0a", &pkt_http_request, TRUE},
|
||||
{"tcp.Payload32[-2] == 0x20474d54", &pkt_http_request, TRUE},
|
||||
{"random8 < 128", &pkt_http_request, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_http_request, TRUE},
|
||||
{"(random32 < 0x22223333? packet32[72] == 0x58585858: udp)",
|
||||
&pkt_http_request, TRUE},
|
||||
{"udp", &pkt_dns_request, TRUE},
|
||||
{"udp && udp.SrcPort > 1 && ipv6", &pkt_dns_request, FALSE},
|
||||
{"udp.DstPort == 53", &pkt_dns_request, TRUE},
|
||||
@@ -253,7 +358,18 @@ static struct test tests[] =
|
||||
&pkt_dns_request, TRUE},
|
||||
{"ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255",
|
||||
&pkt_dns_request, FALSE},
|
||||
{"ip.DstAddr == ::ffff:8.8.4.4", &pkt_dns_request, TRUE},
|
||||
{"ip.DstAddr == ::0:ffff:8.8.4.4", &pkt_dns_request, TRUE},
|
||||
{"udp.PayloadLength == 29", &pkt_dns_request, TRUE},
|
||||
{"udp.Payload16[-1] == 0x0001 && udp.Payload16[-2] == 0x0001",
|
||||
&pkt_dns_request, TRUE},
|
||||
{"packet16[-1] == 0x0001 && packet16[-2] == 0x0001",
|
||||
&pkt_dns_request, TRUE},
|
||||
{"tcp.Payload32[0] > 0", &pkt_dns_request, FALSE},
|
||||
{"udp.Payload32[1] > 0", &pkt_dns_request, TRUE},
|
||||
{"random8 < 128", &pkt_dns_request, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_dns_request, TRUE},
|
||||
{"ipv6", &pkt_ipv6_tcp_syn, TRUE},
|
||||
{"ip", &pkt_ipv6_tcp_syn, FALSE},
|
||||
{"tcp.Syn", &pkt_ipv6_tcp_syn, TRUE},
|
||||
@@ -267,6 +383,15 @@ static struct test tests[] =
|
||||
{"ipv6.SrcAddr == aabb:5678:1::1234:ccdd", &pkt_ipv6_tcp_syn, FALSE},
|
||||
{"tcp.SrcPort == 50046", &pkt_ipv6_tcp_syn, TRUE},
|
||||
{"tcp.SrcPort == 0x0000C37E", &pkt_ipv6_tcp_syn, TRUE},
|
||||
{"packet32[0b] == 0x60000000 && packet32[1b] == 0x00000000 && "
|
||||
"packet32[2b] == 0x00000028 && packet32[3b] == 0x00002806 && "
|
||||
"packet32[4b] == 0x00280640 && packet32[5b] == 0x28064012 && "
|
||||
"packet32[-4b] == 0x01030307 && packet32[-5b] == 0x00010303",
|
||||
&pkt_ipv6_tcp_syn, TRUE},
|
||||
{"tcp.Payload32[0] > 0", &pkt_ipv6_tcp_syn, FALSE},
|
||||
{"random8 < 128", &pkt_ipv6_tcp_syn, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_ipv6_tcp_syn, TRUE},
|
||||
{"icmpv6", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"icmp", &pkt_ipv6_echo_reply, FALSE},
|
||||
{"icmp or icmpv6", &pkt_ipv6_echo_reply, TRUE},
|
||||
@@ -276,12 +401,17 @@ static struct test tests[] =
|
||||
{"icmpv6.Body == 0x10720003", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"ipv6.DstAddr >= 1000", &pkt_ipv6_echo_reply, FALSE},
|
||||
{"ipv6.DstAddr <= 1", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"random8 < 128", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_ipv6_echo_reply, TRUE},
|
||||
{"true", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"false", &pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"udp", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"tcp", &pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"ipv6.SrcAddr == ::", &pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"ipv6.SrcAddr == ::1", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"ipv6.SrcAddr == ::2", &pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"ipv6.SrcAddr == ::8.8.4.4", &pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"ipv6.SrcAddr < abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"ipv6.SrcAddr <= abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"ipv6.SrcAddr != abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
@@ -296,6 +426,14 @@ static struct test tests[] =
|
||||
"(inbound and tcp? tcp.SrcPort == 0xABAB: false) or "
|
||||
"(inbound and udp? udp.SrcPort == 0xAAAA: false)",
|
||||
&pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"(tcp or udp) and (ip or ipv6) and (icmp or !icmpv6) and "
|
||||
"(tcp.Payload16[-1] == 0x1234 or udp.Payload16[-1] == 0x2101)",
|
||||
&pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"(tcp or icmp or icmpv6 or ip or !udp or ipv6? udp.PayloadLength > 0: "
|
||||
"udp.DstPort == 39482)", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"random8 < 128", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_ipv6_exthdrs_udp, TRUE},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -305,14 +443,16 @@ int main(void)
|
||||
{
|
||||
HANDLE upper_handle, lower_handle;
|
||||
HANDLE console;
|
||||
LARGE_INTEGER freq;
|
||||
UINT64 diff;
|
||||
size_t i;
|
||||
|
||||
// Open handles to:
|
||||
// (1) stop normal traffic from interacting with the tests; and
|
||||
// (2) stop test packets escaping to the Internet or TCP/IP stack.
|
||||
upper_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, -510,
|
||||
WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_DEBUG);
|
||||
lower_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 510,
|
||||
upper_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, -999,
|
||||
WINDIVERT_FLAG_DROP);
|
||||
lower_handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 999,
|
||||
WINDIVERT_FLAG_DROP);
|
||||
if (upper_handle == INVALID_HANDLE_VALUE ||
|
||||
lower_handle == INVALID_HANDLE_VALUE)
|
||||
@@ -323,31 +463,31 @@ int main(void)
|
||||
}
|
||||
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
QueryPerformanceFrequency(&freq);
|
||||
|
||||
// Wait for existing packets to flush:
|
||||
Sleep(100);
|
||||
Sleep(150);
|
||||
|
||||
// Run tests:
|
||||
size_t num_tests = sizeof(tests) / sizeof(struct test);
|
||||
size_t num_tests = sizeof(tests) / sizeof(struct test), passed_tests = 0;
|
||||
for (i = 0; i < num_tests; i++)
|
||||
{
|
||||
char *filter = tests[i].filter;
|
||||
char *packet = tests[i].packet->packet;
|
||||
const char *filter = tests[i].filter;
|
||||
const char *packet = tests[i].packet->packet;
|
||||
size_t packet_len = tests[i].packet->packet_len;
|
||||
char *name = tests[i].packet->name;
|
||||
BOOL match = tests[i].match;
|
||||
|
||||
// Ensure the correct checksum:
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, NULL, 0);
|
||||
|
||||
// Run the test:
|
||||
BOOL res = run_test(upper_handle, filter, packet, packet_len, match);
|
||||
|
||||
printf("%.2u ", i);
|
||||
BOOL res = run_test(upper_handle, filter, packet, packet_len, match,
|
||||
&diff);
|
||||
diff = 1000000 * diff / freq.QuadPart;
|
||||
printf("%.3u ", i);
|
||||
if (res)
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("PASSED");
|
||||
passed_tests++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -356,7 +496,7 @@ int main(void)
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE);
|
||||
printf(" p=[");
|
||||
printf(" %.5llu p=[", diff);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%s", name);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
@@ -372,6 +512,9 @@ int main(void)
|
||||
WinDivertClose(upper_handle);
|
||||
WinDivertClose(lower_handle);
|
||||
|
||||
printf("\npassed = %.2f%%\n",
|
||||
((double)passed_tests / (double)num_tests) * 100.0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -379,60 +522,82 @@ int main(void)
|
||||
* Run a test case.
|
||||
*/
|
||||
static BOOL run_test(HANDLE inject_handle, const char *filter,
|
||||
const char *packet, const size_t packet_len, BOOL match)
|
||||
const char *packet, const size_t packet_len, BOOL match, INT64 *diff)
|
||||
{
|
||||
char buf[MAX_PACKET];
|
||||
UINT buf_len, i;
|
||||
static char object[8192];
|
||||
char buf[2][MAX_PACKET];
|
||||
UINT buf_len[2], i, idx;
|
||||
DWORD iolen;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
OVERLAPPED overlapped;
|
||||
WINDIVERT_ADDRESS addr[2], addr_send;
|
||||
OVERLAPPED overlapped[2];
|
||||
const char *err_str;
|
||||
UINT err_pos;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE, handle0 = INVALID_HANDLE_VALUE,
|
||||
event = NULL;
|
||||
PWINDIVERT_IPHDR iphdr = NULL;
|
||||
HANDLE handle[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
|
||||
HANDLE event[2] = {NULL, NULL};
|
||||
BOOL random, result, ipv4;
|
||||
LARGE_INTEGER end;
|
||||
|
||||
*diff = 0;
|
||||
|
||||
// (0) Verify the test data:
|
||||
if (!WinDivertHelperCheckFilter(filter, WINDIVERT_LAYER_NETWORK, &err_str,
|
||||
&err_pos))
|
||||
if (!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_NETWORK,
|
||||
object, sizeof(object), &err_str, &err_pos))
|
||||
{
|
||||
fprintf(stderr, "error: filter string \"%s\" is invalid with error "
|
||||
"\"%s\" (position=%u)\n", filter, err_str, err_pos);
|
||||
goto failed;
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.Direction = WINDIVERT_DIRECTION_OUTBOUND;
|
||||
if (WinDivertHelperEvalFilter(filter, WINDIVERT_LAYER_NETWORK,
|
||||
(PVOID)packet, packet_len, &addr) != match)
|
||||
{
|
||||
fprintf(stderr, "error: filter \"%s\" does not match the given "
|
||||
"packet\n", filter);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// (1) Open a WinDivert handle to the given filter:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, 0, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
// (1) Open WinDivert handles:
|
||||
handle[0] = WinDivertOpen(object, WINDIVERT_LAYER_NETWORK, 777, 0);
|
||||
if (handle[0] == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fprintf(stderr, "error: failed to open WinDivert handle for filter "
|
||||
"\"%s\" (err = %d)\n", filter, GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!match)
|
||||
handle[1] = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 888, 0);
|
||||
if (handle[1] == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Catch non-matching packets:
|
||||
handle0 = handle;
|
||||
handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 33, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fprintf(stderr, "error: failed to open WinDivert handle "
|
||||
"(err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
fprintf(stderr, "error: failed to open WinDivert handle "
|
||||
"(err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// (2) Create pended recv requests:
|
||||
event[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
event[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (event[0] == NULL || event[1] == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to create event (err = %d)\n",
|
||||
GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
memset(&overlapped[0], 0, sizeof(overlapped[0]));
|
||||
memset(&overlapped[1], 0, sizeof(overlapped[1]));
|
||||
overlapped[0].hEvent = event[0];
|
||||
overlapped[1].hEvent = event[1];
|
||||
if (WinDivertRecvEx(handle[0], buf[0], sizeof(buf[0]), &buf_len[0], 0,
|
||||
&addr[0], NULL, &overlapped[0]) ||
|
||||
GetLastError() != ERROR_IO_PENDING ||
|
||||
WinDivertRecvEx(handle[1], buf[1], sizeof(buf[1]), &buf_len[1], 0,
|
||||
&addr[1], NULL, &overlapped[1]) ||
|
||||
GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
fprintf(stderr, "error: failed to created pended recv from WinDivert "
|
||||
"handle (err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// (2) Inject the packet:
|
||||
if (!WinDivertSend(inject_handle, (PVOID)packet, packet_len, &addr, NULL))
|
||||
memset(&addr_send, 0, sizeof(addr_send));
|
||||
addr_send.Outbound = TRUE;
|
||||
addr_send.PseudoIPChecksum = TRUE;
|
||||
addr_send.PseudoTCPChecksum = TRUE;
|
||||
addr_send.PseudoUDPChecksum = TRUE;
|
||||
if (!WinDivertSend(inject_handle, (PVOID)packet, packet_len, &addr_send,
|
||||
NULL))
|
||||
{
|
||||
fprintf(stderr, "error: failed to inject test packet (err = %d)\n",
|
||||
GetLastError());
|
||||
@@ -441,108 +606,111 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
|
||||
|
||||
// (3) Wait for the packet to arrive.
|
||||
// NOTE: This may fail, so set a generous time-out of 250ms.
|
||||
memset(&overlapped, 0, sizeof(overlapped));
|
||||
event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (event == NULL)
|
||||
switch (WaitForMultipleObjects(2, event, FALSE, 250))
|
||||
{
|
||||
fprintf(stderr, "error: failed to create event (err = %d)\n",
|
||||
GetLastError());
|
||||
case WAIT_OBJECT_0:
|
||||
QueryPerformanceCounter(&end);
|
||||
result = TRUE;
|
||||
idx = 0;
|
||||
break;
|
||||
case WAIT_OBJECT_0+1:
|
||||
QueryPerformanceCounter(&end);
|
||||
result = FALSE;
|
||||
idx = 1;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
fprintf(stderr, "error: failed to read packet from WinDivert "
|
||||
"handle (timeout)\n", GetLastError());
|
||||
goto failed;
|
||||
default:
|
||||
fprintf(stderr, "error: failed to wait for packet (err = %d)\n",
|
||||
GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
if (!GetOverlappedResult(handle[idx], &overlapped[idx], &iolen, TRUE))
|
||||
{
|
||||
fprintf(stderr, "error: failed to get the overlapped result from "
|
||||
"WinDivert handle (err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
overlapped.hEvent = event;
|
||||
if (!WinDivertRecvEx(handle, buf, sizeof(buf), 0, &addr, &buf_len,
|
||||
&overlapped))
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
read_failed:
|
||||
fprintf(stderr, "error: failed to read packet from WinDivert "
|
||||
"handle (err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
buf_len[idx] = (UINT)iolen;
|
||||
*diff = end.QuadPart - addr[idx].Timestamp;
|
||||
|
||||
switch (WaitForSingleObject(event, 250))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
fprintf(stderr, "error: failed to read packet from WinDivert "
|
||||
"handle (timeout)\n", GetLastError());
|
||||
goto failed;
|
||||
default:
|
||||
goto read_failed;
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(handle, &overlapped, &iolen, TRUE))
|
||||
{
|
||||
fprintf(stderr, "error: failed to get the overlapped result from "
|
||||
"WinDivert handle (err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
buf_len = (UINT)iolen;
|
||||
}
|
||||
if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(buf, buf_len, NULL, 0);
|
||||
}
|
||||
|
||||
// (4) Verify that the packet is the same.
|
||||
if (buf_len != packet_len)
|
||||
// (4) Verify that the packet is the same & matches.
|
||||
if (buf_len[idx] != packet_len)
|
||||
{
|
||||
fprintf(stderr, "error: packet length mis-match, expected (%u), got "
|
||||
"(%u)\n", packet_len, buf_len);
|
||||
"(%u)\n", packet_len, buf_len[idx]);
|
||||
goto failed;
|
||||
}
|
||||
iphdr = (PWINDIVERT_IPHDR)buf[idx];
|
||||
ipv4 = (iphdr->Version == 4);
|
||||
for (i = 0; i < packet_len; i++)
|
||||
{
|
||||
if (packet[i] != buf[i])
|
||||
if (ipv4 && i >= offsetof(WINDIVERT_IPHDR, Checksum) &&
|
||||
i < offsetof(WINDIVERT_IPHDR, Checksum) + sizeof(UINT16))
|
||||
{
|
||||
// The IPv4 checksum can change, so ignore it.
|
||||
continue;
|
||||
}
|
||||
if (packet[i] != buf[idx][i])
|
||||
{
|
||||
fprintf(stderr, "error: packet data mis-match, expected byte #%u "
|
||||
"to be (0x%.2X), got (0x%.2X)\n", i, (unsigned char)packet[i],
|
||||
(unsigned char)buf[i]);
|
||||
(unsigned char)buf[idx][i]);
|
||||
for (i = 0; i < packet_len; i++)
|
||||
{
|
||||
printf("%c", (packet[i] == buf[i]? '.': 'X'));
|
||||
printf("%c", (packet[i] == buf[idx][i]? '.': 'X'));
|
||||
}
|
||||
putchar('\n');
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
// (5) Clean-up:
|
||||
if (!WinDivertClose(handle))
|
||||
random = (strstr(filter, "random") != 0);
|
||||
// If (random && !result), then we cannot verify since the original
|
||||
// non-matching random values have been lost:
|
||||
if ((!random &&
|
||||
WinDivertHelperEvalFilter(filter, buf[idx], buf_len[idx],
|
||||
&addr[idx]) != result) ||
|
||||
(random && result &&
|
||||
!WinDivertHelperEvalFilter(filter, buf[idx], buf_len[idx],
|
||||
&addr[idx])))
|
||||
{
|
||||
fprintf(stderr, "error: filter \"%s\" does not match the given "
|
||||
"packet\n", filter);
|
||||
goto failed;
|
||||
}
|
||||
if (!random && result != match)
|
||||
{
|
||||
fprintf(stderr, "error: filter \"%s\" does not match the expected "
|
||||
"result\n", filter);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// (5) Clean-up:
|
||||
if (!WinDivertClose(handle[0]) || !WinDivertClose(handle[1]))
|
||||
{
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
fprintf(stderr, "error: failed to close WinDivert handle (err = %d)\n",
|
||||
GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
if (handle0 != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!WinDivertClose(handle0))
|
||||
{
|
||||
handle0 = INVALID_HANDLE_VALUE;
|
||||
fprintf(stderr, "error: failed to close WinDivert handle "
|
||||
"(err = %d)\n", GetLastError());
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
CloseHandle(event);
|
||||
CloseHandle(event[0]);
|
||||
CloseHandle(event[1]);
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
if (handle0 != INVALID_HANDLE_VALUE)
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
WinDivertClose(handle0);
|
||||
}
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WinDivertClose(handle);
|
||||
}
|
||||
if (event != NULL)
|
||||
{
|
||||
CloseHandle(event);
|
||||
if (handle[i] != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WinDivertClose(handle[i]);
|
||||
}
|
||||
if (event[i] != NULL)
|
||||
{
|
||||
CloseHandle(event[i]);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+12
-12
@@ -33,11 +33,11 @@
|
||||
*/
|
||||
|
||||
// IPV4 ICMP ECHO REQUEST
|
||||
static unsigned char echo_request[] =
|
||||
static const unsigned char echo_request[] =
|
||||
{
|
||||
0x45, 0x00, 0x00, 0x54, 0x12, 0x34, 0x40, 0x00,
|
||||
0x40, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x3c, 0xd2,
|
||||
0x0d, 0x56, 0x00, 0x01, 0x8b, 0xa6, 0x60, 0x54,
|
||||
0x00, 0x00, 0x00, 0x00, 0xf9, 0x08, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
|
||||
@@ -49,13 +49,13 @@ static unsigned char echo_request[] =
|
||||
};
|
||||
|
||||
// IPV4 TCP HTTP GET REQUEST
|
||||
static unsigned char http_request[] =
|
||||
static const unsigned char http_request[] =
|
||||
{
|
||||
0x45, 0x00, 0x02, 0x09, 0x48, 0x2d, 0x40, 0x00,
|
||||
0x40, 0x06, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a,
|
||||
0x5d, 0xb8, 0xd8, 0x77, 0xa3, 0x1a, 0x00, 0x50,
|
||||
0x53, 0x38, 0xcc, 0xc2, 0x56, 0x37, 0xb3, 0x55,
|
||||
0x80, 0x18, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x18, 0x00, 0x73, 0x02, 0xa4, 0x00, 0x00,
|
||||
0x01, 0x01, 0x08, 0x0a, 0x00, 0x2c, 0x85, 0x1b,
|
||||
0x1b, 0x7f, 0x3a, 0x71, 0x47, 0x45, 0x54, 0x20,
|
||||
0x2f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,
|
||||
@@ -120,12 +120,12 @@ static unsigned char http_request[] =
|
||||
};
|
||||
|
||||
// IPV4 DNS REQUEST
|
||||
static unsigned char dns_request[] =
|
||||
static const unsigned char dns_request[] =
|
||||
{
|
||||
0x45, 0x00, 0x00, 0x39, 0x20, 0x90, 0x00, 0x00,
|
||||
0x49, 0x11, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01,
|
||||
0x08, 0x08, 0x04, 0x04, 0xe0, 0x45, 0x00, 0x35,
|
||||
0x00, 0x25, 0x00, 0x00, 0x17, 0x08, 0x01, 0x00,
|
||||
0x00, 0x25, 0x22, 0xa7, 0x17, 0x08, 0x01, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
|
||||
@@ -133,7 +133,7 @@ static unsigned char dns_request[] =
|
||||
};
|
||||
|
||||
// IPV6 TCP SYN
|
||||
static unsigned char ipv6_tcp_syn[] =
|
||||
static const unsigned char ipv6_tcp_syn[] =
|
||||
{
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0x06, 0x40,
|
||||
0x12, 0x34, 0x56, 0x78, 0x00, 0x01, 0x00, 0x00,
|
||||
@@ -142,20 +142,20 @@ static unsigned char ipv6_tcp_syn[] =
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0xc3, 0x7e, 0x00, 0x17, 0xe1, 0xd7, 0xc8, 0xaa,
|
||||
0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xaa, 0xaa,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xff, 0xc4,
|
||||
0xc3, 0x5e, 0x00, 0x00, 0x02, 0x04, 0xff, 0xc4,
|
||||
0x04, 0x02, 0x08, 0x0a, 0xff, 0xff, 0x91, 0x86,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07
|
||||
};
|
||||
|
||||
// IPV6 ICMPV6 ECHO REPLY
|
||||
static unsigned char ipv6_echo_reply[] =
|
||||
static const unsigned char ipv6_echo_reply[] =
|
||||
{
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x3a, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x81, 0x00, 0x00, 0x00, 0x10, 0x72, 0x00, 0x03,
|
||||
0x81, 0x00, 0x6e, 0xd6, 0x10, 0x72, 0x00, 0x03,
|
||||
0xa4, 0xd5, 0x69, 0x54, 0x00, 0x00, 0x00, 0x00,
|
||||
0xab, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
@@ -166,7 +166,7 @@ static unsigned char ipv6_echo_reply[] =
|
||||
};
|
||||
|
||||
// IPV6 EXTENSION HEADERS UDP
|
||||
static unsigned char ipv6_exthdrs_udp[] =
|
||||
static const unsigned char ipv6_exthdrs_udp[] =
|
||||
{
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x64,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -176,7 +176,7 @@ static unsigned char ipv6_exthdrs_udp[] =
|
||||
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x12, 0x34, 0xaa, 0xaa, 0x00, 0x15, 0x00, 0x00,
|
||||
0x12, 0x34, 0xaa, 0xaa, 0x00, 0x15, 0xef, 0xf4,
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f,
|
||||
0x72, 0x6c, 0x64, 0x21, 0x01
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user