diff --git a/CHANGELOG b/CHANGELOG index 71dfc1c..c2bd62b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -136,16 +136,21 @@ WinDivert 2.0.0-rc * addr.Layer: The WINDIVERT_LAYER_* value for the handle. * addr.Event: A WINDIVERT_EVENT_* value representing the event (see below). + * addr.Sniffed: Indicates that the event was sniffed. * addr.Outbound: Replaces addr.Direction. * addr.IPv6: Indicates an IPv6 packet. * addr.Network.IfIdx: Replaces addr.IfIdx. * addr.Network.SubIfIdx: Replaces addr.SubIfIdx. + * addr.Flow.EndpointId: The endpoint ID of the flow. + * addr.Flow.ParentEndpointId: The parent endpoint ID of the flow. * addr.Flow.ProcessId: The ID of process that created the flow. * addr.Flow.LocalAddr: The flow's local address. * addr.Flow.RemoteAddr: The flow's remote address. * addr.Flow.LocalPort: The flow's local port. * addr.Flow.RemotePort: The flow's remote port. * addr.Flow.Protocol: The flow's protocol. + * addr.Socket.EndpointId: The endpoint ID of the operation. + * addr.Socket.ParentEndpointId: The parent endpoint ID of the operation. * addr.Socket.ProcessId: The ID of process that created the socket. * addr.Socket.LocalAddr: The socket's local address. * addr.Socket.RemoteAddr: The socket's remote address. @@ -167,17 +172,14 @@ WinDivert 2.0.0-rc deleted. * WINDIVERT_EVENT_SOCKET_BIND: (SOCKET layer) a socket bind() operation occurred. - * 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_SOCKET_CLOSE: (SOCKET layer) a socket endpoint is + closed. * WINDIVERT_EVENT_REFLECT_OPEN: (REFLECT layer) a WinDivertOpen() operation occurred. * WINDIVERT_EVENT_REFLECT_CLOSE: (REFLECT layer) a WinDivertClose() @@ -227,12 +229,11 @@ WinDivert 2.0.0-rc * 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. + * CLOSE: (SOCKET layer) equal to WINDIVERT_EVENT_SOCKET_CLOSE. * 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. diff --git a/dll/windivert.c b/dll/windivert.c index 1ec6c41..0885e3f 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -65,8 +65,10 @@ static BOOLEAN WinDivertStrLen(const wchar_t *s, size_t maxlen, static BOOLEAN WinDivertStrCpy(wchar_t *dst, size_t dstlen, const wchar_t *src); static int WinDivertStrCmp(const char *s, const char *t); -static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr); -static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr); +static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr, + UINT size); +static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr, + UINT size, BOOL prefix); /* * Misc. @@ -379,12 +381,11 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer, UINT obj_len; ERROR comp_err; DWORD err; - BOOL sniff; HANDLE handle; UINT64 filter_flags; WINDIVERT_IOCTL ioctl; WINDIVERT_VERSION version; - + // Parameter checking. switch (layer) { @@ -418,8 +419,7 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer, SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } - sniff = ((flags & WINDIVERT_FLAG_SNIFF) != 0); - filter_flags = WinDivertAnalyzeFilter(layer, sniff, object, obj_len); + filter_flags = WinDivertAnalyzeFilter(layer, object, obj_len); // Attempt to open the WinDivert device: handle = CreateFile(L"\\\\.\\" WINDIVERT_DEVICE_NAME, @@ -711,66 +711,112 @@ static int WinDivertStrCmp(const char *s, const char *t) } } -static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr) +static BOOLEAN WinDivertMul128(UINT32 *n, UINT32 m) +{ + UINT64 n64 = (UINT64)n[0] * (UINT64)m; + n[0] = (UINT32)n64; + n64 = (UINT64)n[1] * (UINT64)m + (n64 >> 32); + n[1] = (UINT32)n64; + n64 = (UINT64)n[2] * (UINT64)m + (n64 >> 32); + n[2] = (UINT32)n64; + n64 = (UINT64)n[3] * (UINT64)m + (n64 >> 32); + n[3] = (UINT32)n64; + return ((n64 >> 32) == 0); +} + +static BOOLEAN WinDivertAdd128(UINT32 *n, UINT32 a) +{ + UINT64 n64 = (UINT64)n[0] + (UINT64)a; + n[0] = (UINT32)n64; + n64 = (UINT64)n[1] + (n64 >> 32); + n[1] = (UINT32)n64; + n64 = (UINT64)n[2] + (n64 >> 32); + n[2] = (UINT32)n64; + n64 = (UINT64)n[3] + (n64 >> 32); + n[3] = (UINT32)n64; + return ((n64 >> 32) == 0); +} + +static BOOLEAN WinDivertAToI(const char *str, char **endptr, UINT32 *intptr, + UINT size) { size_t i = 0; - UINT32 num = 0, num0; - if (str[i] == '\0') - { - return FALSE; - } + UINT32 n[4] = {0}; + BOOLEAN result = TRUE; for (; str[i] && isdigit(str[i]); i++) { - num0 = num; - num *= 10; - num += (UINT32)(str[i] - '0'); - if (num0 > num) + if (!WinDivertMul128(n, 10) || !WinDivertAdd128(n, str[i] - '0')) { return FALSE; } } + if (i == 0) + { + return FALSE; + } if (endptr != NULL) { *endptr = (char *)str + i; } - *intptr = num; - return TRUE; + for (i = 0; i < size; i++) + { + intptr[i] = n[i]; + } + for (; result && i < size && i < 4; i++) + { + result = result && (n[i] == 0); + } + return result; } -static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr) +static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr, + UINT size, BOOL prefix) { size_t i = 0; - UINT32 num = 0, num0; - if (str[i] == '\0') + UINT32 n[4] = {0}, dig; + BOOLEAN result = TRUE; + if (prefix) { - return FALSE; - } - if (str[i] == '0' && str[i+1] == 'x') - { - i += 2; - } - for (; str[i] && WinDivertIsXDigit(str[i]); i++) - { - num0 = num; - num *= 16; - if (isdigit(str[i])) + if (str[i] == '0' && str[i+1] == 'x') { - num += (UINT32)(str[i] - '0'); + i += 2; } else { - num += (UINT32)(WinDivertToLower(str[i]) - 'a') + 0x0A; + return FALSE; } - if (num0 > num) + } + for (; str[i] && WinDivertIsXDigit(str[i]); i++) + { + if (isdigit(str[i])) + { + dig = (UINT32)(str[i] - '0'); + } + else + { + dig = (UINT32)(WinDivertToLower(str[i]) - 'a') + 0x0A; + } + if (!WinDivertMul128(n, 16) || !WinDivertAdd128(n, dig)) { return FALSE; } } + if (i == 0) + { + return FALSE; + } if (endptr != NULL) { *endptr = (char *)str + i; } - *intptr = num; - return TRUE; + for (i = 0; i < size; i++) + { + intptr[i] = n[i]; + } + for (; result && i < size && i < 4; i++) + { + result = result && (n[i] == 0); + } + return result; } diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 3355433..4dac77b 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -136,6 +136,8 @@ typedef enum TOKEN_LOCAL_PORT, TOKEN_REMOTE_PORT, TOKEN_PROTOCOL, + TOKEN_ENDPOINT_ID, + TOKEN_PARENT_ENDPOINT_ID, TOKEN_LAYER, TOKEN_PRIORITY, TOKEN_FLOW, @@ -147,9 +149,7 @@ 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, @@ -181,7 +181,7 @@ typedef struct UINT pos; UINT32 val[4]; } TOKEN; -#define TOKEN_MAXLEN 32 +#define TOKEN_MAXLEN 40 typedef struct { @@ -216,6 +216,10 @@ typedef struct #define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \ WINDIVERT_LAYER_FLAG_FLOW | \ WINDIVERT_LAYER_FLAG_SOCKET) +#define L__FS_ (WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET) +#define L___SR (WINDIVERT_LAYER_FLAG_SOCKET | \ + WINDIVERT_LAYER_FLAG_REFLECT) #define L__FSR (WINDIVERT_LAYER_FLAG_FLOW | \ WINDIVERT_LAYER_FLAG_SOCKET | \ WINDIVERT_LAYER_FLAG_REFLECT) @@ -241,7 +245,7 @@ struct EXPR }; UINT8 kind; UINT8 count; - BOOL neg; + BOOLEAN neg; UINT16 succ; UINT16 fail; }; @@ -281,6 +285,7 @@ static PEXPR WinDivertParseFilter(HANDLE pool, TOKEN *toks, UINT *i, INT depth, BOOL and, PERROR error); static BOOL WinDivertCondExecFilter(PWINDIVERT_FILTER filter, UINT length, UINT8 field, UINT32 arg); +static int WinDivertBigNumCompare(const UINT32 *a, const UINT32 *b, BOOL big); static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream, PWINDIVERT_FILTER filter, UINT *length); static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, @@ -302,7 +307,7 @@ extern BOOL WinDivertHelperParseIPv4Address(const char *str, UINT32 *addr_ptr) for (i = 0; i < 4; i++) { - if (!WinDivertAToI(str, (char **)&str, &part) || part > UINT8_MAX) + if (!WinDivertAToI(str, (char **)&str, &part, 1) || part > UINT8_MAX) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; @@ -396,7 +401,7 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr) SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - WinDivertAToX(part_str, NULL, &part); + WinDivertAToX(part_str, NULL, &part, /*size=*/1, /*prefix=*/FALSE); if (left) { laddr[i++] = (UINT16)part; @@ -516,15 +521,9 @@ 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); @@ -535,8 +534,17 @@ static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer, *val = WINDIVERT_EVENT_REFLECT_OPEN; return (layer == WINDIVERT_LAYER_REFLECT); case TOKEN_EVENT_CLOSE: - *val = WINDIVERT_EVENT_REFLECT_CLOSE; - return (layer == WINDIVERT_LAYER_REFLECT); + switch (layer) + { + case WINDIVERT_LAYER_SOCKET: + *val = WINDIVERT_EVENT_SOCKET_CLOSE; + return TRUE; + case WINDIVERT_LAYER_REFLECT: + *val = WINDIVERT_EVENT_REFLECT_CLOSE; + return TRUE; + default: + return FALSE; + } default: return FALSE; } @@ -552,10 +560,9 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, { {"ACCEPT", TOKEN_EVENT_ACCEPT, L___S_}, {"BIND", TOKEN_EVENT_BIND, L___S_}, - {"CLOSE", TOKEN_EVENT_CLOSE, L____R}, + {"CLOSE", TOKEN_EVENT_CLOSE, L___SR}, {"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_}, @@ -565,8 +572,8 @@ 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}, + {"endpointId", TOKEN_ENDPOINT_ID, L__FS_}, {"event", TOKEN_EVENT, LNMFSR}, {"false", TOKEN_FALSE, LNMFSR}, {"icmp", TOKEN_ICMP, LNMFS_}, @@ -613,6 +620,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, {"packet", TOKEN_PACKET, LNM___}, {"packet16", TOKEN_PACKET16, LNM___}, {"packet32", TOKEN_PACKET32, LNM___}, + {"parentEndpointId", TOKEN_PARENT_ENDPOINT_ID, L__FS_}, {"priority", TOKEN_PRIORITY, L____R}, {"processId", TOKEN_PROCESS_ID, L__FSR}, {"protocol", TOKEN_PROTOCOL, LN_FS_}, @@ -762,7 +770,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, token[0] = c; if (WinDivertIsAlNum(c) || c == '.' || c == ':' || c == '_') { - UINT32 num; + UINT32 num[4]; char *end; for (j = 1; j < TOKEN_MAXLEN && (WinDivertIsAlNum(filter[i]) || filter[i] == '.' || filter[i] == ':' || filter[i] == '_'); @@ -808,17 +816,25 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, continue; } + // Check for 'b': + if (token[0] == 'b' && token[1] == '\0') + { + tokens[tp].kind = TOKEN_BYTES; + continue; + } + // Check for base 10 number: - if (WinDivertAToI(token, &end, &num)) + if (WinDivertAToI(token, &end, num, sizeof(num)/sizeof(num[0]))) { BOOL b = (*end == 'b' && *(end+1) == '\0'); if (*end == '\0' || b) { - tokens[tp].kind = TOKEN_NUMBER; - tokens[tp].val[0] = num; + tokens[tp].kind = TOKEN_NUMBER; + memcpy(tokens[tp].val, num, sizeof(tokens[tp].val)); tp++; if (b) { + memset(tokens[tp].val, 0, sizeof(tokens[tp].val)); tokens[tp].kind = TOKEN_BYTES; tp++; } @@ -828,13 +844,16 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, // Check for base 16 number: if (token[0] == '0' && token[1] == 'x' && - WinDivertAToX(token, &end, &num) && *end == '\0') + WinDivertAToX(token, &end, num, sizeof(num)/sizeof(num[0]), + /*prefix=*/TRUE) && + *end == '\0') { - tokens[tp].kind = TOKEN_NUMBER; - tokens[tp].val[0] = num; + tokens[tp].kind = TOKEN_NUMBER; + memcpy(tokens[tp].val, num, sizeof(tokens[tp].val)); tp++; continue; } + // Check for IPv4 address: if (WinDivertHelperParseIPv4Address(token, tokens[tp].val)) { @@ -942,6 +961,8 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error) {{{0}}, TOKEN_LOCAL_PORT}, {{{0}}, TOKEN_REMOTE_PORT}, {{{0}}, TOKEN_PROTOCOL}, + {{{0}}, TOKEN_ENDPOINT_ID}, + {{{0}}, TOKEN_PARENT_ENDPOINT_ID}, {{{0}}, TOKEN_LAYER}, {{{0}}, TOKEN_PRIORITY}, }; @@ -1098,6 +1119,8 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) case TOKEN_LOCAL_PORT: case TOKEN_REMOTE_PORT: case TOKEN_PROTOCOL: + case TOKEN_ENDPOINT_ID: + case TOKEN_PARENT_ENDPOINT_ID: case TOKEN_LAYER: case TOKEN_IP_HDR_LENGTH: case TOKEN_IP_TOS: @@ -1182,7 +1205,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) 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) + toks[*i].val[1] != 0 || toks[*i].val[0] > WINDIVERT_MTU_MAX) { *error = MAKE_ERROR(WINDIVERT_ERROR_INDEX_OOB, toks[*i].pos); return NULL; @@ -1385,28 +1408,29 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res) { PEXPR var = test->arg[0]; PEXPR val = test->arg[1]; - UINT32 val32 = val->val[0]; - BOOL big = (val->val[1] != 0 || val->val[2] != 0 || val->val[3] != 0); - UINT32 lb, ub; + UINT32 lb[4] = {0}, ub[4] = {0}; + int result_lb, result_ub; + BOOL eq = FALSE; + switch (var->kind) { case TOKEN_ZERO: - lb = ub = 0; + case TOKEN_FALSE: + eq = TRUE; + lb[0] = ub[0] = 0; break; case TOKEN_TRUE: - lb = ub = 1; - break; - case TOKEN_FALSE: - lb = ub = 0; + eq = TRUE; + lb[0] = ub[0] = 1; break; case TOKEN_LAYER: - lb = 0; ub = WINDIVERT_LAYER_MAX; + lb[0] = 0; ub[0] = WINDIVERT_LAYER_MAX; break; case TOKEN_PRIORITY: - lb = 0; ub = WINDIVERT_PRIORITY_MAX; + lb[0] = 0; ub[0] = WINDIVERT_PRIORITY_MAX; break; case TOKEN_EVENT: - lb = 0; ub = WINDIVERT_EVENT_MAX; + lb[0] = 0; ub[0] = WINDIVERT_EVENT_MAX; break; case TOKEN_INBOUND: case TOKEN_OUTBOUND: @@ -1424,11 +1448,11 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res) case TOKEN_TCP_RST: case TOKEN_TCP_SYN: case TOKEN_TCP_FIN: - lb = 0; ub = 1; + lb[0] = 0; ub[0] = 1; break; case TOKEN_IP_HDR_LENGTH: case TOKEN_TCP_HDR_LENGTH: - lb = 0; ub = 0x0F; + lb[0] = 0; ub[0] = 0x0F; break; case TOKEN_IP_TTL: case TOKEN_IP_PROTOCOL: @@ -1444,10 +1468,10 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res) case TOKEN_TCP_PAYLOAD: case TOKEN_UDP_PAYLOAD: case TOKEN_RANDOM8: - lb = 0; ub = 0xFF; + lb[0] = 0; ub[0] = 0xFF; break; case TOKEN_IP_FRAG_OFF: - lb = 0; ub = 0x1FFF; + lb[0] = 0; ub[0] = 0x1FFF; break; case TOKEN_IP_TOS: case TOKEN_IP_LENGTH: @@ -1473,90 +1497,105 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res) case TOKEN_TCP_PAYLOAD16: case TOKEN_UDP_PAYLOAD16: case TOKEN_RANDOM16: - lb = 0; ub = 0xFFFF; + lb[0] = 0; ub[0] = 0xFFFF; break; case TOKEN_IPV6_FLOW_LABEL: - lb = 0; ub = 0x000FFFFF; + lb[0] = 0; ub[0] = 0x000FFFFF; break; case TOKEN_IP_SRC_ADDR: case TOKEN_IP_DST_ADDR: + lb[0] = 0; + lb[1] = 0xFFFF; + ub[0] = 0xFFFFFFFF; + ub[1] = 0xFFFF; + break; case TOKEN_IPV6_SRC_ADDR: case TOKEN_IPV6_DST_ADDR: case TOKEN_LOCAL_ADDR: case TOKEN_REMOTE_ADDR: - return FALSE; + lb[0] = lb[1] = lb[2] = lb[3] = 0; + ub[0] = ub[1] = ub[2] = ub[3] = 0xFFFFFFFF; + break; + case TOKEN_ENDPOINT_ID: + case TOKEN_PARENT_ENDPOINT_ID: + lb[0] = lb[1] = 0; + ub[0] = ub[1] = 0xFFFFFFFF; + break; default: - lb = 0; ub = 0xFFFFFFFF; + lb[0] = 0; ub[0] = 0xFFFFFFFF; + break; } + result_lb = WinDivertBigNumCompare(val->val, lb, /*big=*/TRUE); + result_ub = WinDivertBigNumCompare(val->val, ub, /*big=*/TRUE); switch (test->kind) { case TOKEN_EQ: - if (big || val32 < lb || val32 > ub) + if (result_lb < 0 || result_ub > 0) { *res = FALSE; return TRUE; } - if (lb == ub && val32 == lb) + if (eq && result_lb == 0) { *res = TRUE; return TRUE; } return FALSE; case TOKEN_NEQ: - if (big || val32 < lb || val32 > ub) + if (result_lb < 0 || result_ub > 0) { *res = TRUE; return TRUE; } - if (lb == ub && val32 == lb) + if (eq && result_lb == 0) { *res = FALSE; return TRUE; } return FALSE; case TOKEN_LT: - if (big || val32 > ub) + if (result_ub > 0) { *res = TRUE; return TRUE; } - if (val32 <= lb) + if (result_lb <= 0) { *res = FALSE; return TRUE; } return FALSE; case TOKEN_LEQ: - if (big || val32 >= ub) + if (result_ub >= 0) { *res = TRUE; return TRUE; } - if (val32 < lb) + if (result_lb < 0) { *res = FALSE; return TRUE; } return FALSE; case TOKEN_GT: - if (big || val32 >= ub) + if (result_ub >= 0) { *res = FALSE; return TRUE; } - if (val32 < lb) + if (result_lb < 0) { *res = TRUE; return TRUE; } return FALSE; case TOKEN_GEQ: - if (big || val32 > ub) + if (result_ub > 0) { *res = FALSE; return TRUE; } - if (val32 <= lb) + if (result_lb <= 0) { *res = TRUE; return TRUE; @@ -1741,6 +1780,14 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, case TOKEN_PROTOCOL: object->field = WINDIVERT_FILTER_FIELD_PROTOCOL; break; + case TOKEN_ENDPOINT_ID: + object->field = WINDIVERT_FILTER_FIELD_ENDPOINTID; + big = TRUE; + break; + case TOKEN_PARENT_ENDPOINT_ID: + object->field = WINDIVERT_FILTER_FIELD_PARENTENDPOINTID; + big = TRUE; + break; case TOKEN_LAYER: object->field = WINDIVERT_FILTER_FIELD_LAYER; break; @@ -1978,7 +2025,7 @@ static void WinDivertEmitFilter(PEXPR *stack, UINT len, UINT16 label, * Analyze a filter object. */ static UINT64 WinDivertAnalyzeFilter(WINDIVERT_LAYER layer, - BOOL sniff, PWINDIVERT_FILTER filter, UINT length) + PWINDIVERT_FILTER filter, UINT length) { BOOL result; UINT64 flags = 0; @@ -2051,25 +2098,12 @@ 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_CLOSE); + flags |= (result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE: 0); result = WinDivertCondExecFilter(filter, length, WINDIVERT_FILTER_FIELD_EVENT, WINDIVERT_EVENT_SOCKET_LISTEN); flags |= (result? WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN: 0); @@ -2565,6 +2599,11 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, addr->Layer == WINDIVERT_LAYER_FLOW || addr->Layer == WINDIVERT_LAYER_SOCKET); break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + pass = (addr->Layer == WINDIVERT_LAYER_FLOW || + addr->Layer == WINDIVERT_LAYER_SOCKET); + break; case WINDIVERT_FILTER_FIELD_PROCESSID: pass = (addr->Layer == WINDIVERT_LAYER_FLOW || addr->Layer == WINDIVERT_LAYER_SOCKET || @@ -3149,6 +3188,42 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, return FALSE; } break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + big = TRUE; + val[3] = val[2] = 0; + switch (addr->Layer) + { + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)addr->Flow.EndpointId; + val[1] = (UINT32)(addr->Flow.EndpointId >> 32); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)addr->Socket.EndpointId; + val[1] = (UINT32)(addr->Socket.EndpointId >> 32); + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + break; + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + big = TRUE; + val[3] = val[2] = 0; + switch (addr->Layer) + { + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)addr->Flow.ParentEndpointId; + val[1] = (UINT32)(addr->Flow.ParentEndpointId >> 32); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)addr->Socket.ParentEndpointId; + val[1] = (UINT32)(addr->Socket.ParentEndpointId >> 32); + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + break; case WINDIVERT_FILTER_FIELD_PROCESSID: switch (addr->Layer) { @@ -3344,6 +3419,14 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream, } } break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + if (!WinDivertDeserializeNumber(stream, 7, &filter->arg[1])) + { + return FALSE; + } + filter->arg[2] = filter->arg[3] = 0; + break; case WINDIVERT_FILTER_FIELD_IP_SRCADDR: case WINDIVERT_FILTER_FIELD_IP_DSTADDR: filter->arg[1] = 0x0000FFFF; @@ -3641,6 +3724,10 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) kind = TOKEN_REMOTE_PORT; break; case WINDIVERT_FILTER_FIELD_PROTOCOL: kind = TOKEN_PROTOCOL; break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + kind = TOKEN_ENDPOINT_ID; break; + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + kind = TOKEN_PARENT_ENDPOINT_ID; break; case WINDIVERT_FILTER_FIELD_LAYER: kind = TOKEN_LAYER; break; case WINDIVERT_FILTER_FIELD_PRIORITY: @@ -3686,7 +3773,7 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) } break; } - + switch (test->test) { case WINDIVERT_FILTER_TEST_EQ: @@ -3956,9 +4043,9 @@ static PEXPR WinDivertCoalesceExpr(HANDLE pool, PEXPR *exprs, UINT8 i) /* * Format a decimal number. */ -static void WinDivertFormatNumber(PWINDIVERT_STREAM stream, UINT32 val) +static void WinDivertFormatDecNumber(PWINDIVERT_STREAM stream, UINT64 val) { - UINT64 r = 1000000000, dig; + UINT64 r = 10000000000000000000ull, dig; BOOL zeroes = FALSE; while (r != 0) @@ -3978,22 +4065,48 @@ static void WinDivertFormatNumber(PWINDIVERT_STREAM stream, UINT32 val) /* * Format a hexidecimal number. */ -static void WinDivertFormatHexNumber(PWINDIVERT_STREAM stream, UINT32 val) +static void WinDivertFormatHexNumber(PWINDIVERT_STREAM stream, UINT32 *val) { - INT s = 28; + INT i, s; UINT32 dig; BOOL zeroes = FALSE; - while (s >= 0) + for (i = 3; val[i] == 0 && i >= 1; i--) + ; + for (; i >= 0; i--) { - dig = (val & ((UINT32)0xF << s)) >> s; - s -= 4; - if (dig == 0 && !zeroes && s >= 0) + s = 28; + while (s >= 0) { - continue; + dig = (val[i] & ((UINT32)0xF << s)) >> s; + s -= 4; + if (dig == 0 && !zeroes) + { + continue; + } + WinDivertPutChar(stream, (dig <= 9? '0' + dig: 'a' + (dig - 10))); + zeroes = TRUE; } - WinDivertPutChar(stream, (dig <= 9? '0' + dig: 'a' + (dig - 10))); - zeroes = TRUE; + } + if (!zeroes) + { + WinDivertPutChar(stream, '0'); + } +} + +/* + * Format a big number. + */ +static void WinDivertFormatNumber(PWINDIVERT_STREAM stream, UINT32 *val) +{ + if (val[2] == 0 && val[3] == 0) + { + UINT64 val64 = ((UINT64)val[1] << 32) | (UINT64)val[0]; + WinDivertFormatDecNumber(stream, val64); + } + else + { + WinDivertFormatHexNumber(stream, val); } } @@ -4002,13 +4115,13 @@ static void WinDivertFormatHexNumber(PWINDIVERT_STREAM stream, UINT32 val) */ static void WinDivertFormatIPv4Addr(PWINDIVERT_STREAM stream, UINT32 addr) { - WinDivertFormatNumber(stream, (addr & 0xFF000000) >> 24); + WinDivertFormatDecNumber(stream, (addr & 0xFF000000) >> 24); WinDivertPutChar(stream, '.'); - WinDivertFormatNumber(stream, (addr & 0x00FF0000) >> 16); + WinDivertFormatDecNumber(stream, (addr & 0x00FF0000) >> 16); WinDivertPutChar(stream, '.'); - WinDivertFormatNumber(stream, (addr & 0x0000FF00) >> 8); + WinDivertFormatDecNumber(stream, (addr & 0x0000FF00) >> 8); WinDivertPutChar(stream, '.'); - WinDivertFormatNumber(stream, (addr & 0x000000FF) >> 0); + WinDivertFormatDecNumber(stream, (addr & 0x000000FF) >> 0); } /* @@ -4019,6 +4132,7 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream, { INT i, z_curr, z_count, z_start, z_max; UINT16 addr[8]; + UINT32 part[4] = {0}; // IPv4 special case: if (addr32[3] == 0 && addr32[2] == 0 && addr32[1] == 0x0000FFFF) @@ -4056,7 +4170,8 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream, i -= (z_max-1); continue; } - WinDivertFormatHexNumber(stream, addr[i]); + part[0] = (UINT32)addr[i]; + WinDivertFormatHexNumber(stream, part); WinDivertPutString(stream, (i != 0? ":": "")); } } @@ -4235,7 +4350,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case WINDIVERT_LAYER_REFLECT: WinDivertPutString(stream, "REFLECT"); break; default: - WinDivertFormatNumber(stream, val->val[0]); break; + WinDivertFormatDecNumber(stream, val->val[0]); break; } } else if (is_priority) @@ -4246,7 +4361,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, { WinDivertPutChar(stream, '-'); } - WinDivertFormatNumber(stream, (val32 < 0? -val32: val32)); + WinDivertFormatDecNumber(stream, (val32 < 0? -val32: val32)); } else if (is_event) { @@ -4260,7 +4375,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, } else { - WinDivertFormatNumber(stream, val->val[0]); + WinDivertFormatDecNumber(stream, val->val[0]); } break; case WINDIVERT_LAYER_FLOW: @@ -4271,7 +4386,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case WINDIVERT_EVENT_FLOW_DELETED: WinDivertPutString(stream, "DELETED"); break; default: - WinDivertFormatNumber(stream, val->val[0]); break; + WinDivertFormatDecNumber(stream, val->val[0]); break; } break; case WINDIVERT_LAYER_SOCKET: @@ -4279,18 +4394,16 @@ 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: WinDivertPutString(stream, "ACCEPT"); break; + case WINDIVERT_EVENT_SOCKET_CLOSE: + WinDivertPutString(stream, "CLOSE"); break; default: - WinDivertFormatNumber(stream, val->val[0]); break; + WinDivertFormatDecNumber(stream, val->val[0]); break; } break; case WINDIVERT_LAYER_REFLECT: @@ -4301,21 +4414,21 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case WINDIVERT_EVENT_REFLECT_CLOSE: WinDivertPutString(stream, "CLOSE"); break; default: - WinDivertFormatNumber(stream, val->val[0]); break; + WinDivertFormatDecNumber(stream, val->val[0]); break; } break; default: - WinDivertFormatNumber(stream, val->val[0]); break; + WinDivertFormatDecNumber(stream, val->val[0]); break; } } else if (is_hex) { WinDivertPutString(stream, "0x"); - WinDivertFormatHexNumber(stream, val->val[0]); + WinDivertFormatHexNumber(stream, val->val); } else { - WinDivertFormatNumber(stream, val->val[0]); + WinDivertFormatNumber(stream, val->val); } } @@ -4548,12 +4661,16 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutString(stream, "remotePort"); return; case TOKEN_PROTOCOL: WinDivertPutString(stream, "protocol"); return; + case TOKEN_ENDPOINT_ID: + WinDivertPutString(stream, "endpointId"); return; + case TOKEN_PARENT_ENDPOINT_ID: + WinDivertPutString(stream, "parentEndpointId"); return; case TOKEN_LAYER: WinDivertPutString(stream, "layer"); return; case TOKEN_PRIORITY: WinDivertPutString(stream, "priority"); return; case TOKEN_NUMBER: - WinDivertFormatNumber(stream, expr->val[0]); return; + WinDivertFormatNumber(stream, expr->val); return; } WinDivertPutChar(stream, '['); @@ -4563,7 +4680,7 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutChar(stream, '-'); idx = -idx; } - WinDivertFormatNumber(stream, (UINT32)idx); + WinDivertFormatDecNumber(stream, (UINT64)idx); WinDivertPutString(stream, "b]"); } diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index 9f1b190..c3cdf83 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -207,6 +207,10 @@ static void WinDivertSerializeTest(PWINDIVERT_STREAM stream, WinDivertSerializeNumber(stream, filter->arg[i]); } break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + WinDivertSerializeNumber(stream, filter->arg[1]); + break; case WINDIVERT_FILTER_FIELD_PACKET: case WINDIVERT_FILTER_FIELD_PACKET16: case WINDIVERT_FILTER_FIELD_PACKET32: diff --git a/doc/windivert.html b/doc/windivert.html index 875f772..6ca08b7 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -428,11 +428,10 @@ typedef enum WINDIVERT_EVENT_FLOW_ESTABLISHED, WINDIVERT_EVENT_FLOW_DELETED, WINDIVERT_EVENT_SOCKET_BIND, - WINDIVERT_EVENT_SOCKET_UNBIND, WINDIVERT_EVENT_SOCKET_CONNECT, - WINDIVERT_EVENT_SOCKET_DISCONNECT, WINDIVERT_EVENT_SOCKET_LISTEN, WINDIVERT_EVENT_SOCKET_ACCEPT, + WINDIVERT_EVENT_SOCKET_CLOSE, WINDIVERT_EVENT_REFLECT_OPEN, WINDIVERT_EVENT_REFLECT_CLOSE, } WINDIVERT_EVENT, *PWINDIVERT_EVENT; @@ -517,14 +516,6 @@ A bind() operation. -WINDIVERT_EVENT_SOCKET_UNBIND - - -A previous binding is removed. -This event cannot be blocked. - - - WINDIVERT_EVENT_SOCKET_CONNECT @@ -533,15 +524,6 @@ A connect() operation. -WINDIVERT_EVENT_SOCKET_DISCONNECT - - -A previous connection is terminated. -This event cannot be blocked. - - - - WINDIVERT_EVENT_SOCKET_LISTEN @@ -556,6 +538,15 @@ A listen() operation. An accept() operation. + + +WINDIVERT_EVENT_SOCKET_CLOSE + + +A socket endpoint is closed. +This corresponds to a previous binding being released, or an established +connection being terminated. +The event cannot be blocked. @@ -602,6 +593,8 @@ typedef struct typedef struct { + UINT64 Endpoint; + UINT64 ParentEndpoint; UINT32 ProcessId; UINT32 LocalAddr[4]; UINT32 RemoteAddr[4]; @@ -612,6 +605,8 @@ typedef struct typedef struct { + UINT64 Endpoint; + UINT64 ParentEndpoint; UINT32 ProcessId; UINT32 LocalAddr[4]; UINT32 RemoteAddr[4]; @@ -634,6 +629,7 @@ typedef struct INT64 Timestamp; UINT64 Layer:8; UINT64 Event:8; + UINT64 Sniffed:1; UINT64 Outbound:1; UINT64 Loopback:1; UINT64 Impostor:1; @@ -657,6 +653,8 @@ typedef struct
  • Timestamp: A timestamp indicating when event occurred.
  • Layer: The handle's layer (WINDIVERT_LAYER_*).
  • Event: The captured event (WINDIVERT_EVENT_*).
  • +
  • Sniffed: Set to 1 if the event was + sniffed (i.e., not blocked), 0 otherwise..
  • Outbound: Set to 1 for outbound packets/event, 0 for inbound or otherwise.
  • Loopback: Set to 1 for loopback packets, 0 @@ -674,12 +672,19 @@ valid, 0 otherwise.
  • Network.IfIdx: The interface index on which the packet arrived (for inbound packets), or is to be sent (for outbound packets).
  • Network.SubIfIdx: The sub-interface index for IfIdx.
  • +
  • Flow.EndpointId: The endpoint ID of the flow.
  • +
  • Flow.ParentEndpointId: The parent endpoint ID of the + flow.
  • Flow.ProcessId: The ID of the process associated with the - flow.
  • + flow.
  • Flow.LocalAddr, Flow.RemoteAddr, Flow.LocalPort, Flow.RemotePort, and Flow.Protocol: The network 5-tuple associated with the flow.
  • +
  • Socket.EndpointId: The endpoint ID of the socket + operation.
  • +
  • Socket.ParentEndpointId: The parent endpoint ID of the + socket operation.
  • Socket.ProcessId: The ID of the process associated with the socket operation.
  • Socket.LocalAddr, Socket.RemoteAddr, @@ -2732,6 +2737,8 @@ The possible fields are: subIfIdx✔✔Sub-interface index loopback✔✔✔Is loopback packet? impostor✔✔Is impostor packet? +endpointId✔✔Endpoint ID +parentEndpointId✔✔Parent endpoint ID processId✔✔✔Process ID random8✔✔8-bit random number random16✔✔16-bit random number @@ -2819,20 +2826,21 @@ and layers symbolically, e.g., event == CONNECT or The possible macros are:

    - +
    - - - + diff --git a/examples/socketdump/socketdump.c b/examples/socketdump/socketdump.c index 52c717a..13233da 100644 --- a/examples/socketdump/socketdump.c +++ b/examples/socketdump/socketdump.c @@ -36,6 +36,7 @@ * DESCRIPTION: * * usage: socketdump.exe [filter] + * socketdump.exe --block [filter] */ #include @@ -62,22 +63,39 @@ int __cdecl main(int argc, char **argv) char *filename; DWORD path_len; WINDIVERT_ADDRESS addr; + BOOL block = FALSE; switch (argc) { case 1: break; case 2: - filter = argv[1]; + if (strcmp(argv[1], "--block") == 0) + { + block = TRUE; + } + else + { + filter = argv[1]; + } break; + case 3: + if (strcmp(argv[1], "--block") == 0) + { + block = TRUE; + filter = argv[2]; + break; + } + // Fallthrough: default: fprintf(stderr, "usage: %s [filter]\n"); + fprintf(stderr, " %s --block [filter]\n"); exit(EXIT_FAILURE); } // Open WinDivert SOCKET handle: handle = WinDivertOpen(filter, WINDIVERT_LAYER_SOCKET, priority, - WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY); + (block? 0: WINDIVERT_FLAG_SNIFF) | WINDIVERT_FLAG_RECV_ONLY); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_INVALID_PARAMETER && @@ -108,10 +126,6 @@ int __cdecl main(int argc, char **argv) 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"); @@ -120,14 +134,14 @@ int __cdecl main(int argc, char **argv) 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; + case WINDIVERT_EVENT_SOCKET_CLOSE: + SetConsoleTextAttribute(console, FOREGROUND_RED); + printf("CLOSE"); + break; default: SetConsoleTextAttribute(console, FOREGROUND_BLUE); printf("???"); @@ -168,6 +182,18 @@ int __cdecl main(int argc, char **argv) SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + printf(" endpoint="); + SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); + printf("%lu", addr.Socket.Endpoint); + SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + + printf(" parent="); + SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); + printf("%lu", addr.Socket.ParentEndpoint); + SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + printf(" protocol="); SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN); switch (addr.Socket.Protocol) diff --git a/include/windivert.h b/include/windivert.h index 2c0cdca..da1482e 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -95,6 +95,8 @@ typedef struct */ typedef struct { + UINT64 EndpointId; /* Endpoint ID. */ + UINT64 ParentEndpointId; /* Parent endpoint ID. */ UINT32 ProcessId; /* Process ID. */ UINT32 LocalAddr[4]; /* Local address. */ UINT32 RemoteAddr[4]; /* Remote address. */ @@ -108,6 +110,8 @@ typedef struct */ typedef struct { + UINT64 EndpointId; /* Endpoint ID. */ + UINT64 ParentEndpointId; /* Parent Endpoint ID. */ UINT32 ProcessId; /* Process ID. */ UINT32 LocalAddr[4]; /* Local address. */ UINT32 RemoteAddr[4]; /* Remote address. */ @@ -136,6 +140,7 @@ typedef struct INT64 Timestamp; /* Packet's timestamp. */ UINT64 Layer:8; /* Packet's layer. */ UINT64 Event:8; /* Packet event. */ + UINT64 Sniffed:1; /* Packet was sniffed? */ UINT64 Outbound:1; /* Packet is outound? */ UINT64 Loopback:1; /* Packet is loopback? */ UINT64 Impostor:1; /* Packet is impostor? */ @@ -143,14 +148,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 Reserved1:41; + UINT64 Reserved1:40; 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]; + UINT8 Reserved2[64]; }; } WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS; @@ -164,14 +169,12 @@ typedef enum /* Flow established. */ WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */ WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */ - WINDIVERT_EVENT_SOCKET_UNBIND = 4, /* Socket unbind. */ - WINDIVERT_EVENT_SOCKET_CONNECT = 5, /* Socket connect. */ - 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_SOCKET_CONNECT = 4, /* Socket connect. */ + WINDIVERT_EVENT_SOCKET_LISTEN = 5, /* Socket listen. */ + WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */ + WINDIVERT_EVENT_SOCKET_CLOSE = 7, /* Socket close. */ + WINDIVERT_EVENT_REFLECT_OPEN = 8, /* WinDivert handle opened. */ + WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* WinDivert handle closed. */ } WINDIVERT_EVENT, *PWINDIVERT_EVENT; /* @@ -312,6 +315,7 @@ extern WINDIVERTEXPORT BOOL WinDivertGetParam( #define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */ #define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */ #define WINDIVERT_BATCH_MAX 0xFF /* 255 */ +#define WINDIVERT_MTU_MAX (40 + 0xFFFF) /****************************************************************************/ /* WINDIVERT HELPER API */ diff --git a/include/windivert_device.h b/include/windivert_device.h index 50aa833..8659bc7 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -130,21 +130,23 @@ #define WINDIVERT_FILTER_FIELD_LOCALPORT 63 #define WINDIVERT_FILTER_FIELD_REMOTEPORT 64 #define WINDIVERT_FILTER_FIELD_PROTOCOL 65 -#define WINDIVERT_FILTER_FIELD_LAYER 66 -#define WINDIVERT_FILTER_FIELD_PRIORITY 67 -#define WINDIVERT_FILTER_FIELD_EVENT 68 -#define WINDIVERT_FILTER_FIELD_PACKET 69 -#define WINDIVERT_FILTER_FIELD_PACKET16 70 -#define WINDIVERT_FILTER_FIELD_PACKET32 71 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 72 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 73 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 74 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 75 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 76 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 77 -#define WINDIVERT_FILTER_FIELD_RANDOM8 78 -#define WINDIVERT_FILTER_FIELD_RANDOM16 79 -#define WINDIVERT_FILTER_FIELD_RANDOM32 80 +#define WINDIVERT_FILTER_FIELD_ENDPOINTID 66 +#define WINDIVERT_FILTER_FIELD_PARENTENDPOINTID 67 +#define WINDIVERT_FILTER_FIELD_LAYER 68 +#define WINDIVERT_FILTER_FIELD_PRIORITY 69 +#define WINDIVERT_FILTER_FIELD_EVENT 70 +#define WINDIVERT_FILTER_FIELD_PACKET 71 +#define WINDIVERT_FILTER_FIELD_PACKET16 72 +#define WINDIVERT_FILTER_FIELD_PACKET32 73 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 74 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 75 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 76 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 77 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 78 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 79 +#define WINDIVERT_FILTER_FIELD_RANDOM8 80 +#define WINDIVERT_FILTER_FIELD_RANDOM16 81 +#define WINDIVERT_FILTER_FIELD_RANDOM32 82 #define WINDIVERT_FILTER_FIELD_MAX \ WINDIVERT_FILTER_FIELD_RANDOM32 @@ -196,12 +198,10 @@ #define WINDIVERT_FILTER_FLAG_IPV6 0x0000000000000080ull #define WINDIVERT_FILTER_FLAG_EVENT_FLOW_DELETED 0x0000000000000100ull #define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND 0x0000000000000200ull -#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_UNBIND 0x0000000000000400ull -#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT 0x0000000000000800ull -#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_DISCONNECT \ - 0x0000000000001000ull -#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN 0x0000000000002000ull -#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT 0x0000000000004000ull +#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT 0x0000000000000400ull +#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN 0x0000000000000800ull +#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT 0x0000000000001000ull +#define WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE 0x0000000000002000ull #define WINDIVERT_FILTER_FLAGS_ALL \ (WINDIVERT_FILTER_FLAG_INBOUND | \ @@ -210,11 +210,10 @@ 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) + WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT | \ + WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) /* * WinDivert priorities. diff --git a/sys/windivert.c b/sys/windivert.c index b1fcd01..b8b102f 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -258,6 +258,7 @@ struct packet_s LONGLONG timestamp; // Packet timestamp. UINT64 layer:8; // Layer. UINT64 event:8; // Event. + UINT64 sniffed:1; // Packet was sniffed? UINT64 outbound:1; // Packet is outound? UINT64 loopback:1; // Packet is loopback? UINT64 impostor:1; // Packet is impostor? @@ -266,7 +267,7 @@ struct packet_s UINT64 tcp_checksum:1; // Packet has TCP checksum? UINT64 udp_checksum:1; // Packet has UDP checksum? UINT64 match:1; // Packet matches filter? - UINT64 padding:8; // Padding for alignment. + UINT64 padding:7; // Padding for alignment. UINT64 packet_size:32; // Packet total size. PVOID object; // Object associated with packet. UINT32 priority; // Packet priority. @@ -1513,8 +1514,8 @@ 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, unbind, connect, disconnect, - listen, accept; + BOOL inbound, outbound, ipv4, ipv6, bind, connect, listen, + accept, close; NTSTATUS status = STATUS_SUCCESS; inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0); @@ -1522,11 +1523,10 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer, 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); + close = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) != 0); i = 0; switch (layer) @@ -1579,18 +1579,10 @@ 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; @@ -1599,22 +1591,19 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer, { layers[i++] = WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV4; } + if (ipv4 && close) + { + layers[i++] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4; + layers[i++] = WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4; + } if (ipv6 && bind) { 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; @@ -1623,6 +1612,11 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer, { layers[i++] = WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV6; } + if (ipv6 && close) + { + layers[i++] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6; + layers[i++] = WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6; + } break; case WINDIVERT_LAYER_REFLECT: @@ -2188,6 +2182,7 @@ static void windivert_read_service_request(context_t context, packet_t packet, addr[i].Timestamp = (INT64)packet->timestamp; addr[i].Layer = packet->layer; addr[i].Event = packet->event; + addr[i].Sniffed = packet->sniffed; addr[i].Outbound = packet->outbound; addr[i].Loopback = packet->loopback; addr[i].Impostor = packet->impostor; @@ -2294,7 +2289,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len, PWINDIVERT_ADDRESS addr; UINT *addr_len_ptr; NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO checksums; - BOOL ip_checksum, tcp_checksum, udp_checksum; + BOOL sniffed, ip_checksum, tcp_checksum, udp_checksum; NTSTATUS status = STATUS_SUCCESS; // This function bypasses the normal work_queue -> packet_queue flow, but @@ -2384,9 +2379,13 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len, if (addr != NULL) { + sniffed = ((flags & WINDIVERT_FLAG_SNIFF) != 0 || + event == WINDIVERT_EVENT_SOCKET_CLOSE); + addr->Timestamp = timestamp; addr->Layer = layer; addr->Event = event; + addr->Sniffed = (sniffed? 1: 0); addr->Outbound = (outbound? 1: 0); addr->Loopback = (loopback? 1: 0); addr->Impostor = (impostor? 1: 0); @@ -3823,6 +3822,8 @@ static void windivert_flow_established_v4_classify( BOOL outbound, loopback; UINT64 flow_id; + flow_data.EndpointId = meta_vals->transportEndpointHandle; + flow_data.ParentEndpointId = meta_vals->parentEndpointHandle; flow_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS, @@ -4097,6 +4098,8 @@ static void windivert_resource_assignment_v4_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_ADDRESS, @@ -4134,6 +4137,8 @@ static void windivert_resource_assignment_v6_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_ADDRESS, @@ -4166,6 +4171,8 @@ static void windivert_resource_release_v4_classify( WINDIVERT_DATA_SOCKET socket_data; BOOL loopback; + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_ADDRESS, @@ -4182,7 +4189,7 @@ static void windivert_resource_release_v4_classify( FWP_CONDITION_FLAG_IS_LOOPBACK) != 0); windivert_socket_classify((context_t)filter->context, - &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_UNBIND, /*ipv4=*/TRUE, + &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE, /*outbound=*/FALSE, loopback, result); } @@ -4198,6 +4205,8 @@ static void windivert_resource_release_v6_classify( WINDIVERT_DATA_SOCKET socket_data; BOOL loopback; + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_RESOURCE_RELEASE_V6_IP_LOCAL_ADDRESS, @@ -4214,7 +4223,7 @@ static void windivert_resource_release_v6_classify( FWP_CONDITION_FLAG_IS_LOOPBACK) != 0); windivert_socket_classify((context_t)filter->context, - &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_UNBIND, /*ipv4=*/FALSE, + &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE, /*outbound=*/FALSE, loopback, result); } @@ -4243,6 +4252,8 @@ static void windivert_auth_connect_v4_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS, @@ -4289,6 +4300,8 @@ static void windivert_auth_connect_v6_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_LOCAL_ADDRESS, @@ -4322,6 +4335,8 @@ static void windivert_endpoint_closure_v4_classify( WINDIVERT_DATA_SOCKET socket_data; BOOL loopback; + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V4_IP_LOCAL_ADDRESS, @@ -4341,7 +4356,7 @@ static void windivert_endpoint_closure_v4_classify( FWP_CONDITION_FLAG_IS_LOOPBACK) != 0); windivert_socket_classify((context_t)filter->context, - &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_DISCONNECT, + &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE, /*outbound=*/TRUE, loopback, result); } @@ -4357,6 +4372,8 @@ static void windivert_endpoint_closure_v6_classify( WINDIVERT_DATA_SOCKET socket_data; BOOL loopback; + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_ENDPOINT_CLOSURE_V6_IP_LOCAL_ADDRESS, @@ -4376,11 +4393,10 @@ static void windivert_endpoint_closure_v6_classify( FWP_CONDITION_FLAG_IS_LOOPBACK) != 0); windivert_socket_classify((context_t)filter->context, - &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_DISCONNECT, + &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE, /*outbound=*/TRUE, loopback, result); } - /* * WinDivert classify auth listen IPv4 function. */ @@ -4398,6 +4414,8 @@ static void windivert_auth_listen_v4_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_ADDRESS, @@ -4434,6 +4452,8 @@ static void windivert_auth_listen_v6_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = 0; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_ADDRESS, @@ -4478,6 +4498,8 @@ static void windivert_auth_recv_accept_v4_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv4_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_ADDRESS, @@ -4524,6 +4546,8 @@ static void windivert_auth_recv_accept_v6_classify( return; } + socket_data.EndpointId = meta_vals->transportEndpointHandle; + socket_data.ParentEndpointId = meta_vals->parentEndpointHandle; socket_data.ProcessId = (UINT32)meta_vals->processId; windivert_get_ipv6_addr(fixed_vals, FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_LOCAL_ADDRESS, @@ -4598,9 +4622,8 @@ static void windivert_socket_classify(context_t context, } WdfObjectDereference(object); - if ((result->rights & FWPS_RIGHT_ACTION_WRITE) != 0 && - event != WINDIVERT_EVENT_SOCKET_UNBIND && - event != WINDIVERT_EVENT_SOCKET_DISCONNECT && + if (match && (result->rights & FWPS_RIGHT_ACTION_WRITE) != 0 && + event != WINDIVERT_EVENT_SOCKET_CLOSE && (flags & WINDIVERT_FLAG_SNIFF) == 0) { result->actionType = FWP_ACTION_BLOCK; @@ -4665,11 +4688,14 @@ static BOOL windivert_queue_work(context_t context, PVOID packet, PWINDIVERT_DATA_FLOW flow_data; PWINDIVERT_DATA_SOCKET socket_data; PWINDIVERT_DATA_REFLECT reflect_data; - BOOL ip_checksum, tcp_checksum, udp_checksum; + BOOL sniffed, ip_checksum, tcp_checksum, udp_checksum; WDFREQUEST request = NULL; NTSTATUS status; - if (!match && (flags & WINDIVERT_FLAG_SNIFF) != 0) + sniffed = ((flags & WINDIVERT_FLAG_SNIFF) != 0 || + event == WINDIVERT_EVENT_SOCKET_CLOSE); + + if (!match && sniffed) { return TRUE; } @@ -4795,6 +4821,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet, work->layer = layer; work->event = event; + work->sniffed = (sniffed? 1: 0); work->outbound = (outbound? 1: 0); work->loopback = (loopback? 1: 0); work->impostor = (impostor? 1: 0); @@ -5438,6 +5465,11 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, layer == WINDIVERT_LAYER_SOCKET || layer == WINDIVERT_LAYER_REFLECT); break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + result = (layer == WINDIVERT_LAYER_FLOW || + layer == WINDIVERT_LAYER_SOCKET); + break; case WINDIVERT_FILTER_FIELD_LAYER: case WINDIVERT_FILTER_FIELD_PRIORITY: result = (layer == WINDIVERT_LAYER_REFLECT); @@ -6057,6 +6089,42 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, return FALSE; } break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + big = TRUE; + field[2] = field[3] = 0; + switch (layer) + { + case WINDIVERT_LAYER_FLOW: + field[0] = (UINT32)flow_data->EndpointId; + field[1] = (UINT32)(flow_data->EndpointId >> 32); + break; + case WINDIVERT_LAYER_SOCKET: + field[0] = (UINT32)socket_data->EndpointId; + field[1] = (UINT32)(socket_data->EndpointId >> 32); + break; + default: + return FALSE; + } + break; + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + big = TRUE; + field[2] = field[3] = 0; + switch (layer) + { + case WINDIVERT_LAYER_FLOW: + field[0] = (UINT32)flow_data->ParentEndpointId; + field[1] = + (UINT32)(flow_data->ParentEndpointId >> 32); + break; + case WINDIVERT_LAYER_SOCKET: + field[0] = (UINT32)socket_data->ParentEndpointId; + field[1] = + (UINT32)(socket_data->ParentEndpointId >> 32); + break; + default: + return FALSE; + } + break; case WINDIVERT_FILTER_FIELD_LAYER: field[0] = (UINT32)reflect_data->Layer; break; @@ -6119,6 +6187,8 @@ static const WINDIVERT_FILTER *windivert_filter_compile( { PWINDIVERT_FILTER filter = NULL; WINDIVERT_EVENT event; + UINT32 lb[4], ub[4]; + int result; UINT16 i; size_t length; @@ -6174,49 +6244,30 @@ static const WINDIVERT_FILTER *windivert_filter_compile( } // Enforce ranges: - if (ioctl_filter[i].field != WINDIVERT_FILTER_FIELD_IPV6_SRCADDR && - ioctl_filter[i].field != WINDIVERT_FILTER_FIELD_IPV6_DSTADDR && - ioctl_filter[i].field != WINDIVERT_FILTER_FIELD_LOCALADDR && - ioctl_filter[i].field != WINDIVERT_FILTER_FIELD_REMOTEADDR) + lb[0] = lb[1] = lb[2] = lb[3] = 0; + ub[0] = ub[1] = ub[2] = ub[3] = 0; + switch (ioctl_filter[i].field) { - if (ioctl_filter[i].arg[2] != 0 || - ioctl_filter[i].arg[3] != 0) + 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; - } - switch (ioctl_filter[i].field) - { - 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: + INT idx = (INT)ioctl_filter[i].arg[1]; + if (idx > WINDIVERT_MTU_MAX || idx < -WINDIVERT_MTU_MAX) { - INT idx = (INT)ioctl_filter[i].arg[1]; - if (idx > UINT16_MAX || idx < -UINT16_MAX) - { - goto windivert_filter_compile_error; - } - break; + goto windivert_filter_compile_error; } - default: - if (ioctl_filter[i].arg[1] != 0) - { - goto windivert_filter_compile_error; - } - break; + lb[1] = ub[1] = ioctl_filter[i].arg[1]; + break; } + default: + break; } switch (ioctl_filter[i].field) { @@ -6237,22 +6288,13 @@ static const WINDIVERT_FILTER *windivert_filter_compile( case WINDIVERT_FILTER_FIELD_TCP_RST: case WINDIVERT_FILTER_FIELD_TCP_SYN: case WINDIVERT_FILTER_FIELD_TCP_FIN: - if (ioctl_filter[i].arg[0] > 1) - { - goto windivert_filter_compile_error; - } + ub[0] = 1; break; case WINDIVERT_FILTER_FIELD_LAYER: - if (ioctl_filter[i].arg[0] > WINDIVERT_LAYER_MAX) - { - goto windivert_filter_compile_error; - } + ub[0] = WINDIVERT_LAYER_MAX; break; case WINDIVERT_FILTER_FIELD_PRIORITY: - if (ioctl_filter[i].arg[0] > 2 * WINDIVERT_PRIORITY_MAX) - { - goto windivert_filter_compile_error; - } + ub[0] = 2 * WINDIVERT_PRIORITY_MAX; break; case WINDIVERT_FILTER_FIELD_EVENT: event = (WINDIVERT_EVENT)ioctl_filter[i].arg[0]; @@ -6274,11 +6316,10 @@ static const WINDIVERT_FILTER *windivert_filter_compile( break; case WINDIVERT_LAYER_SOCKET: if (event != WINDIVERT_EVENT_SOCKET_BIND && - event != WINDIVERT_EVENT_SOCKET_UNBIND && event != WINDIVERT_EVENT_SOCKET_CONNECT && - event != WINDIVERT_EVENT_SOCKET_DISCONNECT && event != WINDIVERT_EVENT_SOCKET_LISTEN && - event != WINDIVERT_EVENT_SOCKET_ACCEPT) + event != WINDIVERT_EVENT_SOCKET_ACCEPT && + event != WINDIVERT_EVENT_SOCKET_CLOSE) { goto windivert_filter_compile_error; } @@ -6293,13 +6334,11 @@ static const WINDIVERT_FILTER *windivert_filter_compile( default: goto windivert_filter_compile_error; } + ub[0] = WINDIVERT_EVENT_MAX; break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: - if (ioctl_filter[i].arg[0] > 0x0F) - { - goto windivert_filter_compile_error; - } + ub[0] = 0x0F; break; case WINDIVERT_FILTER_FIELD_IP_TOS: case WINDIVERT_FILTER_FIELD_IP_TTL: @@ -6316,16 +6355,10 @@ static const WINDIVERT_FILTER *windivert_filter_compile( case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: case WINDIVERT_FILTER_FIELD_RANDOM8: - if (ioctl_filter[i].arg[0] > UINT8_MAX) - { - goto windivert_filter_compile_error; - } + ub[0] = 0xFF; break; case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: - if (ioctl_filter[i].arg[0] > 0x1FFF) - { - goto windivert_filter_compile_error; - } + ub[0] = 0x1FFF; break; case WINDIVERT_FILTER_FIELD_IP_LENGTH: case WINDIVERT_FILTER_FIELD_IP_ID: @@ -6350,20 +6383,41 @@ static const WINDIVERT_FILTER *windivert_filter_compile( case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: case WINDIVERT_FILTER_FIELD_RANDOM16: - if (ioctl_filter[i].arg[0] > UINT16_MAX) - { - goto windivert_filter_compile_error; - } + ub[0] = 0xFFFF; break; case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: - if (ioctl_filter[i].arg[0] > 0x000FFFFF) - { - goto windivert_filter_compile_error; - } + ub[0] = 0x000FFFFF; + break; + case WINDIVERT_FILTER_FIELD_IP_SRCADDR: + case WINDIVERT_FILTER_FIELD_IP_DSTADDR: + ub[0] = 0xFFFFFFFF; + ub[1] = lb[1] = 0x0000FFFF; + break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + ub[0] = ub[1] = 0xFFFFFFFF; + break; + case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: + case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: + case WINDIVERT_FILTER_FIELD_LOCALADDR: + case WINDIVERT_FILTER_FIELD_REMOTEADDR: + ub[0] = ub[1] = ub[2] = ub[3] = 0xFFFFFFFF; break; default: + ub[0] = 0xFFFFFFFF; break; } + result = windivert_big_num_compare(ioctl_filter[i].arg, lb, TRUE); + if (result < 0) + { + goto windivert_filter_compile_error; + } + result = windivert_big_num_compare(ioctl_filter[i].arg, ub, TRUE); + if (result > 0) + { + goto windivert_filter_compile_error; + } + filter[i].field = ioctl_filter[i].field; filter[i].test = ioctl_filter[i].test; filter[i].success = ioctl_filter[i].success; diff --git a/test/test.c b/test/test.c index 4c8da69..0ce8eb1 100644 --- a/test/test.c +++ b/test/test.c @@ -296,13 +296,13 @@ static const struct test tests[] = "not packet[69] <= 0x29)))))", &pkt_echo_request, FALSE}, {"ip.HdrLength == 5 and ip.TOS == 0 and ip.Length == 84 and " "ip.Id == 0x1234 and ip.FragOff == 0 and ip.MF == 0 and ip.DF == 1 and " - "ip.TTL == 64 and ip.Protocol == 1 and ip.SrcAddr == 0x0A000001 and " - "ip.DstAddr == 0x08080808 and icmp.Type == 8 and icmp.Code == 0 and " + "ip.TTL == 64 and ip.Protocol == 1 and ip.SrcAddr == 0xFFFF0A000001 and " + "ip.DstAddr == 0xFFFF08080808 and icmp.Type == 8 and icmp.Code == 0 and " "icmp.Body == 0x0D560001", &pkt_echo_request, TRUE}, {"ip.HdrLength > 5 or ip.TOS > 0 or ip.Length != 84 or ip.Id < 0x1234 or " "ip.FragOff != 0 or ip.MF < 0 or ip.DF != 1 or ip.TTL > 64 or " - "ip.Protocol != 1 or ip.SrcAddr < 0x0A000001 or " - "ip.DstAddr < 0x08080808 or icmp.Type != 8 or icmp.Code != 0 or " + "ip.Protocol != 1 or ip.SrcAddr < 0xFFFF0A000001 or " + "ip.DstAddr < 0xFFFF08080808 or icmp.Type != 8 or icmp.Code != 0 or " "icmp.Body != 0x0D560001", &pkt_echo_request, FALSE}, {"localAddr == 10.0.0.1 && remoteAddr == 8.8.8.8 && localPort == 8 && " "remotePort == 0 && protocol == 1", &pkt_echo_request, TRUE}, @@ -481,8 +481,8 @@ static const struct test tests[] = "not packet[477] == 0x69)))", &pkt_http_request, FALSE}, {"ip.HdrLength == 5 and ip.TOS == 0 and ip.Length == 521 and " "ip.Id == 0x482D and ip.FragOff == 0 and ip.MF == 0 and ip.DF == 1 and " - "ip.TTL == 64 and ip.Protocol == 6 and ip.SrcAddr == 0x0A0A0A0A and " - "ip.DstAddr == 0x5DB8D877 and tcp.SrcPort == 41754 and " + "ip.TTL == 64 and ip.Protocol == 6 and ip.SrcAddr == 0xFFFF0A0A0A0A and " + "ip.DstAddr == 0xFFFF5DB8D877 and tcp.SrcPort == 41754 and " "tcp.DstPort == 80 and tcp.SeqNum == 1396231362 and " "tcp.AckNum == 1446490965 and tcp.HdrLength == 8 and tcp.Fin == 0 and " "tcp.Syn == 0 and tcp.Rst == 0 and tcp.Psh == 1 and tcp.Ack == 1 and " @@ -490,12 +490,13 @@ static const struct test tests[] = &pkt_http_request, TRUE}, {"ip.HdrLength > 5 or ip.TOS < 0 or ip.Length < 521 or ip.Id != 0x482D or " "ip.FragOff != 0 or ip.MF != 0 or ip.DF < 1 or ip.TTL < 64 or " - "ip.Protocol > 6 or ip.SrcAddr != 0x0A0A0A0A or " - "ip.DstAddr < 0x5DB8D877 or tcp.SrcPort < 41754 or tcp.DstPort < 80 or " - "tcp.SeqNum != 1396231362 or tcp.AckNum < 1446490965 or " - "tcp.HdrLength < 8 or tcp.Fin != 0 or tcp.Syn != 0 or tcp.Rst != 0 or " - "tcp.Psh != 1 or tcp.Ack > 1 or tcp.Urg != 0 or tcp.Window < 115 or " - "tcp.UrgPtr < 0", &pkt_http_request, FALSE}, + "ip.Protocol > 6 or ip.SrcAddr != 0xFFFF0A0A0A0A or " + "ip.DstAddr < 0xFFFF5DB8D877 or tcp.SrcPort < 41754 or " + "tcp.DstPort < 80 or tcp.SeqNum != 1396231362 or " + "tcp.AckNum < 1446490965 or tcp.HdrLength < 8 or tcp.Fin != 0 or " + "tcp.Syn != 0 or tcp.Rst != 0 or tcp.Psh != 1 or tcp.Ack > 1 or " + "tcp.Urg != 0 or tcp.Window < 115 or tcp.UrgPtr < 0", + &pkt_http_request, FALSE}, {"localAddr == 10.10.10.10 && remoteAddr == 93.184.216.119 && " "localPort == 41754 && remotePort == 80 && protocol == 6", &pkt_http_request, TRUE}, @@ -585,14 +586,14 @@ static const struct test tests[] = {"packet32[54b] <= 0xFFFFFFE", &pkt_dns_request, FALSE}, {"ip.HdrLength == 5 and ip.TOS == 0 and ip.Length == 57 and " "ip.Id == 0x2090 and ip.FragOff == 0 and ip.MF == 0 and ip.DF == 0 and " - "ip.TTL == 73 and ip.Protocol == 17 and ip.SrcAddr == 0x0A000001 and " - "ip.DstAddr == 0x08080404 and udp.SrcPort == 57413 and " + "ip.TTL == 73 and ip.Protocol == 17 and ip.SrcAddr == 0xFFFF0A000001 and " + "ip.DstAddr == 0xFFFF08080404 and udp.SrcPort == 57413 and " "udp.DstPort == 53 and udp.Length == 37", &pkt_dns_request, TRUE}, {"ip.HdrLength > 5 or ip.TOS > 0 or ip.Length < 57 or ip.Id > 0x2090 or " "ip.FragOff != 0 or ip.MF < 0 or ip.DF < 0 or ip.TTL > 73 or " - "ip.Protocol < 17 or ip.SrcAddr < 0x0A000001 or " - "ip.DstAddr > 0x08080404 or udp.SrcPort > 57413 or udp.DstPort != 53 or " - "udp.Length < 37", &pkt_dns_request, FALSE}, + "ip.Protocol < 17 or ip.SrcAddr < 0xFFFF0A000001 or " + "ip.DstAddr > 0xFFFF08080404 or udp.SrcPort > 57413 or " + "udp.DstPort != 53 or udp.Length < 37", &pkt_dns_request, FALSE}, {"localAddr == 10.0.0.1 && remoteAddr == 8.8.4.4 && " "localPort == 57413 && remotePort == 53 && protocol == 17", &pkt_dns_request, TRUE}, @@ -1316,8 +1317,8 @@ static DWORD monitor_worker(LPVOID arg) tests[i].packet->packet_len, &addr) != tests[i].match) { fprintf(stderr, "error: failed to match recompiled filter " - "(test = %.3u, filter = \"%s\", err = %d)\n", i, filter_2, - GetLastError()); + "(test = %.3u, filter = \"%s\", err = %d)\n", i, + tests[i].filter, GetLastError()); exit(EXIT_FAILURE); } }
    MacroLayerValue
    NETWORKFORWARDFLOW   SOCKET REFLECT
    PACKET✔✔WINDIVERT_EVENT_NETWORK_PACKET
    ESTABLISHED✔WINDIVERT_EVENT_FLOW_ESTABLISHED
    DELETED✔WINDIVERT_EVENT_FLOW_DELETED
    BIND✔WINDIVERT_EVENT_SOCKET_BIND
    UNBIND✔WINDIVERT_EVENT_SOCKET_UNBIND
    CONNECT✔WINDIVERT_EVENT_SOCKET_CONNECT
    DISCONNECT✔WINDIVERT_EVENT_SOCKET_DISCONNECT
    ACCEPT✔WINDIVERT_EVENT_SOCKET_ACCEPT
    LISTEN✔WINDIVERT_EVENT_SOCKET_LISTEN
    OPEN✔WINDIVERT_EVENT_REFLECT_OPEN
    CLOSE✔WINDIVERT_EVENT_REFLECT_CLOSE
    CLOSE✔✔WINDIVERT_EVENT_SOCKET_CLOSE +for the SOCKET layer, or +WINDIVERT_EVENT_REFLECT_CLOSE for the REFLECT +layer.
    NETWORK✔WINDIVERT_LAYER_FLOW_NETWORK
    NETWORK_FORWARD✔WINDIVERT_LAYER_FLOW_NETWORK_FORWARD
    FLOW✔WINDIVERT_LAYER_FLOW_FLOW