Towards WinDivert version 2.1 release.
- inbounds/outbound now work for SOCKET layer. - passthru.exe now uses MTU_MAX to prevent 122 errors. - Further header parsing code hardening. - Fix bug where Reserved2 was not zeroed.
This commit is contained in:
@@ -297,13 +297,14 @@ WinDivert 2.0.1-rc
|
||||
- Rename the following functions for consistency:
|
||||
* WinDivertHelperNtohIpv6Address -> WinDivertHelperNtohIPv6Address
|
||||
* WinDivertHelperHtonIpv6Address -> WinDivertHelperHtonIPv6Address
|
||||
WinDivert 2.1.0-rc
|
||||
WinDivert 2.1.0
|
||||
- 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.
|
||||
inbound packets at the NETWORK layer.
|
||||
- Filter fields inbound/outbound are now supported at the SOCKET layer.
|
||||
- Fix BSOD caused by packets with missing or incomplete transport
|
||||
headers. This bug does not affect WinDivert 1.4.*.
|
||||
headers (introduced in 2.0.0).
|
||||
- Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
WinDivert 2.0: Windows Packet Divert
|
||||
WinDivert 2.1: Windows Packet Divert
|
||||
====================================
|
||||
|
||||
1. Introduction
|
||||
|
||||
@@ -217,8 +217,6 @@ typedef struct
|
||||
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \
|
||||
WINDIVERT_LAYER_FLAG_FLOW | \
|
||||
WINDIVERT_LAYER_FLAG_SOCKET)
|
||||
#define LN_F__ (WINDIVERT_LAYER_FLAG_NETWORK | \
|
||||
WINDIVERT_LAYER_FLAG_FLOW)
|
||||
#define L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \
|
||||
WINDIVERT_LAYER_FLAG_REFLECT)
|
||||
#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
|
||||
@@ -625,7 +623,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"icmpv6.Type", TOKEN_ICMPV6_TYPE, LNM___},
|
||||
{"ifIdx", TOKEN_IF_IDX, LNM___},
|
||||
{"impostor", TOKEN_IMPOSTOR, LNM___},
|
||||
{"inbound", TOKEN_INBOUND, LN_F__},
|
||||
{"inbound", TOKEN_INBOUND, LN_FS_},
|
||||
{"ip", TOKEN_IP, LNMFS_},
|
||||
{"ip.Checksum", TOKEN_IP_CHECKSUM, LNM___},
|
||||
{"ip.DF", TOKEN_IP_DF, LNM___},
|
||||
@@ -654,7 +652,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"loopback", TOKEN_LOOPBACK, LN_FS_},
|
||||
{"not", TOKEN_NOT, LNMFSR},
|
||||
{"or", TOKEN_OR, LNMFSR},
|
||||
{"outbound", TOKEN_OUTBOUND, LN_F__},
|
||||
{"outbound", TOKEN_OUTBOUND, LN_FS_},
|
||||
{"packet", TOKEN_PACKET, LNM___},
|
||||
{"packet16", TOKEN_PACKET16, LNM___},
|
||||
{"packet32", TOKEN_PACKET32, LNM___},
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>WinDivert 2.0 Documentation</title>
|
||||
<title>WinDivert 2.1 Documentation</title>
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WinDivert 2.0: Windows Packet Divert</h1>
|
||||
<h1>WinDivert 2.1: Windows Packet Divert</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#introduction">1. Introduction</a></li>
|
||||
|
||||
@@ -147,7 +147,7 @@ int __cdecl main(int argc, char **argv)
|
||||
static DWORD passthru(LPVOID arg)
|
||||
{
|
||||
UINT8 *packet;
|
||||
UINT packet_len, addr_len;
|
||||
UINT packet_len, recv_len, addr_len;
|
||||
WINDIVERT_ADDRESS *addr;
|
||||
PCONFIG config = (PCONFIG)arg;
|
||||
HANDLE handle;
|
||||
@@ -156,7 +156,10 @@ static DWORD passthru(LPVOID arg)
|
||||
handle = config->handle;
|
||||
batch = config->batch;
|
||||
|
||||
packet = (UINT8 *)malloc(batch * MTU);
|
||||
packet_len = batch * MTU;
|
||||
packet_len =
|
||||
(packet_len < WINDIVERT_MTU_MAX? WINDIVERT_MTU_MAX: packet_len);
|
||||
packet = (UINT8 *)malloc(packet_len);
|
||||
addr = (WINDIVERT_ADDRESS *)malloc(batch * sizeof(WINDIVERT_ADDRESS));
|
||||
if (packet == NULL || addr == NULL)
|
||||
{
|
||||
@@ -169,9 +172,8 @@ static DWORD passthru(LPVOID arg)
|
||||
while (TRUE)
|
||||
{
|
||||
// Read a matching packet.
|
||||
packet_len = batch * MTU;
|
||||
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
|
||||
if (!WinDivertRecvEx(handle, packet, packet_len, &packet_len, 0,
|
||||
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
|
||||
if (!WinDivertRecvEx(handle, packet, packet_len, &recv_len, 0,
|
||||
addr, &addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to read packet (%d)\n",
|
||||
@@ -180,7 +182,7 @@ static DWORD passthru(LPVOID arg)
|
||||
}
|
||||
|
||||
// Re-inject the matching packet.
|
||||
if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
|
||||
if (!WinDivertSendEx(handle, packet, recv_len, NULL, 0, addr,
|
||||
addr_len, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
|
||||
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
|
||||
Provider = %Basil%
|
||||
CatalogFile = WinDivert32.Cat
|
||||
DriverVer = 01/01/2019,2.0.0
|
||||
DriverVer = 08/08/2019,2.1.0
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
|
||||
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
|
||||
Provider = %Basil%
|
||||
CatalogFile = WinDivert64.Cat
|
||||
DriverVer = 01/01/2019,2.0.0
|
||||
DriverVer = 08/08/2019,2.1.0
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%
|
||||
|
||||
+39
-20
@@ -2168,6 +2168,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
|
||||
addr[i].TCPChecksum = packet->tcp_checksum;
|
||||
addr[i].UDPChecksum = packet->udp_checksum;
|
||||
addr[i].Reserved1 = 0;
|
||||
addr[i].Reserved2 = 0;
|
||||
layer_data = (PVOID)packet->data;
|
||||
switch (packet->layer)
|
||||
{
|
||||
@@ -2371,6 +2372,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
addr->TCPChecksum = (tcp_checksum? 1: 0);
|
||||
addr->UDPChecksum = (udp_checksum? 1: 0);
|
||||
addr->Reserved1 = 0;
|
||||
addr->Reserved2 = 0;
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -4180,7 +4182,7 @@ static void windivert_resource_assignment_v4_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/TRUE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4223,7 +4225,7 @@ static void windivert_resource_assignment_v6_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/FALSE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4261,7 +4263,7 @@ static void windivert_resource_release_v4_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4299,7 +4301,7 @@ static void windivert_resource_release_v6_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4527,7 +4529,7 @@ static void windivert_auth_listen_v4_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/TRUE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4569,7 +4571,7 @@ static void windivert_auth_listen_v6_classify(
|
||||
|
||||
windivert_socket_classify(context, &socket_data,
|
||||
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/FALSE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5289,7 +5291,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
|
||||
UINT *payload_len_ptr)
|
||||
{
|
||||
UINT tot_len, ip_header_len;
|
||||
UINT total_len, ip_header_len = 0;
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6_header = NULL;
|
||||
PWINDIVERT_ICMPHDR icmp_header = NULL;
|
||||
@@ -5306,8 +5308,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
DEBUG("FILTER: REJECT (packet is NULL)");
|
||||
return FALSE;
|
||||
}
|
||||
tot_len = NET_BUFFER_DATA_LENGTH(buffer);
|
||||
if (tot_len < sizeof(WINDIVERT_IPHDR))
|
||||
total_len = NET_BUFFER_DATA_LENGTH(buffer);
|
||||
if (total_len < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
DEBUG("FILTER: REJECT (packet length too small)");
|
||||
return FALSE;
|
||||
@@ -5317,7 +5319,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
if (ipv4)
|
||||
{
|
||||
// IPv4:
|
||||
if (tot_len < sizeof(WINDIVERT_IPHDR))
|
||||
if (total_len < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
DEBUG("FILTER: REJECT (packet length too small)");
|
||||
return FALSE;
|
||||
@@ -5331,14 +5333,14 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
}
|
||||
ip_header_len = ip_header->HdrLength*sizeof(UINT32);
|
||||
if (ip_header->Version != 4 ||
|
||||
RtlUshortByteSwap(ip_header->Length) != tot_len ||
|
||||
RtlUshortByteSwap(ip_header->Length) != total_len ||
|
||||
ip_header->HdrLength < 5 ||
|
||||
ip_header_len > tot_len)
|
||||
ip_header_len > total_len)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (bad IPv4 packet)");
|
||||
return FALSE;
|
||||
}
|
||||
if (!frag_mode &&
|
||||
if (!frag_mode &&
|
||||
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
|
||||
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
|
||||
{
|
||||
@@ -5351,7 +5353,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
else
|
||||
{
|
||||
// IPv6:
|
||||
if (tot_len < sizeof(WINDIVERT_IPV6HDR))
|
||||
if (total_len < sizeof(WINDIVERT_IPV6HDR))
|
||||
{
|
||||
DEBUG("FILTER: REJECT (packet length too small)");
|
||||
return FALSE;
|
||||
@@ -5365,9 +5367,9 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
}
|
||||
ip_header_len = sizeof(WINDIVERT_IPV6HDR);
|
||||
if (ipv6_header->Version != 6 ||
|
||||
ip_header_len > tot_len ||
|
||||
ip_header_len > total_len ||
|
||||
RtlUshortByteSwap(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR) != tot_len)
|
||||
sizeof(WINDIVERT_IPV6HDR) != total_len)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (bad IPv6 packet)");
|
||||
return FALSE;
|
||||
@@ -5395,6 +5397,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
if (!frag_mode)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (fragment)");
|
||||
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
|
||||
0, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
ext_header_len = 8;
|
||||
@@ -5420,6 +5424,13 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
}
|
||||
|
||||
proto = ext_header[0];
|
||||
if (ip_header_len + ext_header_len > total_len)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (bad IPv6 extension header)");
|
||||
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
|
||||
0, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
ip_header_len += ext_header_len;
|
||||
NdisAdvanceNetBufferDataStart(buffer, ext_header_len, FALSE,
|
||||
NULL);
|
||||
@@ -5443,8 +5454,17 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
|
||||
header_len +=
|
||||
(tcp_header == NULL? 0: tcp_header->HdrLength*sizeof(UINT32));
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
UINT tcp_header_len = tcp_header->HdrLength * sizeof(UINT32);
|
||||
if (header_len + tcp_header_len > total_len)
|
||||
{
|
||||
// Bad TCP options:
|
||||
tcp_header = NULL;
|
||||
break;
|
||||
}
|
||||
header_len += tcp_header_len;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
|
||||
@@ -5454,7 +5474,6 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
status = NdisRetreatNetBufferDataStart(buffer, ip_header_len, 0, NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
@@ -5471,7 +5490,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
*udp_header_ptr = udp_header;
|
||||
*proto_ptr = proto;
|
||||
*header_len_ptr = header_len;
|
||||
*payload_len_ptr = (header_len > tot_len? 0: tot_len - header_len);
|
||||
*payload_len_ptr = total_len - header_len;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user