Various WinDivert improvements.
- Add UNBIND/DISCONNECT events to the SOCKET layer. These events can only be sniffed. - Remove the RECV_PARTIAL flag. The user application can just ignore the error code instead. - WINDIVERT_ADDRESS is now 64bytes. Some extra padding added for future-proofing. - Ignore SOCKET-layer REAUTHORIZE. - The REFLECT layer returns the filter object directly (no IPv4 "pseudo" packet).
This commit is contained in:
@@ -167,10 +167,15 @@ WinDivert 2.0.0-rc
|
||||
deleted.
|
||||
* WINDIVERT_EVENT_SOCKET_BIND: (SOCKET layer) a socket bind()
|
||||
operation occurred.
|
||||
* WINDIVERT_EVENT_SOCKET_LISTEN: (SOCKET layer) a socket listen()
|
||||
* WINDIVERT_EVENT_SOCKET_UNBIND: (SOCKET layer) a previous binding
|
||||
is removed.
|
||||
operation occurred.
|
||||
* WINDIVERT_EVENT_SOCKET_CONNECT: (SOCKET layer) a socket connect()
|
||||
operation occurred.
|
||||
* WINDIVERT_EVENT_SOCKET_DISCONNECT: (SOCKET layer) a previous
|
||||
connection is terminated.
|
||||
* WINDIVERT_EVENT_SOCKET_LISTEN: (SOCKET layer) a socket listen()
|
||||
operation occurred.
|
||||
* WINDIVERT_EVENT_SOCKET_ACCEPT: (SOCKET layer) a socket accept()
|
||||
operation occurred.
|
||||
* WINDIVERT_EVENT_REFLECT_OPEN: (REFLECT layer) a WinDivertOpen()
|
||||
@@ -217,28 +222,29 @@ WinDivert 2.0.0-rc
|
||||
packet/payload.
|
||||
* Negative, representing addressing from the end of the packet/payload.
|
||||
- The WinDivert filter language now supports several symbolic values:
|
||||
* ACCEPT: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_ACCEPT.
|
||||
* BIND: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_BIND.
|
||||
* CLOSE: (REFLECT layer) equal to WINDIVERT_EVENT_REFLECT_CLOSE.
|
||||
* DELETED: (FLOW LAYER) equal to WINDIVERT_EVENT_FLOW_DELETED.
|
||||
* ESTABLISHED: (FLOW layer) equal to WINDIVERT_EVENT_FLOW_ESTABLISHED.
|
||||
* FLOW: (REFLECT layer) equal to WINDIVERT_LAYER_FLOW.
|
||||
* LISTEN: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_LISTEN.
|
||||
* NETWORK: (REFLECT layer) equal to WINDIVERT_LAYER_NETWORK.
|
||||
* NETWORK_FORWARD: (REFLECT layer) equal to
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD.
|
||||
* OPEN: (REFLECT layer) equal to WINDIVERT_EVENT_REFLECT_OPEN.
|
||||
* PACKET: (NETWORK/NETWORK_FORWARD layers) equal to
|
||||
WINDIVERT_EVENT_NETWORK_PACKET
|
||||
* REFLECT: (REFLECT layer) equal to WINDIVERT_LAYER_REFLECT.
|
||||
* ESTABLISHED: (FLOW layer) equal to WINDIVERT_EVENT_FLOW_ESTABLISHED.
|
||||
* DELETED: (FLOW LAYER) equal to WINDIVERT_EVENT_FLOW_DELETED.
|
||||
* BIND: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_BIND.
|
||||
* UNBIND: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_UNBIND.
|
||||
* CONNECT: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_CONNECT.
|
||||
* DISCONNECT: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_DISCONNECT.
|
||||
* LISTEN: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_LISTEN.
|
||||
* ACCEPT: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_ACCEPT.
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD.
|
||||
* OPEN: (REFLECT layer) equal to WINDIVERT_EVENT_REFLECT_OPEN.
|
||||
* CLOSE: (REFLECT layer) equal to WINDIVERT_EVENT_REFLECT_CLOSE.
|
||||
* NETWORK: (REFLECT layer) equal to WINDIVERT_LAYER_NETWORK.
|
||||
* NETWORK_FORWARD: (REFLECT layer) equal to
|
||||
* FLOW: (REFLECT layer) equal to WINDIVERT_LAYER_FLOW.
|
||||
* SOCKET: (REFLECT layer) equal to WINDIVERT_LAYER_SOCKET.
|
||||
* REFLECT: (REFLECT layer) equal to WINDIVERT_LAYER_REFLECT.
|
||||
- WinDivertOpen() now supports several new flags:
|
||||
* WINDIVERT_FLAG_RECV_ONLY/WINDIVERT_FLAG_READ_ONLY: The handle cannot
|
||||
be used for send operations.
|
||||
* WINDIVERT_FLAG_SEND_ONLY/WINDIVERT_FLAG_WRITE_ONLY: The handle cannot
|
||||
be used for receive operations.
|
||||
* WINDIVERT_FLAG_RECV_PARTIAL: The handle will support partial receives,
|
||||
meaning that the buffer can be smaller than the packet.
|
||||
* WINDIVERT_FLAG_NO_INSTALL: If the WinDivert driver is not already
|
||||
installed/loaded, then WinDivertOpen() will fail with an error.
|
||||
- WinDivertRecvEx()/WinDivertSendEx() now support a "batch" mode that
|
||||
|
||||
+3
-1
@@ -365,6 +365,7 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
UINT obj_len;
|
||||
ERROR comp_err;
|
||||
DWORD err;
|
||||
BOOL sniff;
|
||||
HANDLE handle;
|
||||
SC_HANDLE service;
|
||||
UINT64 filter_flags;
|
||||
@@ -404,7 +405,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
filter_flags = WinDivertAnalyzeFilter(layer, object, obj_len);
|
||||
sniff = ((flags & WINDIVERT_FLAG_SNIFF) != 0);
|
||||
filter_flags = WinDivertAnalyzeFilter(layer, sniff, object, obj_len);
|
||||
|
||||
// Attempt to open the WinDivert device:
|
||||
handle = CreateFile(L"\\\\.\\" WINDIVERT_DEVICE_NAME,
|
||||
|
||||
+31
-1
@@ -147,7 +147,9 @@ typedef enum
|
||||
TOKEN_EVENT_ESTABLISHED,
|
||||
TOKEN_EVENT_DELETED,
|
||||
TOKEN_EVENT_BIND,
|
||||
TOKEN_EVENT_UNBIND,
|
||||
TOKEN_EVENT_CONNECT,
|
||||
TOKEN_EVENT_DISCONNECT,
|
||||
TOKEN_EVENT_LISTEN,
|
||||
TOKEN_EVENT_ACCEPT,
|
||||
TOKEN_EVENT_OPEN,
|
||||
@@ -514,9 +516,15 @@ static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer,
|
||||
case TOKEN_EVENT_BIND:
|
||||
*val = WINDIVERT_EVENT_SOCKET_BIND;
|
||||
return (layer == WINDIVERT_LAYER_SOCKET);
|
||||
case TOKEN_EVENT_UNBIND:
|
||||
*val = WINDIVERT_EVENT_SOCKET_UNBIND;
|
||||
return (layer == WINDIVERT_LAYER_SOCKET);
|
||||
case TOKEN_EVENT_CONNECT:
|
||||
*val = WINDIVERT_EVENT_SOCKET_CONNECT;
|
||||
return (layer == WINDIVERT_LAYER_SOCKET);
|
||||
case TOKEN_EVENT_DISCONNECT:
|
||||
*val = WINDIVERT_EVENT_SOCKET_DISCONNECT;
|
||||
return (layer == WINDIVERT_LAYER_SOCKET);
|
||||
case TOKEN_EVENT_LISTEN:
|
||||
*val = WINDIVERT_EVENT_SOCKET_LISTEN;
|
||||
return (layer == WINDIVERT_LAYER_SOCKET);
|
||||
@@ -547,6 +555,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"CLOSE", TOKEN_EVENT_CLOSE, L____R},
|
||||
{"CONNECT", TOKEN_EVENT_CONNECT, L___S_},
|
||||
{"DELETED", TOKEN_EVENT_DELETED, L__F__},
|
||||
{"DISCONNECT", TOKEN_EVENT_DISCONNECT, L___S_},
|
||||
{"ESTABLISHED", TOKEN_EVENT_ESTABLISHED, L__F__},
|
||||
{"FLOW", TOKEN_FLOW, L____R},
|
||||
{"LISTEN", TOKEN_EVENT_LISTEN, L___S_},
|
||||
@@ -556,6 +565,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"PACKET", TOKEN_EVENT_PACKET, LNM___},
|
||||
{"REFLECT", TOKEN_REFLECT, L____R},
|
||||
{"SOCKET", TOKEN_SOCKET, L____R},
|
||||
{"UNBIND", TOKEN_EVENT_UNBIND, L___S_},
|
||||
{"and", TOKEN_AND, LNMFSR},
|
||||
{"event", TOKEN_EVENT, LNMFSR},
|
||||
{"false", TOKEN_FALSE, LNMFSR},
|
||||
@@ -1968,7 +1978,7 @@ static void WinDivertEmitFilter(PEXPR *stack, UINT len, UINT16 label,
|
||||
* Analyze a filter object.
|
||||
*/
|
||||
static UINT64 WinDivertAnalyzeFilter(WINDIVERT_LAYER layer,
|
||||
PWINDIVERT_FILTER filter, UINT length)
|
||||
BOOL sniff, PWINDIVERT_FILTER filter, UINT length)
|
||||
{
|
||||
BOOL result;
|
||||
UINT64 flags = 0;
|
||||
@@ -2041,9 +2051,25 @@ static UINT64 WinDivertAnalyzeFilter(WINDIVERT_LAYER layer,
|
||||
result = WinDivertCondExecFilter(filter, length,
|
||||
WINDIVERT_FILTER_FIELD_EVENT, WINDIVERT_EVENT_SOCKET_BIND);
|
||||
flags |= (result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND: 0);
|
||||
if (sniff)
|
||||
{
|
||||
result = WinDivertCondExecFilter(filter, length,
|
||||
WINDIVERT_FILTER_FIELD_EVENT,
|
||||
WINDIVERT_EVENT_SOCKET_UNBIND);
|
||||
flags |=
|
||||
(result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_UNBIND: 0);
|
||||
}
|
||||
result = WinDivertCondExecFilter(filter, length,
|
||||
WINDIVERT_FILTER_FIELD_EVENT, WINDIVERT_EVENT_SOCKET_CONNECT);
|
||||
flags |= (result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT: 0);
|
||||
if (sniff)
|
||||
{
|
||||
result = WinDivertCondExecFilter(filter, length,
|
||||
WINDIVERT_FILTER_FIELD_EVENT,
|
||||
WINDIVERT_EVENT_SOCKET_DISCONNECT);
|
||||
flags |=
|
||||
(result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_DISCONNECT: 0);
|
||||
}
|
||||
result = WinDivertCondExecFilter(filter, length,
|
||||
WINDIVERT_FILTER_FIELD_EVENT, WINDIVERT_EVENT_SOCKET_LISTEN);
|
||||
flags |= (result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN: 0);
|
||||
@@ -4210,8 +4236,12 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
{
|
||||
case WINDIVERT_EVENT_SOCKET_BIND:
|
||||
WinDivertPutString(stream, "BIND"); break;
|
||||
case WINDIVERT_EVENT_SOCKET_UNBIND:
|
||||
WinDivertPutString(stream, "UNBIND"); break;
|
||||
case WINDIVERT_EVENT_SOCKET_CONNECT:
|
||||
WinDivertPutString(stream, "CONNECT"); break;
|
||||
case WINDIVERT_EVENT_SOCKET_DISCONNECT:
|
||||
WinDivertPutString(stream, "DISCONNECT"); break;
|
||||
case WINDIVERT_EVENT_SOCKET_LISTEN:
|
||||
WinDivertPutString(stream, "LISTEN"); break;
|
||||
case WINDIVERT_EVENT_SOCKET_ACCEPT:
|
||||
|
||||
+25
-29
@@ -401,14 +401,19 @@ correspond to socket operations, such as:
|
||||
</p>
|
||||
<ul>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_BIND</code>: A <code>bind()</code> operation.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_LISTEN</code>: A <code>listen()</code> operation.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_UNBIND</code>: A previous binding is
|
||||
removed.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_CONNECT</code>: A <code>connect()</code>
|
||||
operation.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_DISCONNECT</code>: A previous connection
|
||||
is terminated.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_LISTEN</code>: A <code>listen()</code> operation.</li>
|
||||
<li> <code>WINDIVERT_EVENT_SOCKET_ACCEPT</code>: An <code>accept()</code>
|
||||
operation.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Socket events can be blocked but not injected.
|
||||
Socket events, except for <code>UNBIND</code>/<code>DISCONNECT</code>,
|
||||
can be blocked, and no socket event can be injected.
|
||||
Process ID information is available at this layer.
|
||||
Due to technical limitations, the
|
||||
<code>WINDIVERT_LAYER_SOCKET</code> layer cannot capture events that
|
||||
@@ -429,8 +434,12 @@ These events can be captured, but not injected nor blocked.
|
||||
Process ID information is available at this layer,
|
||||
meaning that it is possible to determine which (if any) process is using
|
||||
WinDivert.
|
||||
The layer also returns a <q>pseudo packet</q> that encodes the filter string
|
||||
associated with the event.
|
||||
The layer also returns an <q>object</q> representation of the filter string
|
||||
used to open the handle.
|
||||
The object representation can be converted back into a human-readable
|
||||
filter string using the
|
||||
<a href="#divert_helper_format_filter"><code>WinDivertHelperFormatFilter()</code></a>
|
||||
function.
|
||||
The <code>WINDIVERT_LAYER_REFLECT</code> layer can also capture events that
|
||||
occurred before the handle was opened.
|
||||
</p>
|
||||
@@ -626,7 +635,7 @@ fields form the network 5-tuple associated with the operation.
|
||||
For IPv4, the <code>Socket.LocalAddr</code> and <code>Socket.RemoteAddr</code>
|
||||
fields will be IPv4-mapped IPv6 addresses.
|
||||
The <code>WINDIVERT_EVENT_SOCKET_BIND</code> and
|
||||
<code>WINDIVERT_EVENT_SOCKET_LISTEN</code> events will occur before a
|
||||
<code>WINDIVERT_EVENT_SOCKET_LISTEN</code> events can occur before a
|
||||
connection attempt has been made, meaning that the
|
||||
<code>Socket.RemoteAddr</code> and <code>Socket.RemotePort</code> fields
|
||||
for these events will be zero.
|
||||
@@ -955,21 +964,6 @@ An alias for <code>WINDIVERT_FLAG_SEND_ONLY</code>.
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>WINDIVERT_FLAG_RECV_PARTIAL</code>
|
||||
</td>
|
||||
<td>
|
||||
This flags enables <q>partial receives</q>.
|
||||
By default, if a packet is too big for the buffer passed to
|
||||
<a href="#divert_recv"><code>WinDivertRecv()</code></a>, the operation
|
||||
will fail with <code>ERROR_INSUFFICIENT_BUFFER</code>.
|
||||
This flag silences this error and only copies part of the packet
|
||||
up to the buffer size.
|
||||
The <code>WINDIVERT_FLAG_RECV_PARTIAL</code> behavior was the default
|
||||
on older (pre-2.0) versions of WinDivert.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>WINDIVERT_FLAG_NO_INSTALL</code>
|
||||
</td>
|
||||
<td>
|
||||
@@ -985,8 +979,7 @@ This flag is useful for querying the WinDivert state using a
|
||||
<p>
|
||||
Note that any combination of
|
||||
<code>(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP)</code> or
|
||||
<code>(WINDIVERT_FLAG_RECV_ONLY | WINDIVERT_FLAG_SEND_ONLY)</code> or
|
||||
<code>(WINDIVERT_FLAG_RECV_PARTIAL | WINDIVERT_FLAG_SEND_ONLY)</code>
|
||||
<code>(WINDIVERT_FLAG_RECV_ONLY | WINDIVERT_FLAG_SEND_ONLY)</code>
|
||||
are considered invalid.
|
||||
</p>
|
||||
<p>
|
||||
@@ -1165,10 +1158,11 @@ For layers that do support capturing, the captured packet will be written to
|
||||
the <code>pPacket</code> buffer.
|
||||
If non-<code>NULL</code>, then the total number of bytes
|
||||
written to <code>pPacket</code> will be written to <code>recvLen</code>.
|
||||
Partial receives (where the packet data is truncated) is supported provided
|
||||
the handle was opened with the <code>WINDIVERT_FLAG_RECV_PARTIAL</code> flag set,
|
||||
otherwise the operation will fail with <code>ERROR_INSUFFICIENT_BUFFER</code>
|
||||
if the <code>pPacket</code> buffer is too small.
|
||||
If the <code>pPacket</code> buffer is too small, the packet will be
|
||||
truncated and the operation will fail with the
|
||||
<code>ERROR_INSUFFICIENT_BUFFER</code> error code.
|
||||
This error can be ignored if the application only intends to receive part
|
||||
of the packet, e.g., the IP headers only.
|
||||
For layers that do not capture packets, the <code>pPacket</code> parameter
|
||||
should be <code>NULL</code> and <code>packetLen</code> should be zero.
|
||||
</p><p>
|
||||
@@ -2372,8 +2366,8 @@ Formats the given filter string or object.
|
||||
This function is mainly useful for <q>decompiling</q> the filter object
|
||||
representation back into a human-readable filter string representation.
|
||||
One application is the <code>WINDIVERT_LAYER_REFLECT</code> layer,
|
||||
where a <q>pseudo packet</q> containing a filter object is returned by
|
||||
<a href="#divert_recv"><code>WinDivertRecv()</code></a>.
|
||||
where the filter object associated with the reflection event is
|
||||
returned by <a href="#divert_recv"><code>WinDivertRecv()</code></a>.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -2635,9 +2629,11 @@ The possible macros are:
|
||||
<tr><td><code>PACKET</code></td><td>✔</td><td>✔</td><td></td><td></td><td></td><td><code>WINDIVERT_EVENT_NETWORK_PACKET</code></td></tr>
|
||||
<tr><td><code>ESTABLISHED</code></td><td></td><td></td><td>✔</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_ESTABLISHED</code></td></tr>
|
||||
<tr><td><code>DELETED</code></td><td></td><td></td><td>✔</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_DELETED</code></td></tr>
|
||||
<tr><td><code>ACCEPT</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_ACCEPT</code></td></tr>
|
||||
<tr><td><code>BIND</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_BIND</code></td></tr>
|
||||
<tr><td><code>UNBIND</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_UNBIND</code></td></tr>
|
||||
<tr><td><code>CONNECT</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_CONNECT</code></td></tr>
|
||||
<tr><td><code>DISCONNECT</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_DISCONNECT</code></td></tr>
|
||||
<tr><td><code>ACCEPT</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_ACCEPT</code></td></tr>
|
||||
<tr><td><code>LISTEN</code></td><td></td><td></td><td></td><td>✔</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_LISTEN</code></td></tr>
|
||||
<tr><td><code>OPEN</code></td><td></td><td></td><td></td><td></td><td>✔</td><td><code>WINDIVERT_EVENT_REFLECT_OPEN</code></td></tr>
|
||||
<tr><td><code>CLOSE</code></td><td></td><td></td><td></td><td></td><td>✔</td><td><code>WINDIVERT_EVENT_REFLECT_CLOSE</code></td></tr>
|
||||
|
||||
@@ -103,22 +103,34 @@ int __cdecl main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_SOCKET_BIND:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("BIND");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_UNBIND:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("UNBIND");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_LISTEN:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("LISTEN");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_CONNECT:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("CONNECT");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_DISCONNECT:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("DISCONNECT");
|
||||
break;
|
||||
case WINDIVERT_EVENT_SOCKET_ACCEPT:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("ACCEPT");
|
||||
break;
|
||||
default:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_BLUE);
|
||||
printf("???");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,6 @@ int __cdecl main(int argc, char **argv)
|
||||
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;
|
||||
@@ -369,11 +368,6 @@ usage:
|
||||
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? "|": ""));
|
||||
@@ -389,9 +383,7 @@ usage:
|
||||
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, NULL, &object, NULL, NULL, NULL);
|
||||
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
|
||||
if (WinDivertHelperFormatFilter((char *)packet, addr.Reflect.Layer,
|
||||
filter_str, sizeof(filter_str)))
|
||||
{
|
||||
printf("\"%s\"", filter_str);
|
||||
|
||||
+10
-7
@@ -143,13 +143,14 @@ typedef struct
|
||||
UINT64 IPChecksum:1; /* Packet has valid IPv4 checksum? */
|
||||
UINT64 TCPChecksum:1; /* Packet has valid TCP checksum? */
|
||||
UINT64 UDPChecksum:1; /* Packet has valid UDP checksum? */
|
||||
UINT64 Reserved:41;
|
||||
UINT64 Reserved1: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. */
|
||||
UINT8 Reserved2[48];
|
||||
};
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
|
||||
@@ -163,11 +164,14 @@ typedef enum
|
||||
/* 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_UNBIND = 4, /* Socket unbind. */
|
||||
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_SOCKET_DISCONNECT = 6,
|
||||
/* Socket disconnect. */
|
||||
WINDIVERT_EVENT_SOCKET_LISTEN = 7, /* Socket listen. */
|
||||
WINDIVERT_EVENT_SOCKET_ACCEPT = 8, /* Socket accept. */
|
||||
WINDIVERT_EVENT_REFLECT_OPEN = 9, /* WinDivert handle opened. */
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE = 10, /* WinDivert handle closed. */
|
||||
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
|
||||
|
||||
/*
|
||||
@@ -179,8 +183,7 @@ typedef enum
|
||||
#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
|
||||
#define WINDIVERT_FLAG_NO_INSTALL 0x0010
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
|
||||
@@ -177,8 +177,7 @@
|
||||
*/
|
||||
#define WINDIVERT_FLAGS_ALL \
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_RECV_PARTIAL | \
|
||||
WINDIVERT_FLAG_NO_INSTALL)
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_NO_INSTALL)
|
||||
#define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \
|
||||
(((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2)))
|
||||
#define WINDIVERT_FLAGS_VALID(flags) \
|
||||
@@ -186,8 +185,6 @@
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_SNIFF, \
|
||||
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))
|
||||
|
||||
/*
|
||||
@@ -199,16 +196,21 @@
|
||||
#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_FLAG_EVENT_SOCKET_UNBIND 0x0000000000000040ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT 0x0000000000000080ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_DISCONNECT \
|
||||
0x0000000000000100ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN 0x0000000000000200ull
|
||||
#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT 0x0000000000000800ull
|
||||
|
||||
#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_UNBIND | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_DISCONNECT | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN | \
|
||||
WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT)
|
||||
|
||||
|
||||
+399
-78
@@ -129,7 +129,7 @@ struct reflect_context_s
|
||||
* WinDivert context information.
|
||||
*/
|
||||
#define WINDIVERT_CONTEXT_SIZE (sizeof(struct context_s))
|
||||
#define WINDIVERT_CONTEXT_MAXLAYERS 8
|
||||
#define WINDIVERT_CONTEXT_MAXLAYERS 12
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_CONTEXT_STATE_OPENING = 0xA0, // Context is opening.
|
||||
@@ -408,6 +408,16 @@ static void windivert_resource_assignment_v6_classify(
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_resource_release_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_resource_release_v6_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_auth_connect_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
@@ -418,6 +428,16 @@ static void windivert_auth_connect_v6_classify(
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_endpoint_closure_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_endpoint_closure_v6_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result);
|
||||
static void windivert_auth_listen_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
@@ -516,12 +536,24 @@ DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV4_GUID,
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV6_GUID,
|
||||
0xF3458E58, 0xD123, 0x439B,
|
||||
0xB6, 0x40, 0x74, 0x3C, 0xC7, 0x53, 0x9E, 0x36);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV4_GUID,
|
||||
0x02366282, 0x9099, 0x43A7,
|
||||
0x95, 0xC3, 0xAB, 0x52, 0x87, 0xB3, 0xF2, 0xDC);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV6_GUID,
|
||||
0x60FCA14A, 0x7677, 0x45D2,
|
||||
0xBB, 0x5C, 0x15, 0xDB, 0xAE, 0x4B, 0x7B, 0x6B);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV4_GUID,
|
||||
0x2F97411F, 0x6350, 0x450A,
|
||||
0xBF, 0x45, 0x4C, 0x0B, 0xC1, 0xDB, 0x3F, 0x7E);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV6_GUID,
|
||||
0x7BAFEEEB, 0x84F0, 0x4BB0,
|
||||
0x91, 0x1F, 0x7E, 0x62, 0x2D, 0x73, 0x24, 0x2C);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV4_GUID,
|
||||
0x8180D216, 0xB3BD, 0x4014,
|
||||
0x99, 0x69, 0xA3, 0xDF, 0x0F, 0x3E, 0x61, 0x85);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV6_GUID,
|
||||
0x2535A264, 0xEC8B, 0x49CC,
|
||||
0xA4, 0xD6, 0x83, 0x81, 0xD7, 0x5F, 0xAB, 0xE6);
|
||||
DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV4_GUID,
|
||||
0x49F2A9AD, 0x805E, 0x4328,
|
||||
0xBB, 0xDA, 0x92, 0x57, 0xB5, 0x18, 0x3A, 0x40);
|
||||
@@ -674,6 +706,40 @@ static const struct layer_s windivert_layer_resource_assignment_ipv6 =
|
||||
#define WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV6 \
|
||||
(&windivert_layer_resource_assignment_ipv6)
|
||||
|
||||
static const struct layer_s windivert_layer_resource_release_ipv4 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerResourceReleaseIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" sublayer resource release (IPv4)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_CalloutResourceReleaseIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" callout resource release (IPv4)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_FilterResourceReleaseIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" filter resource release (IPv4)",
|
||||
&FWPM_LAYER_ALE_RESOURCE_RELEASE_V4,
|
||||
&WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV4_GUID,
|
||||
windivert_resource_release_v4_classify,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
#define WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4 \
|
||||
(&windivert_layer_resource_release_ipv4)
|
||||
|
||||
static const struct layer_s windivert_layer_resource_release_ipv6 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerResourceReleaseIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" sublayer resource release (IPv6)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_CalloutResourceReleaseIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" callout resource release (IPv6)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_FilterResourceReleaseIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" filter resource release (IPv6)",
|
||||
&FWPM_LAYER_ALE_RESOURCE_RELEASE_V6,
|
||||
&WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV6_GUID,
|
||||
windivert_resource_release_v6_classify,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
#define WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6 \
|
||||
(&windivert_layer_resource_release_ipv6)
|
||||
|
||||
static const struct layer_s windivert_layer_auth_connect_ipv4 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerAuthConnectIPv4",
|
||||
@@ -708,6 +774,40 @@ static const struct layer_s windivert_layer_auth_connect_ipv6 =
|
||||
#define WINDIVERT_LAYER_AUTH_CONNECT_IPV6 \
|
||||
(&windivert_layer_auth_connect_ipv6)
|
||||
|
||||
static const struct layer_s windivert_layer_endpoint_closure_ipv4 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerEndpointClosureIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" sublayer endpoint closure (IPv4)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_CalloutEndpointClosureIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" callout endpoint closure (IPv4)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_FilterEndpointClosureIPv4",
|
||||
L"" WINDIVERT_LAYER_NAME L" filter endpoint closure (IPv4)",
|
||||
&FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V4,
|
||||
&WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV4_GUID,
|
||||
windivert_endpoint_closure_v4_classify,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
#define WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4 \
|
||||
(&windivert_layer_endpoint_closure_ipv4)
|
||||
|
||||
static const struct layer_s windivert_layer_endpoint_closure_ipv6 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerEndpointClosureIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" sublayer endpoint closure (IPv6)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_CalloutEndpointClosureIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" callout endpoint closure (IPv6)",
|
||||
L"" WINDIVERT_LAYER_NAME L"_FilterEndpointClosureIPv6",
|
||||
L"" WINDIVERT_LAYER_NAME L" filter endpoint closure (IPv6)",
|
||||
&FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V6,
|
||||
&WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV6_GUID,
|
||||
windivert_endpoint_closure_v6_classify,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
#define WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6 \
|
||||
(&windivert_layer_endpoint_closure_ipv6)
|
||||
|
||||
static const struct layer_s windivert_layer_auth_listen_ipv4 =
|
||||
{
|
||||
L"" WINDIVERT_LAYER_NAME L"_SubLayerAuthListenIPv4",
|
||||
@@ -1072,6 +1172,16 @@ driver_entry_sublayer_error:
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_AUTH_CONNECT_IPV4);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
@@ -1082,6 +1192,16 @@ driver_entry_sublayer_error:
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
goto driver_entry_sublayer_error;
|
||||
}
|
||||
status = windivert_install_sublayer(WINDIVERT_LAYER_AUTH_LISTEN_IPV4);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
@@ -1187,10 +1307,18 @@ static void windivert_driver_unload(void)
|
||||
WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV4->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV6->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_AUTH_CONNECT_IPV4->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_AUTH_CONNECT_IPV6->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
WINDIVERT_LAYER_AUTH_LISTEN_IPV4->sublayer_guid);
|
||||
FwpmSubLayerDeleteByKey0(engine_handle,
|
||||
@@ -1266,6 +1394,7 @@ extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
|
||||
context->shutdown_recv_enabled = FALSE;
|
||||
context->shutdown_send = FALSE;
|
||||
context->priority = 0;
|
||||
context->priority16 = 0;
|
||||
context->filter = NULL;
|
||||
context->filter_len = 0;
|
||||
context->filter_flags = 0;
|
||||
@@ -1356,17 +1485,20 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
|
||||
UINT8 i, j;
|
||||
layer_t layers[WINDIVERT_CONTEXT_MAXLAYERS];
|
||||
UINT32 *callout_ids[WINDIVERT_CONTEXT_MAXLAYERS] = {NULL};
|
||||
BOOL inbound, outbound, ipv4, ipv6, bind, connect, listen, accept;
|
||||
BOOL inbound, outbound, ipv4, ipv6, bind, unbind, connect, disconnect,
|
||||
listen, accept;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
|
||||
outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
|
||||
ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
|
||||
ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
|
||||
bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
|
||||
connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
|
||||
listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
|
||||
accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
|
||||
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
|
||||
outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
|
||||
ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
|
||||
ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
|
||||
bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
|
||||
unbind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_UNBIND) != 0);
|
||||
connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
|
||||
disconnect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_DISCONNECT) != 0);
|
||||
listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
|
||||
accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
|
||||
|
||||
i = 0;
|
||||
switch (layer)
|
||||
@@ -1419,10 +1551,18 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV4;
|
||||
}
|
||||
if (ipv4 && unbind)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4;
|
||||
}
|
||||
if (ipv4 && connect)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_AUTH_CONNECT_IPV4;
|
||||
}
|
||||
if (ipv4 && disconnect)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4;
|
||||
}
|
||||
if (ipv4 && listen)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_AUTH_LISTEN_IPV4;
|
||||
@@ -1435,10 +1575,18 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV6;
|
||||
}
|
||||
if (ipv6 && unbind)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6;
|
||||
}
|
||||
if (ipv6 && connect)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_AUTH_CONNECT_IPV6;
|
||||
}
|
||||
if (ipv6 && disconnect)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6;
|
||||
}
|
||||
if (ipv6 && listen)
|
||||
{
|
||||
layers[i++] = WINDIVERT_LAYER_AUTH_LISTEN_IPV6;
|
||||
@@ -1899,7 +2047,7 @@ static NTSTATUS windivert_read(context_t context, WDFREQUEST request)
|
||||
* WinDivert service a single read request.
|
||||
*/
|
||||
static void windivert_read_service_request(context_t context, packet_t packet,
|
||||
BOOL partial, LONGLONG timestamp, WDFREQUEST request)
|
||||
LONGLONG timestamp, WDFREQUEST request)
|
||||
{
|
||||
KLOCK_QUEUE_HANDLE lock_handle;
|
||||
PLIST_ENTRY entry;
|
||||
@@ -1989,7 +2137,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
|
||||
packet);
|
||||
}
|
||||
src_len = packet->packet_len;
|
||||
if (!partial && src_len > dst_len)
|
||||
if (src_len > dst_len)
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
@@ -2017,7 +2165,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
|
||||
addr[i].IPChecksum = packet->ip_checksum;
|
||||
addr[i].TCPChecksum = packet->tcp_checksum;
|
||||
addr[i].UDPChecksum = packet->udp_checksum;
|
||||
addr[i].Reserved = 0;
|
||||
addr[i].Reserved1 = 0;
|
||||
layer_data = (PVOID)packet->data;
|
||||
switch (packet->layer)
|
||||
{
|
||||
@@ -2175,8 +2323,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
{
|
||||
RtlCopyMemory(dst, src, dst_len);
|
||||
}
|
||||
if ((flags & WINDIVERT_FLAG_RECV_PARTIAL) == 0 &&
|
||||
dst_len < packet_len)
|
||||
if (dst_len < packet_len)
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
@@ -2226,7 +2373,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
addr->IPChecksum = (ip_checksum? 1: 0);
|
||||
addr->TCPChecksum = (tcp_checksum? 1: 0);
|
||||
addr->UDPChecksum = (udp_checksum? 1: 0);
|
||||
addr->Reserved = 0;
|
||||
addr->Reserved1 = 0;
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -2273,7 +2420,7 @@ static void windivert_read_service(context_t context)
|
||||
WDFREQUEST request;
|
||||
PLIST_ENTRY entry;
|
||||
LONGLONG timestamp;
|
||||
BOOL partial, timeout;
|
||||
BOOL timeout;
|
||||
NTSTATUS status;
|
||||
packet_t packet;
|
||||
req_context_t req_context;
|
||||
@@ -2281,7 +2428,6 @@ static void windivert_read_service(context_t context)
|
||||
|
||||
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
partial = ((context->flags & WINDIVERT_FLAG_RECV_PARTIAL) != 0);
|
||||
while (context->state == WINDIVERT_CONTEXT_STATE_OPEN &&
|
||||
!IsListEmpty(&context->packet_queue))
|
||||
{
|
||||
@@ -2303,8 +2449,7 @@ static void windivert_read_service(context_t context)
|
||||
context->packet_queue_size -= packet->packet_len;
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
|
||||
windivert_read_service_request(context, packet, partial, timestamp,
|
||||
request);
|
||||
windivert_read_service_request(context, packet, timestamp, request);
|
||||
|
||||
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
@@ -2669,7 +2814,6 @@ VOID windivert_caller_context(IN WDFDEVICE device, IN WDFREQUEST request)
|
||||
addr_len_ptr, sizeof(UINT), &memobj);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DEBUG_ERROR("invalid address length pointer for RECV ioctl",
|
||||
status);
|
||||
goto windivert_caller_context_error;
|
||||
@@ -3911,6 +4055,11 @@ static void windivert_resource_assignment_v4_classify(
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_ADDRESS,
|
||||
@@ -3943,6 +4092,11 @@ static void windivert_resource_assignment_v6_classify(
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_ADDRESS,
|
||||
@@ -3963,6 +4117,70 @@ static void windivert_resource_assignment_v6_classify(
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert classify resource release IPv4 function.
|
||||
*/
|
||||
static void windivert_resource_release_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_ADDRESS,
|
||||
socket_data.LocalAddr);
|
||||
RtlZeroMemory(&socket_data.RemoteAddr, sizeof(socket_data.RemoteAddr));
|
||||
socket_data.LocalPort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_PORT);
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_UNBIND, /*ipv4=*/TRUE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert classify resource release IPv6 function.
|
||||
*/
|
||||
static void windivert_resource_release_v6_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V6_IP_LOCAL_ADDRESS,
|
||||
socket_data.LocalAddr);
|
||||
RtlZeroMemory(&socket_data.RemoteAddr, sizeof(socket_data.RemoteAddr));
|
||||
socket_data.LocalPort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V6_IP_LOCAL_PORT);
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V6_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_RESOURCE_RELEASE_V6_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_UNBIND, /*ipv4=*/FALSE,
|
||||
/*outbound=*/FALSE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert classify auth connect IPv4 function.
|
||||
*/
|
||||
@@ -3973,8 +4191,21 @@ static void windivert_auth_connect_v4_classify(
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
UINT32 flags;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
flags = windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V4_FLAGS);
|
||||
if ((flags & FWP_CONDITION_FLAG_IS_REAUTHORIZE) != 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS,
|
||||
@@ -3989,9 +4220,7 @@ static void windivert_auth_connect_v4_classify(
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V4_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CONNECT, /*ipv4=*/TRUE,
|
||||
@@ -4008,8 +4237,21 @@ static void windivert_auth_connect_v6_classify(
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
UINT32 flags;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
flags = windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V6_FLAGS);
|
||||
if ((flags & FWP_CONDITION_FLAG_IS_REAUTHORIZE) != 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_LOCAL_ADDRESS,
|
||||
@@ -4024,15 +4266,84 @@ static void windivert_auth_connect_v6_classify(
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_CONNECT_V6_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CONNECT, /*ipv4=*/FALSE,
|
||||
/*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert classify endpoint closure IPv4 function.
|
||||
*/
|
||||
static void windivert_endpoint_closure_v4_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_LOCAL_ADDRESS,
|
||||
socket_data.LocalAddr);
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_REMOTE_ADDRESS,
|
||||
socket_data.RemoteAddr);
|
||||
socket_data.LocalPort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_LOCAL_PORT);
|
||||
socket_data.RemotePort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_REMOTE_PORT);
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_DISCONNECT,
|
||||
/*ipv4=*/TRUE, /*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert classify endpoint closure IPv6 function.
|
||||
*/
|
||||
static void windivert_endpoint_closure_v6_classify(
|
||||
IN const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
|
||||
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_LOCAL_ADDRESS,
|
||||
socket_data.LocalAddr);
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_REMOTE_ADDRESS,
|
||||
socket_data.RemoteAddr);
|
||||
socket_data.LocalPort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_LOCAL_PORT);
|
||||
socket_data.RemotePort = windivert_get_val16(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_REMOTE_PORT);
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_DISCONNECT,
|
||||
/*ipv4=*/FALSE, /*outbound=*/TRUE, loopback, result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WinDivert classify auth listen IPv4 function.
|
||||
*/
|
||||
@@ -4045,6 +4356,11 @@ static void windivert_auth_listen_v4_classify(
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_ADDRESS,
|
||||
@@ -4076,6 +4392,11 @@ static void windivert_auth_listen_v6_classify(
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_ADDRESS,
|
||||
@@ -4105,8 +4426,21 @@ static void windivert_auth_recv_accept_v4_classify(
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
UINT32 flags;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
flags = windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_FLAGS);
|
||||
if ((flags & FWP_CONDITION_FLAG_IS_REAUTHORIZE) != 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv4_addr(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_ADDRESS,
|
||||
@@ -4121,9 +4455,7 @@ static void windivert_auth_recv_accept_v4_classify(
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_ACCEPT, /*ipv4=*/TRUE,
|
||||
@@ -4140,7 +4472,20 @@ static void windivert_auth_recv_accept_v6_classify(
|
||||
OUT FWPS_CLASSIFY_OUT0 *result)
|
||||
{
|
||||
WINDIVERT_DATA_SOCKET socket_data;
|
||||
UINT32 flags;
|
||||
BOOL loopback;
|
||||
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
flags = windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_FLAGS);
|
||||
if ((flags & FWP_CONDITION_FLAG_IS_REAUTHORIZE) != 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
return;
|
||||
}
|
||||
|
||||
socket_data.ProcessId = (UINT32)meta_vals->processId;
|
||||
windivert_get_ipv6_addr(fixed_vals,
|
||||
@@ -4156,9 +4501,7 @@ static void windivert_auth_recv_accept_v6_classify(
|
||||
socket_data.Protocol = windivert_get_val8(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_PROTOCOL);
|
||||
|
||||
loopback = ((windivert_get_val32(fixed_vals,
|
||||
FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_FLAGS) &
|
||||
FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
loopback = ((flags & FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
|
||||
|
||||
windivert_socket_classify((context_t)filter->context,
|
||||
&socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_ACCEPT, /*ipv4=*/FALSE,
|
||||
@@ -4180,16 +4523,13 @@ static void windivert_socket_classify(context_t context,
|
||||
LONGLONG timestamp;
|
||||
NTSTATUS status;
|
||||
|
||||
// Basic checks:
|
||||
if (!(result->rights & FWPS_RIGHT_ACTION_WRITE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the timestamp.
|
||||
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) != 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_CONTINUE;
|
||||
}
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
|
||||
@@ -4221,7 +4561,10 @@ static void windivert_socket_classify(context_t context,
|
||||
}
|
||||
|
||||
WdfObjectDereference(object);
|
||||
if ((flags & WINDIVERT_FLAG_SNIFF) == 0)
|
||||
if ((result->rights & FWPS_RIGHT_ACTION_WRITE) != 0 &&
|
||||
event != WINDIVERT_EVENT_SOCKET_UNBIND &&
|
||||
event != WINDIVERT_EVENT_SOCKET_DISCONNECT &&
|
||||
(flags & WINDIVERT_FLAG_SNIFF) == 0)
|
||||
{
|
||||
result->actionType = FWP_ACTION_BLOCK;
|
||||
result->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
|
||||
@@ -4906,7 +5249,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 = tot_len - header_len;
|
||||
*payload_len_ptr = (header_len > tot_len? 0: tot_len - header_len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -5976,7 +6319,7 @@ windivert_filter_compile_error:
|
||||
/* WINDIVERT REFLECT MANAGER IMPLEMENTATION */
|
||||
/****************************************************************************/
|
||||
|
||||
#define WINDIVERT_REFLECT_PSEUDO_PACKET_MAX 12288
|
||||
#define WINDIVERT_REFLECT_PACKET_MAX 12288
|
||||
|
||||
/*
|
||||
* WinDivert reflect state.
|
||||
@@ -5989,7 +6332,7 @@ static LIST_ENTRY reflect_contexts; // All open (non-REFLECT) contexts.
|
||||
static LIST_ENTRY reflect_waiters; // All open REFLECT contexts.
|
||||
static WDFWORKITEM reflect_worker; // Reflect work item.
|
||||
#pragma data_seg(push, stack, "PAGE")
|
||||
static UINT8 reflect_pseudo_packet[WINDIVERT_REFLECT_PSEUDO_PACKET_MAX];
|
||||
static UINT8 reflect_packet[WINDIVERT_REFLECT_PACKET_MAX];
|
||||
#pragma data_seg(pop, stack)
|
||||
|
||||
/*
|
||||
@@ -6095,31 +6438,19 @@ static void windivert_reflect_close_event(context_t context)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create REFLECT layer "pseudo" packet to pass the filter.
|
||||
* Create REFLECT layer packet to pass the filter.
|
||||
*/
|
||||
static PWINDIVERT_IPHDR windivert_reflect_pseudo_packet(context_t context,
|
||||
ULONG *len_ptr)
|
||||
static PVOID windivert_reflect_packet(context_t context, ULONG *len_ptr)
|
||||
{
|
||||
KLOCK_QUEUE_HANDLE lock_handle;
|
||||
UINT16 total_len;
|
||||
UINT8 *packet;
|
||||
char *object;
|
||||
const WINDIVERT_FILTER *filter;
|
||||
UINT16 filter_len;
|
||||
PWINDIVERT_IPHDR iphdr;
|
||||
WINDIVERT_STREAM stream;
|
||||
|
||||
// The filter is returned in a pseudo-IP packet. This is just to make
|
||||
// the interface consistent, i.e., WinDivertRecv() always receives IP
|
||||
// packets.
|
||||
|
||||
packet = reflect_pseudo_packet;
|
||||
iphdr = (PWINDIVERT_IPHDR)packet;
|
||||
object = (char *)(iphdr + 1);
|
||||
|
||||
stream.data = object;
|
||||
stream.data = reflect_packet;
|
||||
stream.pos = 0;
|
||||
stream.max = sizeof(reflect_pseudo_packet) - sizeof(WINDIVERT_IPHDR);
|
||||
stream.max = sizeof(reflect_packet) - 1;
|
||||
stream.overflow = FALSE;
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
@@ -6128,18 +6459,8 @@ static PWINDIVERT_IPHDR windivert_reflect_pseudo_packet(context_t context,
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
|
||||
WinDivertSerializeFilter(&stream, filter, (UINT8)filter_len);
|
||||
|
||||
total_len = sizeof(WINDIVERT_IPHDR) + (UINT16)stream.pos;
|
||||
RtlZeroMemory(iphdr, sizeof(WINDIVERT_IPHDR));
|
||||
iphdr->Version = 4;
|
||||
iphdr->HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
|
||||
iphdr->Length = RtlUshortByteSwap(total_len);
|
||||
iphdr->TTL = 1;
|
||||
iphdr->Protocol = 254; // "experimental"
|
||||
|
||||
*len_ptr = total_len;
|
||||
|
||||
return iphdr;
|
||||
*len_ptr = stream.pos;
|
||||
return (PVOID)stream.data;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6152,7 +6473,7 @@ static void windivert_reflect_event_notify(context_t context,
|
||||
PLIST_ENTRY entry;
|
||||
context_t waiter;
|
||||
const WINDIVERT_FILTER *filter;
|
||||
PWINDIVERT_IPHDR packet = NULL;
|
||||
PVOID packet = NULL;
|
||||
ULONG packet_len;
|
||||
BOOL match;
|
||||
|
||||
@@ -6174,9 +6495,9 @@ static void windivert_reflect_event_notify(context_t context,
|
||||
}
|
||||
if (packet == NULL)
|
||||
{
|
||||
packet = windivert_reflect_pseudo_packet(context, &packet_len);
|
||||
packet = windivert_reflect_packet(context, &packet_len);
|
||||
}
|
||||
(VOID)windivert_queue_work(waiter, (PVOID)packet, packet_len,
|
||||
(VOID)windivert_queue_work(waiter, packet, packet_len,
|
||||
/*buffers=*/NULL, /*layer=*/WINDIVERT_LAYER_REFLECT,
|
||||
(PVOID)&context->reflect.data, event, /*flags=*/0, /*priority=*/0,
|
||||
/*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
|
||||
@@ -6195,7 +6516,7 @@ static void windivert_reflect_established_notify(context_t context,
|
||||
BOOL match, ok;
|
||||
context_t waiter;
|
||||
const WINDIVERT_FILTER *filter;
|
||||
PWINDIVERT_IPHDR packet;
|
||||
PVOID packet;
|
||||
ULONG packet_len;
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
@@ -6220,8 +6541,8 @@ static void windivert_reflect_established_notify(context_t context,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
packet = windivert_reflect_pseudo_packet(waiter, &packet_len);
|
||||
ok = windivert_queue_work(context, (PVOID)packet, packet_len,
|
||||
packet = windivert_reflect_packet(waiter, &packet_len);
|
||||
ok = windivert_queue_work(context, packet, packet_len,
|
||||
/*buffers=*/NULL, /*layer=*/WINDIVERT_LAYER_REFLECT,
|
||||
(PVOID)&waiter->reflect.data,
|
||||
/*event=*/WINDIVERT_EVENT_REFLECT_OPEN, /*flags=*/0,
|
||||
|
||||
Reference in New Issue
Block a user