Add packet/payload matching to WinDivert (#156).
Adds the follow terms to the filter language:
- packet[idx]: 8bit packet value at idx.
- packet16[idx]: 16bit packet value at idx.
- packet32[idx]: 32bit packet value at idx.
- PROTO.Payload[idx]: 8bit payload value at idx.
- PROTO.Payload16[idx]: 16bit payload value at
idx.
- PROTO.Payload32[idx]: 32bit payload value at
idx.
where PROTO is {tcp,udp}.
16 and 32bit values assume network byte ordering.
The index may be:
- An undecorated integer, in which case the
packet or payload is treated as a 8/16/32bit
value array, similar to C arrays.
- A 'b' decorated integer, (e.g, packet32[17b]),
in which case the integer is interpreted as a
byte offset.
- A negative (un)decorated integer, in which
case indexing begins at the *end* of the
packet or payload. E.g., packet32[-1] is the
last 32bits of the packet.
If the index is out-of-bounds, then the test
is deemed to be equivalent to "false".
This commit is contained in:
+433
-53
@@ -93,6 +93,9 @@ typedef enum
|
||||
TOKEN_TCP_DST_PORT,
|
||||
TOKEN_TCP_FIN,
|
||||
TOKEN_TCP_HDR_LENGTH,
|
||||
TOKEN_TCP_PAYLOAD,
|
||||
TOKEN_TCP_PAYLOAD16,
|
||||
TOKEN_TCP_PAYLOAD32,
|
||||
TOKEN_TCP_PAYLOAD_LENGTH,
|
||||
TOKEN_TCP_PSH,
|
||||
TOKEN_TCP_RST,
|
||||
@@ -106,10 +109,16 @@ typedef enum
|
||||
TOKEN_UDP_CHECKSUM,
|
||||
TOKEN_UDP_DST_PORT,
|
||||
TOKEN_UDP_LENGTH,
|
||||
TOKEN_UDP_PAYLOAD,
|
||||
TOKEN_UDP_PAYLOAD16,
|
||||
TOKEN_UDP_PAYLOAD32,
|
||||
TOKEN_UDP_PAYLOAD_LENGTH,
|
||||
TOKEN_UDP_SRC_PORT,
|
||||
TOKEN_ZERO,
|
||||
TOKEN_EVENT,
|
||||
TOKEN_PACKET,
|
||||
TOKEN_PACKET16,
|
||||
TOKEN_PACKET32,
|
||||
TOKEN_TRUE,
|
||||
TOKEN_FALSE,
|
||||
TOKEN_INBOUND,
|
||||
@@ -141,6 +150,10 @@ typedef enum
|
||||
TOKEN_EVENT_CLOSE,
|
||||
TOKEN_OPEN,
|
||||
TOKEN_CLOSE,
|
||||
TOKEN_SQUARE_OPEN,
|
||||
TOKEN_SQUARE_CLOSE,
|
||||
TOKEN_MINUS,
|
||||
TOKEN_BYTES,
|
||||
TOKEN_EQ,
|
||||
TOKEN_NEQ,
|
||||
TOKEN_LT,
|
||||
@@ -239,9 +252,10 @@ typedef UINT64 ERROR, *PERROR;
|
||||
#define WINDIVERT_ERROR_BAD_TOKEN 4
|
||||
#define WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER 5
|
||||
#define WINDIVERT_ERROR_UNEXPECTED_TOKEN 6
|
||||
#define WINDIVERT_ERROR_OUTPUT_TOO_SHORT 7
|
||||
#define WINDIVERT_ERROR_BAD_OBJECT 8
|
||||
#define WINDIVERT_ERROR_ASSERTION_FAILED 9
|
||||
#define WINDIVERT_ERROR_INDEX_OOB 7
|
||||
#define WINDIVERT_ERROR_OUTPUT_TOO_SHORT 8
|
||||
#define WINDIVERT_ERROR_BAD_OBJECT 9
|
||||
#define WINDIVERT_ERROR_ASSERTION_FAILED 10
|
||||
|
||||
#define MAKE_ERROR(code, pos) \
|
||||
(((ERROR)(code) << 32) | (ERROR)(pos));
|
||||
@@ -603,6 +617,9 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"not", TOKEN_NOT, LNMFSR},
|
||||
{"or", TOKEN_OR, LNMFSR},
|
||||
{"outbound", TOKEN_OUTBOUND, LN_F__},
|
||||
{"packet", TOKEN_PACKET, LNM___},
|
||||
{"packet16", TOKEN_PACKET16, LNM___},
|
||||
{"packet32", TOKEN_PACKET32, LNM___},
|
||||
{"processId", TOKEN_PROCESS_ID, L__FSR},
|
||||
{"protocol", TOKEN_PROTOCOL, LN_FS_},
|
||||
{"remoteAddr", TOKEN_REMOTE_ADDR, LN_FS_},
|
||||
@@ -615,6 +632,9 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"tcp.DstPort", TOKEN_TCP_DST_PORT, LNM___},
|
||||
{"tcp.Fin", TOKEN_TCP_FIN, LNM___},
|
||||
{"tcp.HdrLength", TOKEN_TCP_HDR_LENGTH, LNM___},
|
||||
{"tcp.Payload", TOKEN_TCP_PAYLOAD, LNM___},
|
||||
{"tcp.Payload16", TOKEN_TCP_PAYLOAD16, LNM___},
|
||||
{"tcp.Payload32", TOKEN_TCP_PAYLOAD32, LNM___},
|
||||
{"tcp.PayloadLength", TOKEN_TCP_PAYLOAD_LENGTH, LNM___},
|
||||
{"tcp.Psh", TOKEN_TCP_PSH, LNM___},
|
||||
{"tcp.Rst", TOKEN_TCP_RST, LNM___},
|
||||
@@ -629,6 +649,9 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"udp.Checksum", TOKEN_UDP_CHECKSUM, LNM___},
|
||||
{"udp.DstPort", TOKEN_UDP_DST_PORT, LNM___},
|
||||
{"udp.Length", TOKEN_UDP_LENGTH, LNM___},
|
||||
{"udp.Payload", TOKEN_UDP_PAYLOAD, LNM___},
|
||||
{"udp.Payload16", TOKEN_UDP_PAYLOAD16, LNM___},
|
||||
{"udp.Payload32", TOKEN_UDP_PAYLOAD32, LNM___},
|
||||
{"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH, LNM___},
|
||||
{"udp.SrcPort", TOKEN_UDP_SRC_PORT, LNM___},
|
||||
{"zero", TOKEN_ZERO, LNMFSR},
|
||||
@@ -663,6 +686,15 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
case ')':
|
||||
tokens[tp++].kind = TOKEN_CLOSE;
|
||||
continue;
|
||||
case '[':
|
||||
tokens[tp++].kind = TOKEN_SQUARE_OPEN;
|
||||
continue;
|
||||
case ']':
|
||||
tokens[tp++].kind = TOKEN_SQUARE_CLOSE;
|
||||
continue;
|
||||
case '-':
|
||||
tokens[tp++].kind = TOKEN_MINUS;
|
||||
continue;
|
||||
case '!':
|
||||
if (filter[i] == '=')
|
||||
{
|
||||
@@ -780,16 +812,26 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Check for base 10 number:
|
||||
if (WinDivertAToI(token, &end, &num) && *end == '\0')
|
||||
if (WinDivertAToI(token, &end, &num))
|
||||
{
|
||||
tokens[tp].kind = TOKEN_NUMBER;
|
||||
tokens[tp].val[0] = num;
|
||||
tp++;
|
||||
continue;
|
||||
BOOL b = (*end == 'b' && *(end+1) == '\0');
|
||||
if (*end == '\0' || b)
|
||||
{
|
||||
tokens[tp].kind = TOKEN_NUMBER;
|
||||
tokens[tp].val[0] = num;
|
||||
tp++;
|
||||
if (b)
|
||||
{
|
||||
tokens[tp].kind = TOKEN_BYTES;
|
||||
tp++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for base 16 number:
|
||||
if (WinDivertAToX(token, &end, &num) && *end == '\0')
|
||||
if (token[0] == '0' && token[1] == 'x' &&
|
||||
WinDivertAToX(token, &end, &num) && *end == '\0')
|
||||
{
|
||||
tokens[tp].kind = TOKEN_NUMBER;
|
||||
tokens[tp].val[0] = num;
|
||||
@@ -924,6 +966,23 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct array varable.
|
||||
*/
|
||||
static PEXPR WinDivertMakeArrayVar(HANDLE pool, KIND kind, INT idx,
|
||||
PERROR error)
|
||||
{
|
||||
PEXPR var = (PEXPR)HeapAlloc(pool, HEAP_ZERO_MEMORY, sizeof(EXPR));
|
||||
if (var == NULL)
|
||||
{
|
||||
*error = MAKE_ERROR(WINDIVERT_ERROR_NO_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
var->kind = kind;
|
||||
var->val[0] = (UINT32)idx;
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct zero.
|
||||
*/
|
||||
@@ -938,6 +997,10 @@ static PEXPR WinDivertMakeZero(void)
|
||||
*/
|
||||
static PEXPR WinDivertMakeNumber(HANDLE pool, UINT32 *val, PERROR error)
|
||||
{
|
||||
if (val[0] == 0 && val[1] == 0 && val[2] == 0 && val[3] == 0)
|
||||
{
|
||||
return WinDivertMakeZero();
|
||||
}
|
||||
PEXPR expr = (PEXPR)HeapAlloc(pool, HEAP_ZERO_MEMORY, sizeof(EXPR));
|
||||
if (expr == NULL)
|
||||
{
|
||||
@@ -1001,7 +1064,8 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
|
||||
{
|
||||
PEXPR var, val;
|
||||
KIND kind;
|
||||
BOOL not = FALSE;
|
||||
BOOL not = FALSE, neg;
|
||||
UINT idx, size;
|
||||
while (toks[*i].kind == TOKEN_NOT)
|
||||
{
|
||||
not = !not;
|
||||
@@ -1079,13 +1143,80 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
|
||||
case TOKEN_UDP_LENGTH:
|
||||
case TOKEN_UDP_CHECKSUM:
|
||||
case TOKEN_UDP_PAYLOAD_LENGTH:
|
||||
var = WinDivertMakeVar(toks[*i].kind, error);
|
||||
*i = *i + 1;
|
||||
break;
|
||||
case TOKEN_PACKET:
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
size = sizeof(UINT8);
|
||||
goto array;
|
||||
case TOKEN_PACKET16:
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
size = sizeof(UINT16);
|
||||
goto array;
|
||||
case TOKEN_PACKET32:
|
||||
case TOKEN_TCP_PAYLOAD32:
|
||||
case TOKEN_UDP_PAYLOAD32:
|
||||
size = sizeof(UINT32);
|
||||
array:
|
||||
kind = toks[*i].kind;
|
||||
*i = *i + 1;
|
||||
if (toks[*i].kind != TOKEN_SQUARE_OPEN)
|
||||
{
|
||||
goto unexpected_token;
|
||||
}
|
||||
*i = *i + 1;
|
||||
neg = FALSE;
|
||||
if (toks[*i].kind == TOKEN_MINUS)
|
||||
{
|
||||
neg = TRUE;
|
||||
*i = *i + 1;
|
||||
}
|
||||
if (toks[*i].kind != TOKEN_NUMBER)
|
||||
{
|
||||
goto unexpected_token;
|
||||
}
|
||||
if (toks[*i].val[3] != 0 || toks[*i].val[2] != 0 ||
|
||||
toks[*i].val[1] != 0 || toks[*i].val[0] > UINT16_MAX)
|
||||
{
|
||||
*error = MAKE_ERROR(WINDIVERT_ERROR_INDEX_OOB, toks[*i].pos);
|
||||
return NULL;
|
||||
}
|
||||
idx = toks[*i].val[0];
|
||||
*i = *i + 1;
|
||||
if (toks[*i].kind == TOKEN_BYTES)
|
||||
{
|
||||
*i = *i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx *= size;
|
||||
}
|
||||
if ((!neg && idx > UINT16_MAX - size) ||
|
||||
(neg && idx > UINT16_MAX) || (neg && idx < size))
|
||||
{
|
||||
*error = MAKE_ERROR(WINDIVERT_ERROR_INDEX_OOB, toks[*i].pos);
|
||||
return NULL;
|
||||
}
|
||||
var = WinDivertMakeArrayVar(pool, kind, (neg? -(INT)idx: (INT)idx),
|
||||
error);
|
||||
if (var == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (toks[*i].kind != TOKEN_SQUARE_CLOSE)
|
||||
{
|
||||
goto unexpected_token;
|
||||
}
|
||||
*i = *i + 1;
|
||||
break;
|
||||
default:
|
||||
unexpected_token:
|
||||
*error = MAKE_ERROR(WINDIVERT_ERROR_UNEXPECTED_TOKEN, toks[*i].pos);
|
||||
return NULL;
|
||||
}
|
||||
var = WinDivertMakeVar(toks[*i].kind, error);
|
||||
*i = *i + 1;
|
||||
switch (toks[*i].kind)
|
||||
{
|
||||
case TOKEN_EQ:
|
||||
@@ -1296,6 +1427,9 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
case TOKEN_ICMPV6_TYPE:
|
||||
case TOKEN_ICMPV6_CODE:
|
||||
case TOKEN_PROTOCOL:
|
||||
case TOKEN_PACKET:
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
lb = 0; ub = 0xFF;
|
||||
break;
|
||||
case TOKEN_IP_FRAG_OFF:
|
||||
@@ -1321,6 +1455,9 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
case TOKEN_UDP_PAYLOAD_LENGTH:
|
||||
case TOKEN_LOCAL_PORT:
|
||||
case TOKEN_REMOTE_PORT:
|
||||
case TOKEN_PACKET16:
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
lb = 0; ub = 0xFFFF;
|
||||
break;
|
||||
case TOKEN_IPV6_FLOW_LABEL:
|
||||
@@ -1469,6 +1606,7 @@ static INT16 WinDivertFlattenExpr(PEXPR expr, INT16 *label, INT16 succ,
|
||||
static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
PWINDIVERT_FILTER object)
|
||||
{
|
||||
BOOL big;
|
||||
PEXPR var = test->arg[0], val = test->arg[1];
|
||||
switch (test->kind)
|
||||
{
|
||||
@@ -1493,6 +1631,8 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
default:
|
||||
return;
|
||||
}
|
||||
big = FALSE;
|
||||
object->arg[1] = object->arg[2] = object->arg[3] = 0;
|
||||
switch (var->kind)
|
||||
{
|
||||
case TOKEN_ZERO:
|
||||
@@ -1501,6 +1641,42 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
case TOKEN_EVENT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_EVENT;
|
||||
break;
|
||||
case TOKEN_PACKET:
|
||||
object->field = WINDIVERT_FILTER_FIELD_PACKET;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_PACKET16:
|
||||
object->field = WINDIVERT_FILTER_FIELD_PACKET16;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_PACKET32:
|
||||
object->field = WINDIVERT_FILTER_FIELD_PACKET32;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_TCP_PAYLOAD32:
|
||||
object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_UDP_PAYLOAD32:
|
||||
object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32;
|
||||
object->arg[1] = var->val[0];
|
||||
break;
|
||||
case TOKEN_OUTBOUND:
|
||||
object->field = WINDIVERT_FILTER_FIELD_OUTBOUND;
|
||||
break;
|
||||
@@ -1524,9 +1700,11 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
break;
|
||||
case TOKEN_LOCAL_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_LOCALADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_REMOTE_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_REMOTEADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_LOCAL_PORT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_LOCALPORT;
|
||||
@@ -1590,9 +1768,11 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
break;
|
||||
case TOKEN_IP_SRC_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IP_SRCADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_IP_DST_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IP_DSTADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_IPV6_TRAFFIC_CLASS:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS;
|
||||
@@ -1611,9 +1791,11 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
break;
|
||||
case TOKEN_IPV6_SRC_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IPV6_SRCADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_IPV6_DST_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IPV6_DSTADDR;
|
||||
big = TRUE;
|
||||
break;
|
||||
case TOKEN_ICMP_TYPE:
|
||||
object->field = WINDIVERT_FILTER_FIELD_ICMP_TYPE;
|
||||
@@ -1703,9 +1885,12 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
return;
|
||||
}
|
||||
object->arg[0] = val->val[0];
|
||||
object->arg[1] = val->val[1];
|
||||
object->arg[2] = val->val[2];
|
||||
object->arg[3] = val->val[3];
|
||||
if (big)
|
||||
{
|
||||
object->arg[1] = val->val[1];
|
||||
object->arg[2] = val->val[2];
|
||||
object->arg[3] = val->val[3];
|
||||
}
|
||||
switch (test->succ)
|
||||
{
|
||||
case WINDIVERT_FILTER_RESULT_ACCEPT:
|
||||
@@ -2021,6 +2206,8 @@ static const char *WinDivertErrorString(UINT code)
|
||||
return "Filter expression contains a bad token for layer";
|
||||
case WINDIVERT_ERROR_UNEXPECTED_TOKEN:
|
||||
return "Filter expression parse error";
|
||||
case WINDIVERT_ERROR_INDEX_OOB:
|
||||
return "Filter expression array index is out-of-bounds";
|
||||
case WINDIVERT_ERROR_OUTPUT_TOO_SHORT:
|
||||
return "Filter object buffer is too short";
|
||||
case WINDIVERT_ERROR_BAD_OBJECT:
|
||||
@@ -2086,31 +2273,34 @@ extern BOOL WinDivertHelperCompileFilter(const char *filter_str,
|
||||
/*
|
||||
* Big number comparison.
|
||||
*/
|
||||
static int WinDivertBigNumCompare(const UINT32 *a, const UINT32 *b)
|
||||
static int WinDivertBigNumCompare(const UINT32 *a, const UINT32 *b, BOOL big)
|
||||
{
|
||||
if (a[3] < b[3])
|
||||
if (big)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[3] > b[3])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[2] < b[2])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[2] > b[2])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[1] < b[1])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[1] > b[1])
|
||||
{
|
||||
return 1;
|
||||
if (a[3] < b[3])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[3] > b[3])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[2] < b[2])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[2] > b[2])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[1] < b[1])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[1] > b[1])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (a[0] < b[0])
|
||||
{
|
||||
@@ -2123,6 +2313,28 @@ static int WinDivertBigNumCompare(const UINT32 *a, const UINT32 *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get packet/payload data.
|
||||
*/
|
||||
static BOOL WinDivertGetData(PVOID packet, UINT packet_len, UINT offset,
|
||||
INT idx, UINT size, PVOID data)
|
||||
{
|
||||
if (idx < 0)
|
||||
{
|
||||
idx += (INT)packet_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx += (INT)offset;
|
||||
}
|
||||
if (idx < (INT)offset || idx > (INT)(packet_len - size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(data, (UINT8 *)packet + idx, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the given filter with the given packet as input.
|
||||
*/
|
||||
@@ -2138,9 +2350,12 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
PWINDIVERT_TCPHDR tcphdr = NULL;
|
||||
PWINDIVERT_UDPHDR udphdr = NULL;
|
||||
UINT8 protocol = 0;
|
||||
UINT payload_len;
|
||||
UINT header_len = 0, payload_len = 0;
|
||||
UINT32 val[4];
|
||||
BOOL pass;
|
||||
UINT8 data8;
|
||||
UINT16 data16;
|
||||
UINT32 data32;
|
||||
BOOL pass, big;
|
||||
int cmp;
|
||||
WINDIVERT_FILTER object[WINDIVERT_FILTER_MAXLEN];
|
||||
UINT obj_len;
|
||||
@@ -2162,6 +2377,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
WinDivertParsePacket(packet, packet_len, &iphdr, &ipv6hdr,
|
||||
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
|
||||
&payload_len);
|
||||
header_len = packet_len - payload_len;
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
(!addr->IPv6 && iphdr == NULL))
|
||||
{
|
||||
@@ -2209,6 +2425,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
break;
|
||||
}
|
||||
pass = TRUE;
|
||||
big = FALSE;
|
||||
switch (object[pc].field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
@@ -2232,6 +2449,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
|
||||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
@@ -2309,6 +2529,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
case WINDIVERT_FILTER_FIELD_TCP_WINDOW:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URGPTR:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
|
||||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
@@ -2318,6 +2541,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
case WINDIVERT_FILTER_FIELD_UDP_DSTPORT:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_LENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
|
||||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
@@ -2332,7 +2558,6 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
pc = object[pc].failure;
|
||||
continue;
|
||||
}
|
||||
val[1] = val[2] = val[3] = 0;
|
||||
switch (object[pc].field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
@@ -2341,6 +2566,39 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
val[0] = addr->Event;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
pass = WinDivertGetData(packet, packet_len, /*offset=*/0,
|
||||
object[pc].arg[1], sizeof(data8), &data8);
|
||||
val[0] = data8;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
pass = WinDivertGetData(packet, packet_len, /*offset=*/0,
|
||||
object[pc].arg[1], sizeof(data16), &data16);
|
||||
val[0] = ntohs(data16);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
pass = WinDivertGetData(packet, packet_len, /*offset=*/0,
|
||||
object[pc].arg[1], sizeof(data32), &data32);
|
||||
val[0] = ntohl(data32);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
pass = WinDivertGetData(packet, packet_len, header_len,
|
||||
object[pc].arg[1], sizeof(data8), &data8);
|
||||
val[0] = data8;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
pass = WinDivertGetData(packet, packet_len, header_len,
|
||||
object[pc].arg[1], sizeof(data16), &data16);
|
||||
val[0] = ntohs(data16);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
pass = WinDivertGetData(packet, packet_len, header_len,
|
||||
object[pc].arg[1], sizeof(data32), &data32);
|
||||
val[0] = ntohl(data32);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
val[0] = !addr->Outbound;
|
||||
break;
|
||||
@@ -2495,12 +2753,14 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
val[0] = ipv6hdr->HopLimit;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
|
||||
big = TRUE;
|
||||
val[3] = ntohl(ipv6hdr->SrcAddr[0]);
|
||||
val[2] = ntohl(ipv6hdr->SrcAddr[1]);
|
||||
val[1] = ntohl(ipv6hdr->SrcAddr[2]);
|
||||
val[0] = ntohl(ipv6hdr->SrcAddr[3]);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
|
||||
big = TRUE;
|
||||
val[3] = ntohl(ipv6hdr->DstAddr[0]);
|
||||
val[2] = ntohl(ipv6hdr->DstAddr[1]);
|
||||
val[1] = ntohl(ipv6hdr->DstAddr[2]);
|
||||
@@ -2591,6 +2851,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
val[0] = payload_len;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOCALADDR:
|
||||
big = TRUE;
|
||||
switch (addr->Layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -2633,6 +2894,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
|
||||
big = TRUE;
|
||||
switch (addr->Layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -2772,7 +3034,12 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
cmp = WinDivertBigNumCompare(val, object[pc].arg);
|
||||
if (!pass)
|
||||
{
|
||||
pc = object[pc].failure;
|
||||
continue;
|
||||
}
|
||||
cmp = WinDivertBigNumCompare(val, object[pc].arg, big);
|
||||
switch (object[pc].test)
|
||||
{
|
||||
case WINDIVERT_FILTER_TEST_EQ:
|
||||
@@ -2903,6 +3170,22 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream,
|
||||
filter->arg[1] = 0x0000FFFF;
|
||||
filter->arg[2] = filter->arg[3] = 0;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
if (!WinDivertDeserializeNumber(stream, 7, &val))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
filter->arg[1] = (UINT32)((INT)val - UINT16_MAX);
|
||||
filter->arg[2] = filter->arg[3] = 0;
|
||||
break;
|
||||
default:
|
||||
filter->arg[1] = filter->arg[2] = filter->arg[3] = 0;
|
||||
break;
|
||||
@@ -2994,6 +3277,7 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
|
||||
{
|
||||
KIND kind;
|
||||
PEXPR var, val, expr;
|
||||
UINT32 tmp[4];
|
||||
ERROR error;
|
||||
|
||||
switch (test->field)
|
||||
@@ -3002,6 +3286,24 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
|
||||
kind = TOKEN_ZERO; break;
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
kind = TOKEN_EVENT; break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
kind = TOKEN_PACKET; break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
kind = TOKEN_PACKET16; break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
kind = TOKEN_PACKET32; break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
kind = TOKEN_TCP_PAYLOAD; break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
kind = TOKEN_TCP_PAYLOAD16; break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
kind = TOKEN_TCP_PAYLOAD32; break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
kind = TOKEN_UDP_PAYLOAD; break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
kind = TOKEN_UDP_PAYLOAD16; break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
kind = TOKEN_UDP_PAYLOAD32; break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
kind = TOKEN_INBOUND; break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
@@ -3138,15 +3440,42 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
var = WinDivertMakeVar(kind, &error);
|
||||
if (var == NULL)
|
||||
switch (kind)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
val = WinDivertMakeNumber(pool, test->arg, &error);
|
||||
if (val == NULL)
|
||||
{
|
||||
return NULL;
|
||||
case TOKEN_PACKET:
|
||||
case TOKEN_PACKET16:
|
||||
case TOKEN_PACKET32:
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
case TOKEN_TCP_PAYLOAD32:
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
case TOKEN_UDP_PAYLOAD32:
|
||||
var = WinDivertMakeArrayVar(pool, kind, test->arg[1], &error);
|
||||
if (var == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
tmp[0] = test->arg[0];
|
||||
tmp[1] = tmp[2] = tmp[3] = 0;
|
||||
val = WinDivertMakeNumber(pool, tmp, &error);
|
||||
if (val == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
var = WinDivertMakeVar(kind, &error);
|
||||
if (var == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
val = WinDivertMakeNumber(pool, test->arg, &error);
|
||||
if (val == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (test->test)
|
||||
@@ -3558,7 +3887,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
{
|
||||
PEXPR field = expr->arg[0], val = expr->arg[1];
|
||||
BOOL is_ipv4_addr = FALSE, is_ipv6_addr = FALSE, is_layer = FALSE,
|
||||
is_event = FALSE;
|
||||
is_event = FALSE, is_hex = FALSE;
|
||||
|
||||
switch (field->kind)
|
||||
{
|
||||
@@ -3618,6 +3947,23 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
case TOKEN_EVENT:
|
||||
is_event = TRUE;
|
||||
break;
|
||||
case TOKEN_PACKET:
|
||||
case TOKEN_PACKET16:
|
||||
case TOKEN_PACKET32:
|
||||
case TOKEN_IP_ID:
|
||||
case TOKEN_IP_CHECKSUM:
|
||||
case TOKEN_TCP_CHECKSUM:
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
case TOKEN_TCP_PAYLOAD32:
|
||||
case TOKEN_UDP_CHECKSUM:
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
case TOKEN_UDP_PAYLOAD32:
|
||||
case TOKEN_ICMP_CHECKSUM:
|
||||
case TOKEN_ICMPV6_CHECKSUM:
|
||||
is_hex = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3723,6 +4069,11 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
WinDivertFormatNumber(stream, val->val[0]); break;
|
||||
}
|
||||
}
|
||||
else if (is_hex)
|
||||
{
|
||||
WinDivertPutString(stream, "0x");
|
||||
WinDivertFormatHexNumber(stream, val->val[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WinDivertFormatNumber(stream, val->val[0]);
|
||||
@@ -3735,6 +4086,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
WINDIVERT_LAYER layer, BOOL top_level, BOOL and)
|
||||
{
|
||||
INT idx;
|
||||
|
||||
if (stream->pos >= stream->max)
|
||||
{
|
||||
return;
|
||||
@@ -3802,6 +4155,24 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
WinDivertPutString(stream, "zero"); return;
|
||||
case TOKEN_EVENT:
|
||||
WinDivertPutString(stream, "event"); return;
|
||||
case TOKEN_PACKET:
|
||||
WinDivertPutString(stream, "packet"); break;
|
||||
case TOKEN_PACKET16:
|
||||
WinDivertPutString(stream, "packet16"); break;
|
||||
case TOKEN_PACKET32:
|
||||
WinDivertPutString(stream, "packet32"); break;
|
||||
case TOKEN_TCP_PAYLOAD:
|
||||
WinDivertPutString(stream, "tcp.Payload"); break;
|
||||
case TOKEN_TCP_PAYLOAD16:
|
||||
WinDivertPutString(stream, "tcp.Payload16"); break;
|
||||
case TOKEN_TCP_PAYLOAD32:
|
||||
WinDivertPutString(stream, "tcp.Payload32"); break;
|
||||
case TOKEN_UDP_PAYLOAD:
|
||||
WinDivertPutString(stream, "udp.Payload"); break;
|
||||
case TOKEN_UDP_PAYLOAD16:
|
||||
WinDivertPutString(stream, "udp.Payload16"); break;
|
||||
case TOKEN_UDP_PAYLOAD32:
|
||||
WinDivertPutString(stream, "udp.Payload32"); break;
|
||||
case TOKEN_INBOUND:
|
||||
WinDivertPutString(stream, "inbound"); return;
|
||||
case TOKEN_OUTBOUND:
|
||||
@@ -3935,9 +4306,18 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
case TOKEN_LAYER:
|
||||
WinDivertPutString(stream, "layer"); return;
|
||||
case TOKEN_NUMBER:
|
||||
WinDivertFormatNumber(stream, expr->val[0]);
|
||||
return;
|
||||
WinDivertFormatNumber(stream, expr->val[0]); return;
|
||||
}
|
||||
|
||||
WinDivertPutChar(stream, '[');
|
||||
idx = (INT)expr->val[0];
|
||||
if (idx < 0)
|
||||
{
|
||||
WinDivertPutChar(stream, '-');
|
||||
idx = -idx;
|
||||
}
|
||||
WinDivertFormatNumber(stream, (UINT32)idx);
|
||||
WinDivertPutString(stream, "b]");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -167,6 +167,7 @@ static void WinDivertSerializeNumber(PWINDIVERT_STREAM stream, UINT32 val)
|
||||
static void WinDivertSerializeTest(PWINDIVERT_STREAM stream,
|
||||
PWINDIVERT_FILTER filter)
|
||||
{
|
||||
INT idx;
|
||||
UINT i;
|
||||
|
||||
WinDivertPutChar(stream, '_');
|
||||
@@ -184,6 +185,19 @@ static void WinDivertSerializeTest(PWINDIVERT_STREAM stream,
|
||||
WinDivertSerializeNumber(stream, filter->arg[i]);
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
idx = (INT)filter->arg[1];
|
||||
idx += UINT16_MAX;
|
||||
WinDivertSerializeNumber(stream, (UINT32)idx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -127,8 +127,17 @@
|
||||
#define WINDIVERT_FILTER_FIELD_PROTOCOL 65
|
||||
#define WINDIVERT_FILTER_FIELD_LAYER 66
|
||||
#define WINDIVERT_FILTER_FIELD_EVENT 67
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET 68
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET16 69
|
||||
#define WINDIVERT_FILTER_FIELD_PACKET32 70
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 71
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 72
|
||||
#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 73
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 74
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 75
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 76
|
||||
#define WINDIVERT_FILTER_FIELD_MAX \
|
||||
WINDIVERT_FILTER_FIELD_EVENT
|
||||
WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
|
||||
+178
-90
@@ -457,13 +457,14 @@ static void windivert_queue_packet(context_t context, packet_t packet);
|
||||
static void windivert_reinject_packet(packet_t packet);
|
||||
static void windivert_free_packet(packet_t packet);
|
||||
static BOOL windivert_decrement_ttl(PVOID data, BOOL ipv4);
|
||||
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b);
|
||||
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b,
|
||||
BOOL big);
|
||||
static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr,
|
||||
PWINDIVERT_ICMPHDR *icmp_header_ptr,
|
||||
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr,
|
||||
PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr,
|
||||
UINT8 *proto_ptr, UINT *payload_len_ptr);
|
||||
UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr);
|
||||
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
|
||||
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter);
|
||||
@@ -3014,7 +3015,7 @@ static void windivert_get_ipv6_addr(const FWPS_INCOMING_VALUES0 *fixed_vals,
|
||||
UINT8 *addr8 = (UINT8 *)addr;
|
||||
INT i;
|
||||
FWP_VALUE0 value = fixed_vals->incomingValue[idx].value;
|
||||
if (value.type != FWP_BYTE_ARRAY16_TYPE)
|
||||
if (value.type != FWP_BYTE_ARRAY16_TYPE)
|
||||
{
|
||||
RtlZeroMemory(&addr, 16);
|
||||
return;
|
||||
@@ -4431,31 +4432,34 @@ static BOOL windivert_decrement_ttl(PVOID data, BOOL ipv4)
|
||||
/*
|
||||
* Big number comparison.
|
||||
*/
|
||||
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b)
|
||||
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b, BOOL big)
|
||||
{
|
||||
if (a[3] < b[3])
|
||||
if (big)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[3] > b[3])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[2] < b[2])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[2] > b[2])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[1] < b[1])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[1] > b[1])
|
||||
{
|
||||
return 1;
|
||||
if (a[3] < b[3])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[3] > b[3])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[2] < b[2])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[2] > b[2])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (a[1] < b[1])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (a[1] > b[1])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (a[0] < b[0])
|
||||
{
|
||||
@@ -4468,6 +4472,44 @@ static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get packet/payload data.
|
||||
*/
|
||||
static BOOL windivert_get_data(PNET_BUFFER buffer, UINT offset, INT idx,
|
||||
UINT size, PVOID data)
|
||||
{
|
||||
PVOID ptr;
|
||||
UINT length = NET_BUFFER_DATA_LENGTH(buffer);
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
idx += (INT)length;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx += (INT)offset;
|
||||
}
|
||||
if (idx < (INT)offset || idx > (INT)(length - size))
|
||||
{
|
||||
return FALSE; // OOB
|
||||
}
|
||||
|
||||
if (idx > 0)
|
||||
{
|
||||
NdisAdvanceNetBufferDataStart(buffer, idx, FALSE, NULL);
|
||||
}
|
||||
ptr = NdisGetDataBuffer(buffer, size, data, 1, 0);
|
||||
if (ptr != NULL && ptr != data)
|
||||
{
|
||||
RtlCopyMemory(data, ptr, size); // Non-contiguous case
|
||||
}
|
||||
if (idx > 0)
|
||||
{
|
||||
(VOID)NdisRetreatNetBufferDataStart(buffer, idx, 0, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse packet headers.
|
||||
*/
|
||||
@@ -4476,7 +4518,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
PWINDIVERT_ICMPHDR *icmp_header_ptr,
|
||||
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr,
|
||||
PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr,
|
||||
UINT8 *proto_ptr, UINT *payload_len_ptr)
|
||||
UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr)
|
||||
{
|
||||
UINT tot_len, ip_header_len;
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
@@ -4487,7 +4529,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT16 ip, ttl;
|
||||
UINT8 proto = 0;
|
||||
UINT payload_len = 0;
|
||||
UINT header_len = 0, payload_len = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
// Parse the headers:
|
||||
@@ -4609,23 +4651,25 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
case IPPROTO_ICMP:
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPHDR), NULL, 1, 0);
|
||||
header_len = ip_header_len + sizeof(WINDIVERT_ICMPHDR);
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPV6HDR), NULL, 1, 0);
|
||||
header_len = ip_header_len + sizeof(WINDIVERT_ICMPV6HDR);
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
|
||||
payload_len = tot_len - ip_header_len -
|
||||
tcp_header->HdrLength*sizeof(UINT32);
|
||||
header_len = ip_header_len + tcp_header->HdrLength*sizeof(UINT32);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_UDPHDR), NULL, 1, 0);
|
||||
payload_len = tot_len - ip_header_len - sizeof(WINDIVERT_UDPHDR);
|
||||
header_len = ip_header_len + sizeof(WINDIVERT_UDPHDR);
|
||||
break;
|
||||
default:
|
||||
header_len = ip_header_len;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4644,7 +4688,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
*tcp_header_ptr = tcp_header;
|
||||
*udp_header_ptr = udp_header;
|
||||
*proto_ptr = proto;
|
||||
*payload_len_ptr = payload_len;
|
||||
*header_len_ptr = header_len;
|
||||
*payload_len_ptr = tot_len - header_len;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -4663,12 +4708,15 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT8 protocol = 0;
|
||||
UINT payload_len = 0;
|
||||
UINT header_len = 0, payload_len = 0;
|
||||
UINT16 ip, ttl;
|
||||
PWINDIVERT_DATA_NETWORK network_data = NULL;
|
||||
PWINDIVERT_DATA_FLOW flow_data = NULL;
|
||||
PWINDIVERT_DATA_SOCKET socket_data = NULL;
|
||||
PWINDIVERT_DATA_REFLECT reflect_data = NULL;
|
||||
UINT8 data8;
|
||||
UINT16 data16;
|
||||
UINT32 data32;
|
||||
NTSTATUS status;
|
||||
|
||||
switch (layer)
|
||||
@@ -4677,7 +4725,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
if (!windivert_parse_headers(buffer, ipv4, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header,
|
||||
&protocol, &payload_len))
|
||||
&protocol, &header_len, &payload_len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -4703,12 +4751,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
while (ttl-- != 0)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BOOL error = FALSE;
|
||||
BOOL big = FALSE;
|
||||
int cmp;
|
||||
UINT32 field[4];
|
||||
field[1] = 0;
|
||||
field[2] = 0;
|
||||
field[3] = 0;
|
||||
|
||||
switch (filter[ip].field)
|
||||
{
|
||||
@@ -4733,6 +4778,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
result = (layer == WINDIVERT_LAYER_NETWORK ||
|
||||
layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
@@ -4810,6 +4858,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_TCP_WINDOW:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URGPTR:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH:
|
||||
result = (layer == WINDIVERT_LAYER_NETWORK ||
|
||||
layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
@@ -4819,15 +4870,16 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_UDP_DSTPORT:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_LENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
result = (layer == WINDIVERT_LAYER_NETWORK ||
|
||||
layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
result = result && (udp_header != NULL);
|
||||
break;
|
||||
default:
|
||||
result = FALSE;
|
||||
error = TRUE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
@@ -4839,6 +4891,39 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
field[0] = (UINT32)event;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
result = windivert_get_data(buffer, /*offset=*/0,
|
||||
(INT)filter[ip].arg[1], sizeof(data8), &data8);
|
||||
field[0] = (UINT32)data8;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
result = windivert_get_data(buffer, /*offset=*/0,
|
||||
(INT)filter[ip].arg[1], sizeof(data16), &data16);
|
||||
field[0] = (UINT32)RtlUshortByteSwap(data16);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
result = windivert_get_data(buffer, /*offset=*/0,
|
||||
(INT)filter[ip].arg[1], sizeof(data32), &data32);
|
||||
field[0] = (UINT32)RtlUlongByteSwap(data32);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
result = windivert_get_data(buffer, header_len,
|
||||
(INT)filter[ip].arg[1], sizeof(data8), &data8);
|
||||
field[0] = (UINT32)data8;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
result = windivert_get_data(buffer, header_len,
|
||||
(INT)filter[ip].arg[1], sizeof(data16), &data16);
|
||||
field[0] = (UINT32)RtlUshortByteSwap(data16);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
result = windivert_get_data(buffer, header_len,
|
||||
(INT)filter[ip].arg[1], sizeof(data32), &data32);
|
||||
field[0] = (UINT32)RtlUlongByteSwap(data32);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
field[0] = (UINT32)!outbound;
|
||||
break;
|
||||
@@ -4879,9 +4964,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
flow_data->Protocol == IPPROTO_ICMP);
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6:
|
||||
@@ -4900,9 +4983,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
flow_data->Protocol == IPPROTO_ICMPV6);
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP:
|
||||
@@ -4921,9 +5002,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
(UINT32)(flow_data->Protocol == IPPROTO_TCP);
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP:
|
||||
@@ -4942,9 +5021,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
(UINT32)(flow_data->Protocol == IPPROTO_UDP);
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
|
||||
@@ -5004,6 +5081,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = (UINT32)ipv6_header->HopLimit;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
|
||||
big = TRUE;
|
||||
field[3] =
|
||||
(UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[0]);
|
||||
field[2] =
|
||||
@@ -5014,6 +5092,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
(UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[3]);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
|
||||
big = TRUE;
|
||||
field[3] =
|
||||
(UINT32)RtlUlongByteSwap(ipv6_header->DstAddr[0]);
|
||||
field[2] =
|
||||
@@ -5111,6 +5190,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = (UINT32)payload_len;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOCALADDR:
|
||||
big = TRUE;
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -5157,12 +5237,11 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[3] = socket_data->LocalAddr[3];
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
|
||||
big = TRUE;
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -5209,9 +5288,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[3] = socket_data->RemoteAddr[3];
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOCALPORT:
|
||||
@@ -5242,9 +5319,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = (UINT32)socket_data->LocalPort;
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
|
||||
@@ -5275,9 +5350,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = (UINT32)socket_data->RemotePort;
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PROTOCOL:
|
||||
@@ -5293,9 +5366,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = (UINT32)socket_data->Protocol;
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PROCESSID:
|
||||
@@ -5311,22 +5382,19 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
field[0] = reflect_data->ProcessId;
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LAYER:
|
||||
field[0] = reflect_data->Layer;
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
cmp = windivert_big_num_compare(field, filter[ip].arg);
|
||||
cmp = windivert_big_num_compare(field, filter[ip].arg, big);
|
||||
switch (filter[ip].test)
|
||||
{
|
||||
case WINDIVERT_FILTER_TEST_EQ:
|
||||
@@ -5348,16 +5416,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
result = (cmp >= 0);
|
||||
break;
|
||||
default:
|
||||
error = TRUE;
|
||||
result = FALSE;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (bad filter)");
|
||||
return FALSE;
|
||||
}
|
||||
ip = (result? filter[ip].success: filter[ip].failure);
|
||||
if (ip == WINDIVERT_FILTER_RESULT_ACCEPT)
|
||||
{
|
||||
@@ -5447,17 +5508,38 @@ static PWINDIVERT_FILTER windivert_filter_compile(
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
if ((ioctl_filter[i].field == WINDIVERT_FILTER_FIELD_IP_SRCADDR ||
|
||||
ioctl_filter[i].field == WINDIVERT_FILTER_FIELD_IP_DSTADDR))
|
||||
switch (ioctl_filter[i].field)
|
||||
{
|
||||
if (ioctl_filter[i].arg[1] != 0x0000FFFF)
|
||||
case WINDIVERT_FILTER_FIELD_IP_SRCADDR:
|
||||
case WINDIVERT_FILTER_FIELD_IP_DSTADDR:
|
||||
if (ioctl_filter[i].arg[1] != 0x0000FFFF)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32:
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
INT idx = (INT)ioctl_filter[i].arg[1];
|
||||
if (idx > UINT16_MAX || idx < -UINT16_MAX)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ioctl_filter[i].arg[1] != 0)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
default:
|
||||
if (ioctl_filter[i].arg[1] != 0)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (ioctl_filter[i].field)
|
||||
@@ -5547,6 +5629,9 @@ static PWINDIVERT_FILTER windivert_filter_compile(
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE:
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_CODE:
|
||||
case WINDIVERT_FILTER_FIELD_PROTOCOL:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD:
|
||||
if (ioctl_filter[i].arg[0] > UINT8_MAX)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
@@ -5577,6 +5662,9 @@ static PWINDIVERT_FILTER windivert_filter_compile(
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_LOCALPORT:
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16:
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16:
|
||||
if (ioctl_filter[i].arg[0] > UINT16_MAX)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
|
||||
+89
-1
@@ -114,6 +114,22 @@ static struct packet pkt_ipv6_exthdrs_udp =
|
||||
static struct test tests[] =
|
||||
{
|
||||
{"event = PACKET", &pkt_echo_request, TRUE},
|
||||
{"packet[0] == 0x45", &pkt_echo_request, TRUE},
|
||||
{"packet[0] == 0x33", &pkt_echo_request, FALSE},
|
||||
{"packet[55] == 0x1b", &pkt_echo_request, TRUE},
|
||||
{"packet[55b] == 0x1b", &pkt_echo_request, TRUE},
|
||||
{"packet[1000] <= 0 || packet[-1000] = 7", &pkt_echo_request, FALSE},
|
||||
{"packet[-1] == 0x37 && packet[-2] == 0x36 && packet[-3] == 0x35 && "
|
||||
"packet[-4] == 0x34", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x4500", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x0045", &pkt_echo_request, FALSE},
|
||||
{"packet16[2b] == 0x0054", &pkt_echo_request, TRUE},
|
||||
{"packet16[1] == 0x0054", &pkt_echo_request, TRUE},
|
||||
{"packet16[0] == 0x4500 && packet16[1] == 0x0054 && "
|
||||
"packet16[-1] == 0x3637", &pkt_echo_request, TRUE},
|
||||
{"packet32[0b] == 0x45000054 && packet32[3b] == 0x54123440 && "
|
||||
"packet32[-4b] == 0x34353637 && packet32[-5b] == 0x33343536",
|
||||
&pkt_echo_request, TRUE},
|
||||
{"outbound and icmp", &pkt_echo_request, TRUE},
|
||||
{"outbound", &pkt_echo_request, TRUE},
|
||||
{"outbound and inbound", &pkt_echo_request, FALSE},
|
||||
@@ -245,6 +261,74 @@ static struct test tests[] =
|
||||
{"(ipv6? tcp and tcp.DstPort = 1234 and (tcp.SrcPort = 999? !tcp.UrgPtr: "
|
||||
"tcp.Syn) or udp: ip and tcp.DstPort == 80)",
|
||||
&pkt_http_request, TRUE},
|
||||
{"packet32[0] = 0x45000209 && packet32[1] = 0x482d4000 && "
|
||||
"packet16[8b] = 0x4006 && packet32[3] = 0x0a0a0a0a && "
|
||||
"packet32[4] = 0x5db8d877 && packet32[5] = 0xa31a0050 && "
|
||||
"packet32[6] = 0x5338ccc2 && packet32[7] = 0x5637b355 && "
|
||||
"packet32[8] = 0x80180073 && packet16[38b] = 0x0000 && "
|
||||
"packet32[10] = 0x0101080a && packet32[11] = 0x002c851b && "
|
||||
"packet32[12] = 0x1b7f3a71 && packet32[13] = 0x47455420 && "
|
||||
"packet32[14] = 0x2f204854 && packet32[15] = 0x54502f31 && "
|
||||
"packet32[16] = 0x2e310d0a && packet32[17] = 0x486f7374 && "
|
||||
"packet32[18] = 0x3a207777 && packet32[19] = 0x772e6578 && "
|
||||
"packet32[20] = 0x616d706c && packet32[21] = 0x652e636f && "
|
||||
"packet32[22] = 0x6d0d0a43 && packet32[23] = 0x6f6e6e65 && "
|
||||
"packet32[24] = 0x6374696f && packet32[25] = 0x6e3a206b && "
|
||||
"packet32[26] = 0x6565702d && packet32[27] = 0x616c6976 && "
|
||||
"packet32[28] = 0x650d0a43 && packet32[29] = 0x61636865 && "
|
||||
"packet32[30] = 0x2d436f6e && packet32[31] = 0x74726f6c && "
|
||||
"packet32[32] = 0x3a206d61 && packet32[33] = 0x782d6167 && "
|
||||
"packet32[34] = 0x653d300d && packet32[35] = 0x0a416363 && "
|
||||
"packet32[36] = 0x6570743a && packet32[37] = 0x20746578 && "
|
||||
"packet32[38] = 0x742f6874 && packet32[39] = 0x6d6c2c61 && "
|
||||
"packet32[40] = 0x70706c69 && packet32[41] = 0x63617469 && "
|
||||
"packet32[42] = 0x6f6e2f78 && packet32[43] = 0x68746d6c && "
|
||||
"packet32[44] = 0x2b786d6c && packet32[45] = 0x2c617070 && "
|
||||
"packet32[46] = 0x6c696361 && packet32[47] = 0x74696f6e && "
|
||||
"packet32[48] = 0x2f786d6c && packet32[49] = 0x3b713d30 && "
|
||||
"packet32[50] = 0x2e392c69 && packet32[51] = 0x6d616765 && "
|
||||
"packet32[52] = 0x2f776562 && packet32[53] = 0x702c2a2f && "
|
||||
"packet32[54] = 0x2a3b713d && packet32[55] = 0x302e380d && "
|
||||
"packet32[56] = 0x0a557365 && packet32[57] = 0x722d4167 && "
|
||||
"packet32[58] = 0x656e743a && packet32[59] = 0x20585858 && "
|
||||
"packet32[60] = 0x58585858 && packet32[61] = 0x58585858 && "
|
||||
"packet32[62] = 0x58585858 && packet32[63] = 0x58585858 && "
|
||||
"packet32[64] = 0x58585858 && packet32[65] = 0x58585858 && "
|
||||
"packet32[66] = 0x58585858 && packet32[67] = 0x58585858 && "
|
||||
"packet32[68] = 0x58585858 && packet32[69] = 0x58585858 && "
|
||||
"packet32[70] = 0x58585858 && packet32[71] = 0x58585858 && "
|
||||
"packet32[72] = 0x58585858 && packet32[73] = 0x58585858 && "
|
||||
"packet32[74] = 0x58585858 && packet32[75] = 0x58585858 && "
|
||||
"packet32[76] = 0x58585858 && packet32[77] = 0x58585858 && "
|
||||
"packet32[78] = 0x58585858 && packet32[79] = 0x58585858 && "
|
||||
"packet32[80] = 0x58585858 && packet32[81] = 0x58585858 && "
|
||||
"packet32[82] = 0x58585858 && packet32[83] = 0x58585858 && "
|
||||
"packet32[84] = 0x58585858 && packet32[85] = 0x58585858 && "
|
||||
"packet32[86] = 0x58585858 && packet32[87] = 0x58585858 && "
|
||||
"packet32[88] = 0x58585858 && packet32[89] = 0x58585858 && "
|
||||
"packet32[90] = 0x58585858 && packet32[91] = 0x58585858 && "
|
||||
"packet32[92] = 0x58580d0a && packet32[93] = 0x41636365 && "
|
||||
"packet32[94] = 0x70742d45 && packet32[95] = 0x6e636f64 && "
|
||||
"packet32[96] = 0x696e673a && packet32[97] = 0x20677a69 && "
|
||||
"packet32[98] = 0x702c6465 && packet32[99] = 0x666c6174 && "
|
||||
"packet32[100] = 0x652c7364 && packet32[101] = 0x63680d0a && "
|
||||
"packet32[102] = 0x41636365 && packet32[103] = 0x70742d4c && "
|
||||
"packet32[104] = 0x616e6775 && packet32[105] = 0x6167653a && "
|
||||
"packet32[106] = 0x20656e2d && packet32[107] = 0x55532c65 && "
|
||||
"packet32[108] = 0x6e3b713d && packet32[109] = 0x302e380d && "
|
||||
"packet32[110] = 0x0a49662d && packet32[111] = 0x4e6f6e65 && "
|
||||
"packet32[112] = 0x2d4d6174 && packet32[113] = 0x63683a20 && "
|
||||
"packet32[114] = 0x22333333 && packet32[115] = 0x33333333 && "
|
||||
"packet32[116] = 0x3333220d && packet32[117] = 0x0a49662d && "
|
||||
"packet32[118] = 0x4d6f6469 && packet32[119] = 0x66696564 && "
|
||||
"packet32[120] = 0x2d53696e && packet32[121] = 0x63653a20 && "
|
||||
"packet32[122] = 0x4672692c && packet32[123] = 0x20303320 && "
|
||||
"packet32[124] = 0x41756720 && packet32[125] = 0x32303134 && "
|
||||
"packet32[126] = 0x2031333a && packet32[127] = 0x33333a33 && "
|
||||
"packet32[128] = 0x3320474d && packet32[129] = 0x540d0a0d && "
|
||||
"packet[-1] = 0x0a", &pkt_http_request, TRUE},
|
||||
{"tcp.Payload16[-1] == 0x0d0a", &pkt_http_request, TRUE},
|
||||
{"tcp.Payload32[-2] == 0x20474d54", &pkt_http_request, TRUE},
|
||||
{"udp", &pkt_dns_request, TRUE},
|
||||
{"udp && udp.SrcPort > 1 && ipv6", &pkt_dns_request, FALSE},
|
||||
{"udp.DstPort == 53", &pkt_dns_request, TRUE},
|
||||
@@ -260,6 +344,10 @@ static struct test tests[] =
|
||||
{"ip.DstAddr == ::ffff:8.8.4.4", &pkt_dns_request, TRUE},
|
||||
{"ip.DstAddr == ::0:ffff:8.8.4.4", &pkt_dns_request, TRUE},
|
||||
{"udp.PayloadLength == 29", &pkt_dns_request, TRUE},
|
||||
{"udp.Payload16[-1] == 0x0001 && udp.Payload16[-2] == 0x0001",
|
||||
&pkt_dns_request, TRUE},
|
||||
{"packet16[-1] == 0x0001 && packet16[-2] == 0x0001",
|
||||
&pkt_dns_request, TRUE},
|
||||
{"ipv6", &pkt_ipv6_tcp_syn, TRUE},
|
||||
{"ip", &pkt_ipv6_tcp_syn, FALSE},
|
||||
{"tcp.Syn", &pkt_ipv6_tcp_syn, TRUE},
|
||||
@@ -351,7 +439,7 @@ int main(void)
|
||||
// Run the test:
|
||||
BOOL res = run_test(upper_handle, filter, packet, packet_len, match);
|
||||
|
||||
printf("%.2u ", i);
|
||||
printf("%.3u ", i);
|
||||
if (res)
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
|
||||
Reference in New Issue
Block a user