Add new WINDIVERT_FLAG_FRAGMENTS flag (fix #191).

This flag only affects inbound packets at the
WINDIVERT_LAYER_NETWORK layer.

If set, the handle will capture IP fragments,
but not reassembled IP packets.

If unset (the default), the handle will capture
reassembled IP packets, but not IP fragments.
This commit is contained in:
basil00
2019-08-02 08:32:50 +08:00
parent 6eb82d08e0
commit 69e4edade7
7 changed files with 133 additions and 74 deletions
+7 -2
View File
@@ -297,8 +297,13 @@ WinDivert 2.0.1-rc
- Rename the following functions for consistency:
* WinDivertHelperNtohIpv6Address -> WinDivertHelperNtohIPv6Address
* WinDivertHelperHtonIpv6Address -> WinDivertHelperHtonIPv6Address
WinDivert 2.0.2-rc
WinDivert 2.1.0-rc
- WinDivertOpen() now supports a new flag:
* WINDIVERT_FLAG_FRAGMENTS: If set, the handle will capture inbound IP
fragments, but not inbound reassembled IP packets. Otherwise, if not
set (the default), the handle will capture inbound reassembled IP
packets, but not inbound IP fragments. This flag only affects
inbound packets at the WINDIVERT_LAYER_NETWORK layer.
- Fix BSOD caused by packets with missing or incomplete transport
headers. This bug does not affect WinDivert 1.4.*.
- Fix driver max MTU enforcement.
- Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows.
+13
View File
@@ -1135,6 +1135,19 @@ This flag is useful for querying the WinDivert state using a
<code>WINDIVERT_LAYER_REFLECT</code> handle.
</td>
</tr>
<tr>
<td>
<code>WINDIVERT_FLAG_FRAGMENTS</code>
</td>
<td>
If set, the handle will capture inbound IP fragments, but not inbound
reassembled IP packets.
Otherwise, if not set (the default), the handle will capture inbound
reassembled IP packets, but not inbound IP fragments.
This flag only affects inbound packets at the
<code>WINDIVERT_LAYER_NETWORK</code> layer, else the flag is ignored.
</td>
</tr>
</table>
</center>
<p>
+1 -1
View File
@@ -102,7 +102,7 @@ int __cdecl main(int argc, char **argv)
// Divert traffic matching the filter:
handle = WinDivertOpen(argv[1], WINDIVERT_LAYER_NETWORK, priority,
WINDIVERT_FLAG_SNIFF);
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_FRAGMENTS);
if (handle == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_INVALID_PARAMETER &&
+1
View File
@@ -195,6 +195,7 @@ typedef enum
#define WINDIVERT_FLAG_SEND_ONLY 0x0008
#define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY
#define WINDIVERT_FLAG_NO_INSTALL 0x0010
#define WINDIVERT_FLAG_FRAGMENTS 0x0020
/*
* WinDivert parameters.
+3 -2
View File
@@ -45,7 +45,7 @@
#include "windivert.h"
#define WINDIVERT_VERSION_MAJOR 2
#define WINDIVERT_VERSION_MINOR 0
#define WINDIVERT_VERSION_MINOR 1
#define WINDIVERT_MAGIC_DLL 0x4C4C447669645724ull
#define WINDIVERT_MAGIC_SYS 0x5359537669645723ull
@@ -181,7 +181,8 @@
*/
#define WINDIVERT_FLAGS_ALL \
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_NO_INSTALL)
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_NO_INSTALL | \
WINDIVERT_FLAG_FRAGMENTS)
#define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \
(((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2)))
#define WINDIVERT_FLAGS_VALID(flags) \
+106 -67
View File
@@ -63,35 +63,12 @@ EVT_WDF_WORKITEM windivert_reflect_worker;
* Debugging macros.
*/
// #define DEBUG_ON
#define DEBUG_BUFSIZE 256
#ifdef DEBUG_ON
static void DEBUG(PCCH format, ...)
{
va_list args;
char buf[DEBUG_BUFSIZE+1];
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
return;
}
va_start(args, format);
RtlStringCbVPrintfA(buf, DEBUG_BUFSIZE, format, args);
DbgPrint("WINDIVERT: %s\n", buf);
va_end(args);
}
static void DEBUG_ERROR(PCCH format, NTSTATUS status, ...)
{
va_list args;
char buf[DEBUG_BUFSIZE+1];
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
return;
}
va_start(args, status);
RtlStringCbVPrintfA(buf, DEBUG_BUFSIZE, format, args);
DbgPrint("WINDIVERT: *** ERROR ***: (status = %x): %s\n", status, buf);
va_end(args);
}
#define DEBUG(format, ...) \
DbgPrint("WINDIVERT: " format "\n", ##__VA_ARGS__)
#define DEBUG_ERROR(format, status, ...) \
DbgPrint("WINDIVERT: *** ERROR ***: (status = 0x%x): " format "\n", \
(status), ##__VA_ARGS__)
static void DEBUG_BOUNDS_CHECK(PVOID start, PVOID end, PVOID access_start,
PVOID access_end)
{
@@ -478,7 +455,7 @@ static void windivert_socket_classify(context_t context,
BOOL outbound, BOOL loopback, FWPS_CLASSIFY_OUT0 *result);
static void windivert_network_classify(context_t context,
IN PWINDIVERT_DATA_NETWORK network_data, IN BOOL ipv4, IN BOOL outbound,
IN BOOL loopback, IN UINT advance, IN OUT void *data,
IN BOOL loopback, IN BOOL reassembled, IN UINT advance, IN OUT void *data,
OUT FWPS_CLASSIFY_OUT0 *result);
static BOOL windivert_queue_work(context_t context, PVOID packet,
ULONG packet_len, PNET_BUFFER_LIST buffers, PVOID object,
@@ -494,14 +471,14 @@ static BOOL windivert_copy_data(PNET_BUFFER buffer, PVOID data, UINT size);
static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx,
PVOID data, UINT size);
static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr,
PWINDIVERT_ICMPHDR *icmp_header_ptr,
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr,
PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr,
UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr);
BOOL frag_mode, PWINDIVERT_IPHDR *ip_header_ptr,
PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr,
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr,
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
UINT *payload_len_ptr);
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
const VOID *layer_data, LONGLONG timestamp, WINDIVERT_EVENT event,
BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor, BOOL frag_mode,
const WINDIVERT_FILTER *filter);
static const WINDIVERT_FILTER *windivert_filter_compile(
const WINDIVERT_FILTER *ioctl_filter, size_t ioctl_filter_len,
@@ -3456,7 +3433,8 @@ static void windivert_outbound_network_v4_classify(
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
windivert_network_classify(context, &network_data, /*ipv4=*/TRUE,
/*outbound=*/TRUE, loopback, /*advance=*/0, data, result);
/*outbound=*/TRUE, loopback, /*reassembled=*/FALSE, /*advance=*/0,
data, result);
}
/*
@@ -3490,7 +3468,8 @@ static void windivert_outbound_network_v6_classify(
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
windivert_network_classify(context, &network_data, /*ipv4=*/FALSE,
/*outbound=*/TRUE, loopback, /*advance=*/0, data, result);
/*outbound=*/TRUE, loopback, /*reassembled=*/FALSE, /*advance=*/0,
data, result);
}
/*
@@ -3504,7 +3483,8 @@ static void windivert_inbound_network_v4_classify(
{
WINDIVERT_DATA_NETWORK network_data;
UINT advance;
BOOL loopback;
UINT32 flags;
BOOL fragment, loopback, reassembled;
context_t context = (context_t)(ULONG_PTR)filter->context;
UNREFERENCED_PARAMETER(data);
@@ -3515,14 +3495,21 @@ static void windivert_inbound_network_v4_classify(
return;
}
loopback = ((windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V4_FLAGS) &
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
flags = windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V4_FLAGS);
fragment = ((flags & FWP_CONDITION_FLAG_IS_FRAGMENT) != 0);
if (fragment)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
if (loopback)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
reassembled = ((flags & FWP_CONDITION_FLAG_IS_REASSEMBLED) != 0);
network_data.IfIdx = windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V4_INTERFACE_INDEX);
@@ -3531,7 +3518,7 @@ static void windivert_inbound_network_v4_classify(
advance = meta_vals->ipHeaderSize;
windivert_network_classify(context, &network_data, /*ipv4=*/TRUE,
/*outbound=*/FALSE, loopback, advance, data, result);
/*outbound=*/FALSE, loopback, reassembled, advance, data, result);
}
/*
@@ -3545,7 +3532,8 @@ static void windivert_inbound_network_v6_classify(
{
WINDIVERT_DATA_NETWORK network_data;
UINT advance;
BOOL loopback;
UINT32 flags;
BOOL fragment, loopback, reassembled;
context_t context = (context_t)(ULONG_PTR)filter->context;
UNREFERENCED_PARAMETER(data);
@@ -3556,14 +3544,21 @@ static void windivert_inbound_network_v6_classify(
return;
}
loopback = ((windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V6_FLAGS) &
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
flags = windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V6_FLAGS);
fragment = ((flags & FWP_CONDITION_FLAG_IS_FRAGMENT) != 0);
if (fragment)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
if (loopback)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
reassembled = ((flags & FWP_CONDITION_FLAG_IS_REASSEMBLED) != 0);
network_data.IfIdx = windivert_get_val32(fixed_vals,
FWPS_FIELD_INBOUND_IPPACKET_V6_INTERFACE_INDEX);
@@ -3572,7 +3567,7 @@ static void windivert_inbound_network_v6_classify(
advance = meta_vals->ipHeaderSize;
windivert_network_classify(context, &network_data, /*ipv4=*/FALSE,
/*outbound=*/FALSE, loopback, advance, data, result);
/*outbound=*/FALSE, loopback, reassembled, advance, data, result);
}
/*
@@ -3585,6 +3580,8 @@ static void windivert_forward_network_v4_classify(
OUT FWPS_CLASSIFY_OUT0 *result)
{
WINDIVERT_DATA_NETWORK network_data;
UINT32 flags;
BOOL group;
context_t context = (context_t)(ULONG_PTR)filter->context;
UNREFERENCED_PARAMETER(meta_vals);
@@ -3595,13 +3592,21 @@ static void windivert_forward_network_v4_classify(
{
return;
}
flags = windivert_get_val32(fixed_vals, FWPS_FIELD_IPFORWARD_V4_FLAGS);
group = ((flags & FWP_CONDITION_FLAG_IS_FRAGMENT_GROUP) != 0);
if (group)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
network_data.IfIdx = windivert_get_val32(fixed_vals,
FWPS_FIELD_IPFORWARD_V4_DESTINATION_INTERFACE_INDEX);
network_data.SubIfIdx = 0;
windivert_network_classify(context, &network_data, /*ipv4=*/TRUE,
/*outbound=*/TRUE, /*loopback=*/FALSE, /*advance=*/0, data, result);
/*outbound=*/TRUE, /*loopback=*/FALSE, /*reassembled=*/FALSE,
/*advance=*/0, data, result);
}
/*
@@ -3614,6 +3619,8 @@ static void windivert_forward_network_v6_classify(
OUT FWPS_CLASSIFY_OUT0 *result)
{
WINDIVERT_DATA_NETWORK network_data;
UINT32 flags;
BOOL group;
context_t context = (context_t)(ULONG_PTR)filter->context;
UNREFERENCED_PARAMETER(meta_vals);
@@ -3624,13 +3631,21 @@ static void windivert_forward_network_v6_classify(
{
return;
}
flags = windivert_get_val32(fixed_vals, FWPS_FIELD_IPFORWARD_V6_FLAGS);
group = ((flags & FWP_CONDITION_FLAG_IS_FRAGMENT_GROUP) != 0);
if (group)
{
result->actionType = FWP_ACTION_CONTINUE;
return;
}
network_data.IfIdx = windivert_get_val32(fixed_vals,
FWPS_FIELD_IPFORWARD_V6_DESTINATION_INTERFACE_INDEX);
network_data.SubIfIdx = 0;
windivert_network_classify(context, &network_data, /*ipv4=*/FALSE,
/*outbound=*/TRUE, /*loopback=*/FALSE, /*advance=*/0, data, result);
/*outbound=*/TRUE, /*loopback=*/FALSE, /*reassembled=*/FALSE,
/*advance=*/0, data, result);
}
/*
@@ -3638,7 +3653,7 @@ static void windivert_forward_network_v6_classify(
*/
static void windivert_network_classify(context_t context,
IN PWINDIVERT_DATA_NETWORK network_data, IN BOOL ipv4, IN BOOL outbound,
IN BOOL loopback, IN UINT advance, IN OUT void *data,
IN BOOL loopback, IN BOOL reassembled, IN UINT advance, IN OUT void *data,
OUT FWPS_CLASSIFY_OUT0 *result)
{
KLOCK_QUEUE_HANDLE lock_handle;
@@ -3649,7 +3664,7 @@ static void windivert_network_classify(context_t context,
WINDIVERT_LAYER layer;
PNET_BUFFER_LIST buffers;
PNET_BUFFER buffer, buffer_fst, buffer_itr;
BOOL impostor, sniff_mode, ok;
BOOL impostor, sniff_mode, frag_mode, ok;
WDFOBJECT object;
const WINDIVERT_FILTER *filter;
LONGLONG timestamp;
@@ -3712,6 +3727,16 @@ static void windivert_network_classify(context_t context,
// Get the timestamp.
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
// Filter fragments or reassembled packets.
frag_mode =
(outbound || layer == WINDIVERT_LAYER_NETWORK_FORWARD? TRUE:
(flags & WINDIVERT_FLAG_FRAGMENTS) != 0);
if (frag_mode && reassembled)
{
WdfObjectDereference(object);
return;
}
// Retreat the NET_BUFFER to the IP header, if necessary.
// If (advance != 0) then this must be in the inbound path, and the
// NET_BUFFER_LIST must contain exactly one NET_BUFFER.
@@ -3741,7 +3766,7 @@ static void windivert_network_classify(context_t context,
{
BOOL match = windivert_filter(buffer_fst, layer, (PVOID)network_data,
timestamp, /*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4,
outbound, loopback, impostor, filter);
outbound, loopback, impostor, frag_mode, filter);
if (match)
{
break;
@@ -3806,7 +3831,7 @@ static void windivert_network_classify(context_t context,
{
BOOL match = windivert_filter(buffer_itr, layer, (PVOID)network_data,
timestamp, /*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4,
outbound, loopback, impostor, filter);
outbound, loopback, impostor, frag_mode, filter);
ok = windivert_queue_work(context, (PVOID)buffer_itr,
NET_BUFFER_DATA_LENGTH(buffer_itr), buffers, /*object=*/NULL, layer,
(PVOID)network_data, /*event=*/WINDIVERT_EVENT_NETWORK_PACKET,
@@ -3972,7 +3997,7 @@ static void windivert_flow_established_classify(context_t context,
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
(PVOID)flow_data, timestamp,
/*event=*/WINDIVERT_EVENT_FLOW_ESTABLISHED, ipv4, outbound, loopback,
/*impostor=*/FALSE, filter);
/*impostor=*/FALSE, /*frag_mode=*/FALSE, filter);
if (match)
{
ok = windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
@@ -4096,7 +4121,7 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
(PVOID)&flow->data, timestamp, /*event=*/WINDIVERT_EVENT_FLOW_DELETED,
!flow->ipv6, flow->outbound, flow->loopback, /*impostor=*/FALSE,
filter);
/*frag_mode=*/FALSE, filter);
if (match)
{
(VOID)windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
@@ -4688,7 +4713,7 @@ static void windivert_socket_classify(context_t context,
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_SOCKET,
(PVOID)socket_data, timestamp, event, ipv4, outbound, loopback,
/*impostor=*/FALSE, filter);
/*impostor=*/FALSE, /*frag_mode=*/FALSE, filter);
if (match)
{
ok = windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
@@ -5258,11 +5283,11 @@ static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx,
* Parse packet headers.
*/
static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr,
PWINDIVERT_ICMPHDR *icmp_header_ptr,
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr,
PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr,
UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr)
BOOL frag_mode, PWINDIVERT_IPHDR *ip_header_ptr,
PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr,
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr,
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
UINT *payload_len_ptr)
{
UINT tot_len, ip_header_len;
PWINDIVERT_IPHDR ip_header = NULL;
@@ -5313,6 +5338,13 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
DEBUG("FILTER: REJECT (bad IPv4 packet)");
return FALSE;
}
if (!frag_mode &&
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
{
DEBUG("FILTER: REJECT (fragment)");
return FALSE;
}
proto = ip_header->Protocol;
NdisAdvanceNetBufferDataStart(buffer, ip_header_len, FALSE, NULL);
}
@@ -5360,6 +5392,11 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
switch (proto)
{
case IPPROTO_FRAGMENT:
if (!frag_mode)
{
DEBUG("FILTER: REJECT (fragment)");
return FALSE;
}
ext_header_len = 8;
break;
case IPPROTO_AH:
@@ -5444,7 +5481,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
*/
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
const VOID *layer_data, LONGLONG timestamp, WINDIVERT_EVENT event,
BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor, BOOL frag_mode,
const WINDIVERT_FILTER *filter)
{
PWINDIVERT_IPHDR ip_header = NULL;
@@ -5469,9 +5506,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
{
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (!windivert_parse_headers(buffer, ipv4, &ip_header, &ipv6_header,
&icmp_header, &icmpv6_header, &tcp_header, &udp_header,
&protocol, &header_len, &payload_len))
if (!windivert_parse_headers(buffer, ipv4, frag_mode, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, &protocol, &header_len, &payload_len))
{
return FALSE;
}
@@ -6763,7 +6800,8 @@ static void windivert_reflect_event_notify(context_t context,
match = windivert_filter(/*buffer=*/NULL,
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&context->reflect.data,
timestamp, event, /*ipv4=*/TRUE, /*outbound=*/FALSE,
/*loopback=*/FALSE, /*impostor=*/FALSE, filter);
/*loopback=*/FALSE, /*impostor=*/FALSE, /*frag_mode=*/FALSE,
filter);
if (!match)
{
continue;
@@ -6813,7 +6851,8 @@ static void windivert_reflect_established_notify(context_t context,
match = windivert_filter(/*buffer=*/NULL,
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&waiter->reflect.data,
timestamp, /*event=*/WINDIVERT_EVENT_REFLECT_OPEN, /*ipv4=*/TRUE,
/*outbound=*/FALSE, /*loopback=*/FALSE, /*impostor=*/FALSE, filter);
/*outbound=*/FALSE, /*loopback=*/FALSE, /*impostor=*/FALSE,
/*frag_mode=*/FALSE, filter);
if (!match)
{
continue;
+2 -2
View File
@@ -43,8 +43,8 @@
"[Bitcoin: 1C5vZVSbizPeZ8ydTYhUfm4LA2cNwBfcYh]"
#define VER_INTERNALNAME_STR "WinDivert.sys"
#define VER_ORIGINALFILENAME_STR "WinDivert.sys"
#define VER_PRODUCTVERSION 2.0
#define VER_PRODUCTVERSION_STR "2.0"
#define VER_PRODUCTVERSION 2.1
#define VER_PRODUCTVERSION_STR "2.1"
#define VER_COMPANYNAME_STR "Basil"
#define VER_LEGALCOPYRIGHT_YEARS "2011-2019"
#define VER_LEGALCOPYRIGHT_STR \