Skip to content

Commit 194d9af

Browse files
committed
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.
1 parent 69e4eda commit 194d9af

File tree

9 files changed

+59
-39
lines changed

9 files changed

+59
-39
lines changed

CHANGELOG

+4-3
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,14 @@ WinDivert 2.0.1-rc
297297
- Rename the following functions for consistency:
298298
* WinDivertHelperNtohIpv6Address -> WinDivertHelperNtohIPv6Address
299299
* WinDivertHelperHtonIpv6Address -> WinDivertHelperHtonIPv6Address
300-
WinDivert 2.1.0-rc
300+
WinDivert 2.1.0
301301
- WinDivertOpen() now supports a new flag:
302302
* WINDIVERT_FLAG_FRAGMENTS: If set, the handle will capture inbound IP
303303
fragments, but not inbound reassembled IP packets. Otherwise, if not
304304
set (the default), the handle will capture inbound reassembled IP
305305
packets, but not inbound IP fragments. This flag only affects
306-
inbound packets at the WINDIVERT_LAYER_NETWORK layer.
306+
inbound packets at the NETWORK layer.
307+
- Filter fields inbound/outbound are now supported at the SOCKET layer.
307308
- Fix BSOD caused by packets with missing or incomplete transport
308-
headers. This bug does not affect WinDivert 1.4.*.
309+
headers (introduced in 2.0.0).
309310
- Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows.

README

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
WinDivert 2.0: Windows Packet Divert
1+
WinDivert 2.1: Windows Packet Divert
22
====================================
33

44
1. Introduction

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.2-rc
1+
2.1.0

dll/windivert_helper.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,6 @@ typedef struct
217217
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \
218218
WINDIVERT_LAYER_FLAG_FLOW | \
219219
WINDIVERT_LAYER_FLAG_SOCKET)
220-
#define LN_F__ (WINDIVERT_LAYER_FLAG_NETWORK | \
221-
WINDIVERT_LAYER_FLAG_FLOW)
222220
#define L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \
223221
WINDIVERT_LAYER_FLAG_REFLECT)
224222
#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
@@ -625,7 +623,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
625623
{"icmpv6.Type", TOKEN_ICMPV6_TYPE, LNM___},
626624
{"ifIdx", TOKEN_IF_IDX, LNM___},
627625
{"impostor", TOKEN_IMPOSTOR, LNM___},
628-
{"inbound", TOKEN_INBOUND, LN_F__},
626+
{"inbound", TOKEN_INBOUND, LN_FS_},
629627
{"ip", TOKEN_IP, LNMFS_},
630628
{"ip.Checksum", TOKEN_IP_CHECKSUM, LNM___},
631629
{"ip.DF", TOKEN_IP_DF, LNM___},
@@ -654,7 +652,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
654652
{"loopback", TOKEN_LOOPBACK, LN_FS_},
655653
{"not", TOKEN_NOT, LNMFSR},
656654
{"or", TOKEN_OR, LNMFSR},
657-
{"outbound", TOKEN_OUTBOUND, LN_F__},
655+
{"outbound", TOKEN_OUTBOUND, LN_FS_},
658656
{"packet", TOKEN_PACKET, LNM___},
659657
{"packet16", TOKEN_PACKET16, LNM___},
660658
{"packet32", TOKEN_PACKET32, LNM___},

doc/windivert.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<!doctype html>
22
<html lang="en">
33
<head>
4-
<title>WinDivert 2.0 Documentation</title>
4+
<title>WinDivert 2.1 Documentation</title>
55
<meta charset="UTF-8"/>
66
</head>
77
<body>
8-
<h1>WinDivert 2.0: Windows Packet Divert</h1>
8+
<h1>WinDivert 2.1: Windows Packet Divert</h1>
99
<h2>Table of Contents</h2>
1010
<ul>
1111
<li><a href="#introduction">1. Introduction</a></li>

examples/passthru/passthru.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ int __cdecl main(int argc, char **argv)
147147
static DWORD passthru(LPVOID arg)
148148
{
149149
UINT8 *packet;
150-
UINT packet_len, addr_len;
150+
UINT packet_len, recv_len, addr_len;
151151
WINDIVERT_ADDRESS *addr;
152152
PCONFIG config = (PCONFIG)arg;
153153
HANDLE handle;
@@ -156,7 +156,10 @@ static DWORD passthru(LPVOID arg)
156156
handle = config->handle;
157157
batch = config->batch;
158158

159-
packet = (UINT8 *)malloc(batch * MTU);
159+
packet_len = batch * MTU;
160+
packet_len =
161+
(packet_len < WINDIVERT_MTU_MAX? WINDIVERT_MTU_MAX: packet_len);
162+
packet = (UINT8 *)malloc(packet_len);
160163
addr = (WINDIVERT_ADDRESS *)malloc(batch * sizeof(WINDIVERT_ADDRESS));
161164
if (packet == NULL || addr == NULL)
162165
{
@@ -169,9 +172,8 @@ static DWORD passthru(LPVOID arg)
169172
while (TRUE)
170173
{
171174
// Read a matching packet.
172-
packet_len = batch * MTU;
173-
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
174-
if (!WinDivertRecvEx(handle, packet, packet_len, &packet_len, 0,
175+
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
176+
if (!WinDivertRecvEx(handle, packet, packet_len, &recv_len, 0,
175177
addr, &addr_len, NULL))
176178
{
177179
fprintf(stderr, "warning: failed to read packet (%d)\n",
@@ -180,7 +182,7 @@ static DWORD passthru(LPVOID arg)
180182
}
181183

182184
// Re-inject the matching packet.
183-
if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
185+
if (!WinDivertSendEx(handle, packet, recv_len, NULL, 0, addr,
184186
addr_len, NULL))
185187
{
186188
fprintf(stderr, "warning: failed to reinject packet (%d)\n",

inf/windivert32.inf

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
44
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
55
Provider = %Basil%
66
CatalogFile = WinDivert32.Cat
7-
DriverVer = 01/01/2019,2.0.0
7+
DriverVer = 08/08/2019,2.1.0
88

99
[SourceDisksNames]
1010
1 = %DiskName%

inf/windivert64.inf

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
44
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
55
Provider = %Basil%
66
CatalogFile = WinDivert64.Cat
7-
DriverVer = 01/01/2019,2.0.0
7+
DriverVer = 08/08/2019,2.1.0
88

99
[SourceDisksNames]
1010
1 = %DiskName%

sys/windivert.c

+39-20
Original file line numberDiff line numberDiff line change
@@ -2168,6 +2168,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
21682168
addr[i].TCPChecksum = packet->tcp_checksum;
21692169
addr[i].UDPChecksum = packet->udp_checksum;
21702170
addr[i].Reserved1 = 0;
2171+
addr[i].Reserved2 = 0;
21712172
layer_data = (PVOID)packet->data;
21722173
switch (packet->layer)
21732174
{
@@ -2371,6 +2372,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
23712372
addr->TCPChecksum = (tcp_checksum? 1: 0);
23722373
addr->UDPChecksum = (udp_checksum? 1: 0);
23732374
addr->Reserved1 = 0;
2375+
addr->Reserved2 = 0;
23742376
switch (layer)
23752377
{
23762378
case WINDIVERT_LAYER_NETWORK:
@@ -4180,7 +4182,7 @@ static void windivert_resource_assignment_v4_classify(
41804182

41814183
windivert_socket_classify(context, &socket_data,
41824184
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/TRUE,
4183-
/*outbound=*/FALSE, loopback, result);
4185+
/*outbound=*/TRUE, loopback, result);
41844186
}
41854187

41864188
/*
@@ -4223,7 +4225,7 @@ static void windivert_resource_assignment_v6_classify(
42234225

42244226
windivert_socket_classify(context, &socket_data,
42254227
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/FALSE,
4226-
/*outbound=*/FALSE, loopback, result);
4228+
/*outbound=*/TRUE, loopback, result);
42274229
}
42284230

42294231
/*
@@ -4261,7 +4263,7 @@ static void windivert_resource_release_v4_classify(
42614263

42624264
windivert_socket_classify(context, &socket_data,
42634265
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE,
4264-
/*outbound=*/FALSE, loopback, result);
4266+
/*outbound=*/TRUE, loopback, result);
42654267
}
42664268

42674269
/*
@@ -4299,7 +4301,7 @@ static void windivert_resource_release_v6_classify(
42994301

43004302
windivert_socket_classify(context, &socket_data,
43014303
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE,
4302-
/*outbound=*/FALSE, loopback, result);
4304+
/*outbound=*/TRUE, loopback, result);
43034305
}
43044306

43054307
/*
@@ -4527,7 +4529,7 @@ static void windivert_auth_listen_v4_classify(
45274529

45284530
windivert_socket_classify(context, &socket_data,
45294531
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/TRUE,
4530-
/*outbound=*/FALSE, loopback, result);
4532+
/*outbound=*/TRUE, loopback, result);
45314533
}
45324534

45334535
/*
@@ -4569,7 +4571,7 @@ static void windivert_auth_listen_v6_classify(
45694571

45704572
windivert_socket_classify(context, &socket_data,
45714573
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/FALSE,
4572-
/*outbound=*/FALSE, loopback, result);
4574+
/*outbound=*/TRUE, loopback, result);
45734575
}
45744576

45754577
/*
@@ -5289,7 +5291,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
52895291
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
52905292
UINT *payload_len_ptr)
52915293
{
5292-
UINT tot_len, ip_header_len;
5294+
UINT total_len, ip_header_len = 0;
52935295
PWINDIVERT_IPHDR ip_header = NULL;
52945296
PWINDIVERT_IPV6HDR ipv6_header = NULL;
52955297
PWINDIVERT_ICMPHDR icmp_header = NULL;
@@ -5306,8 +5308,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53065308
DEBUG("FILTER: REJECT (packet is NULL)");
53075309
return FALSE;
53085310
}
5309-
tot_len = NET_BUFFER_DATA_LENGTH(buffer);
5310-
if (tot_len < sizeof(WINDIVERT_IPHDR))
5311+
total_len = NET_BUFFER_DATA_LENGTH(buffer);
5312+
if (total_len < sizeof(WINDIVERT_IPHDR))
53115313
{
53125314
DEBUG("FILTER: REJECT (packet length too small)");
53135315
return FALSE;
@@ -5317,7 +5319,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53175319
if (ipv4)
53185320
{
53195321
// IPv4:
5320-
if (tot_len < sizeof(WINDIVERT_IPHDR))
5322+
if (total_len < sizeof(WINDIVERT_IPHDR))
53215323
{
53225324
DEBUG("FILTER: REJECT (packet length too small)");
53235325
return FALSE;
@@ -5331,14 +5333,14 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53315333
}
53325334
ip_header_len = ip_header->HdrLength*sizeof(UINT32);
53335335
if (ip_header->Version != 4 ||
5334-
RtlUshortByteSwap(ip_header->Length) != tot_len ||
5336+
RtlUshortByteSwap(ip_header->Length) != total_len ||
53355337
ip_header->HdrLength < 5 ||
5336-
ip_header_len > tot_len)
5338+
ip_header_len > total_len)
53375339
{
53385340
DEBUG("FILTER: REJECT (bad IPv4 packet)");
53395341
return FALSE;
53405342
}
5341-
if (!frag_mode &&
5343+
if (!frag_mode &&
53425344
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
53435345
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
53445346
{
@@ -5351,7 +5353,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53515353
else
53525354
{
53535355
// IPv6:
5354-
if (tot_len < sizeof(WINDIVERT_IPV6HDR))
5356+
if (total_len < sizeof(WINDIVERT_IPV6HDR))
53555357
{
53565358
DEBUG("FILTER: REJECT (packet length too small)");
53575359
return FALSE;
@@ -5365,9 +5367,9 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53655367
}
53665368
ip_header_len = sizeof(WINDIVERT_IPV6HDR);
53675369
if (ipv6_header->Version != 6 ||
5368-
ip_header_len > tot_len ||
5370+
ip_header_len > total_len ||
53695371
RtlUshortByteSwap(ipv6_header->Length) +
5370-
sizeof(WINDIVERT_IPV6HDR) != tot_len)
5372+
sizeof(WINDIVERT_IPV6HDR) != total_len)
53715373
{
53725374
DEBUG("FILTER: REJECT (bad IPv6 packet)");
53735375
return FALSE;
@@ -5395,6 +5397,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
53955397
if (!frag_mode)
53965398
{
53975399
DEBUG("FILTER: REJECT (fragment)");
5400+
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
5401+
0, NULL);
53985402
return FALSE;
53995403
}
54005404
ext_header_len = 8;
@@ -5420,6 +5424,13 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
54205424
}
54215425

54225426
proto = ext_header[0];
5427+
if (ip_header_len + ext_header_len > total_len)
5428+
{
5429+
DEBUG("FILTER: REJECT (bad IPv6 extension header)");
5430+
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
5431+
0, NULL);
5432+
return FALSE;
5433+
}
54235434
ip_header_len += ext_header_len;
54245435
NdisAdvanceNetBufferDataStart(buffer, ext_header_len, FALSE,
54255436
NULL);
@@ -5443,8 +5454,17 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
54435454
case IPPROTO_TCP:
54445455
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
54455456
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
5446-
header_len +=
5447-
(tcp_header == NULL? 0: tcp_header->HdrLength*sizeof(UINT32));
5457+
if (tcp_header != NULL)
5458+
{
5459+
UINT tcp_header_len = tcp_header->HdrLength * sizeof(UINT32);
5460+
if (header_len + tcp_header_len > total_len)
5461+
{
5462+
// Bad TCP options:
5463+
tcp_header = NULL;
5464+
break;
5465+
}
5466+
header_len += tcp_header_len;
5467+
}
54485468
break;
54495469
case IPPROTO_UDP:
54505470
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
@@ -5454,7 +5474,6 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
54545474
default:
54555475
break;
54565476
}
5457-
54585477
status = NdisRetreatNetBufferDataStart(buffer, ip_header_len, 0, NULL);
54595478
if (!NT_SUCCESS(status))
54605479
{
@@ -5471,7 +5490,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
54715490
*udp_header_ptr = udp_header;
54725491
*proto_ptr = proto;
54735492
*header_len_ptr = header_len;
5474-
*payload_len_ptr = (header_len > tot_len? 0: tot_len - header_len);
5493+
*payload_len_ptr = total_len - header_len;
54755494

54765495
return TRUE;
54775496
}

0 commit comments

Comments
 (0)