Make it possible to filter based on events.

E.g., "event == FLOW_ESTABLISHED".
This commit is contained in:
basil00
2018-10-22 08:38:12 +08:00
parent f0dd1224b1
commit 2ab1ddf1d2
5 changed files with 121 additions and 26 deletions
+83 -1
View File
@@ -109,6 +109,7 @@ typedef enum
TOKEN_UDP_PAYLOAD_LENGTH,
TOKEN_UDP_SRC_PORT,
TOKEN_ZERO,
TOKEN_EVENT,
TOKEN_TRUE,
TOKEN_FALSE,
TOKEN_INBOUND,
@@ -128,6 +129,12 @@ typedef enum
TOKEN_NETWORK,
TOKEN_NETWORK_FORWARD,
TOKEN_REFLECT,
TOKEN_NETWORK_PACKET,
TOKEN_FLOW_ESTABLISHED,
TOKEN_FLOW_DELETED,
TOKEN_REFLECT_ESTABLISHED,
TOKEN_REFLECT_OPEN,
TOKEN_REFLECT_CLOSE,
TOKEN_OPEN,
TOKEN_CLOSE,
TOKEN_EQ,
@@ -820,6 +827,11 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
case TOKEN_NETWORK:
case TOKEN_NETWORK_FORWARD:
case TOKEN_REFLECT:
case TOKEN_FLOW_ESTABLISHED:
case TOKEN_FLOW_DELETED:
case TOKEN_REFLECT_ESTABLISHED:
case TOKEN_REFLECT_OPEN:
case TOKEN_REFLECT_CLOSE:
return FALSE;
default:
return TRUE;
@@ -882,6 +894,10 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
case TOKEN_NETWORK:
case TOKEN_NETWORK_FORWARD:
case TOKEN_REFLECT:
case TOKEN_NETWORK_PACKET:
case TOKEN_REFLECT_ESTABLISHED:
case TOKEN_REFLECT_OPEN:
case TOKEN_REFLECT_CLOSE:
return FALSE;
default:
return TRUE;
@@ -953,6 +969,9 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
case TOKEN_LOCAL_PORT:
case TOKEN_REMOTE_PORT:
case TOKEN_PROTOCOL:
case TOKEN_NETWORK_PACKET:
case TOKEN_FLOW_ESTABLISHED:
case TOKEN_FLOW_DELETED:
return FALSE;
default:
return TRUE;
@@ -981,6 +1000,24 @@ static BOOL WinDivertExpandMacro(KIND kind, UINT32 *val)
case TOKEN_REFLECT:
*val = WINDIVERT_LAYER_REFLECT;
return TRUE;
case TOKEN_NETWORK_PACKET:
*val = WINDIVERT_EVENT_NETWORK_PACKET;
return TRUE;
case TOKEN_FLOW_ESTABLISHED:
*val = WINDIVERT_EVENT_FLOW_ESTABLISHED;
return TRUE;
case TOKEN_FLOW_DELETED:
*val = WINDIVERT_EVENT_FLOW_DELETED;
return TRUE;
case TOKEN_REFLECT_ESTABLISHED:
*val = WINDIVERT_EVENT_REFLECT_ESTABLISHED;
return TRUE;
case TOKEN_REFLECT_OPEN:
*val = WINDIVERT_EVENT_REFLECT_OPEN;
return TRUE;
case TOKEN_REFLECT_CLOSE:
*val = WINDIVERT_EVENT_REFLECT_CLOSE;
return TRUE;
default:
return FALSE;
}
@@ -995,10 +1032,17 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
static const TOKEN_NAME token_names[] =
{
{"FLOW", TOKEN_FLOW},
{"FLOW_DELETED", TOKEN_FLOW_DELETED},
{"FLOW_ESTABLISHED", TOKEN_FLOW_ESTABLISHED},
{"NETWORK", TOKEN_NETWORK},
{"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD},
{"NETWORK_PACKET", TOKEN_NETWORK_PACKET},
{"REFLECT", TOKEN_REFLECT},
{"REFLECT_CLOSE", TOKEN_REFLECT_CLOSE},
{"REFLECT_ESTABLISHED", TOKEN_REFLECT_ESTABLISHED},
{"REFLECT_OPEN", TOKEN_REFLECT_OPEN},
{"and", TOKEN_AND},
{"event", TOKEN_EVENT},
{"false", TOKEN_FALSE},
{"icmp", TOKEN_ICMP},
{"icmp.Body", TOKEN_ICMP_BODY},
@@ -1322,6 +1366,7 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
{{{0}}, TOKEN_UDP_PAYLOAD_LENGTH},
{{{0}}, TOKEN_UDP_SRC_PORT},
{{{0}}, TOKEN_ZERO},
{{{0}}, TOKEN_EVENT},
{{{0}}, TOKEN_TRUE},
{{{0}}, TOKEN_FALSE},
{{{0}}, TOKEN_INBOUND},
@@ -1446,6 +1491,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
switch (toks[*i].kind)
{
case TOKEN_ZERO:
case TOKEN_EVENT:
case TOKEN_TRUE:
case TOKEN_FALSE:
case TOKEN_OUTBOUND:
@@ -1696,6 +1742,9 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
case TOKEN_LAYER:
lb = 0; ub = WINDIVERT_LAYER_MAX;
break;
case TOKEN_EVENT:
lb = 0; ub = WINDIVERT_EVENT_MAX;
break;
case TOKEN_INBOUND:
case TOKEN_OUTBOUND:
case TOKEN_IP:
@@ -1930,6 +1979,9 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
case TOKEN_ZERO:
object->field = WINDIVERT_FILTER_FIELD_ZERO;
break;
case TOKEN_EVENT:
object->field = WINDIVERT_FILTER_FIELD_EVENT;
break;
case TOKEN_OUTBOUND:
object->field = WINDIVERT_FILTER_FIELD_OUTBOUND;
break;
@@ -2728,6 +2780,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
case WINDIVERT_FILTER_FIELD_ZERO:
val[0] = 0;
break;
case WINDIVERT_FILTER_FIELD_EVENT:
val[0] = addr->Event;
break;
case WINDIVERT_FILTER_FIELD_INBOUND:
val[0] = !addr->Outbound;
break;
@@ -3173,6 +3228,8 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
{
case WINDIVERT_FILTER_FIELD_ZERO:
kind = TOKEN_ZERO; break;
case WINDIVERT_FILTER_FIELD_EVENT:
kind = TOKEN_EVENT; break;
case WINDIVERT_FILTER_FIELD_INBOUND:
kind = TOKEN_INBOUND; break;
case WINDIVERT_FILTER_FIELD_OUTBOUND:
@@ -3685,7 +3742,7 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream,
static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
{
PEXPR field = expr->arg[0], val = expr->arg[1];
BOOL ipv4_addr = FALSE, ipv6_addr = FALSE, layer = FALSE;
BOOL ipv4_addr = FALSE, ipv6_addr = FALSE, layer = FALSE, event = FALSE;
switch (field->kind)
{
@@ -3742,6 +3799,9 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
case TOKEN_LAYER:
layer = TRUE;
break;
case TOKEN_EVENT:
event = TRUE;
break;
default:
break;
}
@@ -3786,6 +3846,26 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
WinDivertFormatNumber(stream, val->val[0]); break;
}
}
else if (event)
{
switch (val->val[0])
{
case WINDIVERT_EVENT_NETWORK_PACKET:
WinDivertPutString(stream, "NETWORK_PACKET"); break;
case WINDIVERT_EVENT_FLOW_ESTABLISHED:
WinDivertPutString(stream, "FLOW_ESTABLISHED"); break;
case WINDIVERT_EVENT_FLOW_DELETED:
WinDivertPutString(stream, "FLOW_DELETED"); break;
case WINDIVERT_EVENT_REFLECT_ESTABLISHED:
WinDivertPutString(stream, "REFLECT_ESTABLISHED"); break;
case WINDIVERT_EVENT_REFLECT_OPEN:
WinDivertPutString(stream, "REFLECT_OPEN"); break;
case WINDIVERT_EVENT_REFLECT_CLOSE:
WinDivertPutString(stream, "REFLECT_CLOSE"); break;
default:
WinDivertFormatNumber(stream, val->val[0]); break;
}
}
else
{
WinDivertFormatNumber(stream, val->val[0]);
@@ -3863,6 +3943,8 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
return;
case TOKEN_ZERO:
WinDivertPutString(stream, "zero"); return;
case TOKEN_EVENT:
WinDivertPutString(stream, "event"); return;
case TOKEN_INBOUND:
WinDivertPutString(stream, "inbound"); return;
case TOKEN_OUTBOUND:
+2 -11
View File
@@ -1,5 +1,5 @@
/*
* streamdump.c
* windivertctl.c
* (C) 2018, all rights reserved,
*
* This file is part of WinDivert.
@@ -73,15 +73,6 @@ typedef enum
KILLALL
} MODE;
/*
* Months.
*/
static const char *months[12] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"
};
/*
* Add a new process.
*/
@@ -387,7 +378,7 @@ usage:
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
filter_str, sizeof(filter_str)))
{
printf("\"%s\" \"%s\"", filter_str, (char *)object); // XXX
printf("\"%s\"", filter_str);
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
+8 -1
View File
@@ -129,8 +129,9 @@
#define WINDIVERT_FILTER_FIELD_REMOTEPORT 64
#define WINDIVERT_FILTER_FIELD_PROTOCOL 65
#define WINDIVERT_FILTER_FIELD_LAYER 66
#define WINDIVERT_FILTER_FIELD_EVENT 67
#define WINDIVERT_FILTER_FIELD_MAX \
WINDIVERT_FILTER_FIELD_LAYER
WINDIVERT_FILTER_FIELD_EVENT
#define WINDIVERT_FILTER_TEST_EQ 0
#define WINDIVERT_FILTER_TEST_NEQ 1
@@ -151,6 +152,12 @@
#define WINDIVERT_LAYER_DEFAULT WINDIVERT_LAYER_NETWORK
#define WINDIVERT_LAYER_MAX WINDIVERT_LAYER_REFLECT
/*
* WinDivert events.
*/
#define WINDIVERT_EVENT_MAX \
WINDIVERT_EVENT_REFLECT_CLOSE
/*
* WinDivert flags.
*/
+27 -13
View File
@@ -432,8 +432,8 @@ static void windivert_free_packet(packet_t packet);
static BOOL windivert_decrement_ttl(PVOID data, BOOL ipv4, BOOL checksum);
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b);
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
PVOID layer_data, BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
PWINDIVERT_FILTER filter);
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter);
static PWINDIVERT_FILTER windivert_filter_compile(
PWINDIVERT_FILTER ioctl_filter, size_t ioctl_filter_len);
static NTSTATUS windivert_reflect_init(WDFOBJECT parent);
@@ -1834,7 +1834,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
case WINDIVERT_LAYER_FLOW:
case WINDIVERT_LAYER_REFLECT:
status = STATUS_INVALID_PARAMETER;
DEBUG_ERROR("failed to inject at FLOW layer", status);
DEBUG_ERROR("failed to inject at layer", status);
goto windivert_write_exit;
default:
break;
@@ -2796,7 +2796,8 @@ static void windivert_network_classify(context_t context,
do
{
BOOL match = windivert_filter(buffer_fst, layer, (PVOID)network_data,
ipv4, outbound, loopback, impostor, filter);
/*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4, outbound, loopback,
impostor, filter);
if (match)
{
break;
@@ -2860,7 +2861,8 @@ static void windivert_network_classify(context_t context,
while (buffer_itr != NULL)
{
BOOL match = windivert_filter(buffer_itr, layer, (PVOID)network_data,
ipv4, outbound, loopback, impostor, filter);
/*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4, outbound,
loopback, impostor, filter);
ok = windivert_queue_work(context, (PVOID)buffer_itr,
NET_BUFFER_DATA_LENGTH(buffer_itr), buffers, layer,
(PVOID)network_data, /*event=*/WINDIVERT_EVENT_NETWORK_PACKET,
@@ -3024,7 +3026,8 @@ static void windivert_flow_established_classify(context_t context,
KeReleaseInStackQueuedSpinLock(&lock_handle);
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
(PVOID)flow_data, ipv4, outbound, loopback, /*impostor=*/FALSE, filter);
(PVOID)flow_data, /*event=*/WINDIVERT_EVENT_FLOW_ESTABLISHED, ipv4,
outbound, loopback, /*impostor=*/FALSE, filter);
if (match)
{
ok = windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
@@ -3135,8 +3138,9 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
KeReleaseInStackQueuedSpinLock(&lock_handle);
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
(PVOID)&flow->data, !flow->ipv6, flow->outbound, flow->loopback,
/*impostor=*/FALSE, filter);
(PVOID)&flow->data, /*event=*/WINDIVERT_EVENT_FLOW_DELETED,
!flow->ipv6, flow->outbound, flow->loopback, /*impostor=*/FALSE,
filter);
if (match)
{
(VOID)windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
@@ -3772,8 +3776,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
* Checks if the given network packet is of interest.
*/
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
PVOID layer_data, BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
PWINDIVERT_FILTER filter)
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter)
{
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
@@ -3827,6 +3831,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
switch (filter[ip].field)
{
case WINDIVERT_FILTER_FIELD_ZERO:
case WINDIVERT_FILTER_FIELD_EVENT:
result = TRUE;
break;
case WINDIVERT_FILTER_FIELD_INBOUND:
@@ -3948,6 +3953,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
case WINDIVERT_FILTER_FIELD_ZERO:
field[0] = 0;
break;
case WINDIVERT_FILTER_FIELD_EVENT:
field[0] = (UINT32)event;
break;
case WINDIVERT_FILTER_FIELD_INBOUND:
field[0] = (UINT32)!outbound;
break;
@@ -4354,6 +4362,12 @@ static PWINDIVERT_FILTER windivert_filter_compile(
goto windivert_filter_compile_error;
}
break;
case WINDIVERT_FILTER_FIELD_EVENT:
if (ioctl_filter[i].arg[0] > WINDIVERT_EVENT_MAX)
{
goto windivert_filter_compile_error;
}
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH:
if (ioctl_filter[i].arg[0] > 0x0F)
@@ -4609,7 +4623,7 @@ static void windivert_reflect_event_notify(context_t context,
KeReleaseInStackQueuedSpinLock(&lock_handle);
match = windivert_filter(/*buffer=*/NULL,
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&context->reflect.data,
/*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
event, /*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
/*impostor=*/FALSE, filter);
if (!match)
{
@@ -4658,8 +4672,8 @@ static void windivert_reflect_established_notify(context_t context,
entry = entry->Flink;
match = windivert_filter(/*buffer=*/NULL,
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&waiter->reflect.data,
/*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
/*impostor=*/FALSE, filter);
/*event=*/WINDIVERT_EVENT_REFLECT_ESTABLISHED, /*ipv4=*/TRUE,
/*outbound=*/FALSE, /*loopback=*/FALSE, /*impostor=*/FALSE, filter);
if (!match)
{
continue;
+1
View File
@@ -113,6 +113,7 @@ static struct packet pkt_ipv6_exthdrs_udp =
};
static struct test tests[] =
{
{"event = NETWORK_PACKET", &pkt_echo_request, TRUE},
{"outbound and icmp", &pkt_echo_request, TRUE},
{"outbound", &pkt_echo_request, TRUE},
{"outbound and inbound", &pkt_echo_request, FALSE},