Add a new FLOW layer into WinDivert.
Adds a new WINDIVERT_LAYER_FLOW layer that can: - Track when flows are established - Track when existing flows are deleted
This commit is contained in:
+16
-1
@@ -411,11 +411,26 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
UINT32 priority32;
|
||||
|
||||
// Parameter checking.
|
||||
if (!WINDIVERT_FLAGS_VALID(flags) || layer > WINDIVERT_LAYER_MAX)
|
||||
if (layer == 0)
|
||||
{
|
||||
layer = WINDIVERT_LAYER_NETWORK;
|
||||
}
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (!WINDIVERT_FLAGS_VALID(flags))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
priority32 = WINDIVERT_PRIORITY(priority);
|
||||
if (priority32 < WINDIVERT_PRIORITY_MIN ||
|
||||
priority32 > WINDIVERT_PRIORITY_MAX)
|
||||
|
||||
+234
-49
@@ -116,6 +116,12 @@ typedef enum
|
||||
TOKEN_SUB_IF_IDX,
|
||||
TOKEN_LOOPBACK,
|
||||
TOKEN_IMPOSTOR,
|
||||
TOKEN_PROCESS_ID,
|
||||
TOKEN_LOCAL_ADDR,
|
||||
TOKEN_REMOTE_ADDR,
|
||||
TOKEN_LOCAL_PORT,
|
||||
TOKEN_REMOTE_PORT,
|
||||
TOKEN_PROTOCOL,
|
||||
TOKEN_OPEN,
|
||||
TOKEN_CLOSE,
|
||||
TOKEN_EQ,
|
||||
@@ -504,7 +510,7 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
tcp_header->Checksum = WinDivertHelperCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
|
||||
}
|
||||
else if (pAddr->Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo TCP checksum
|
||||
tcp_header->Checksum = 0;
|
||||
@@ -533,7 +539,7 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
}
|
||||
else if (pAddr->Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo UDP checksum
|
||||
udp_header->Checksum = 0;
|
||||
@@ -748,7 +754,7 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
|
||||
l = k + 1;
|
||||
k = (k >= 8? k - 8: k);
|
||||
l = (l >= 8? l - 8: l);
|
||||
addr_ptr[i] =
|
||||
addr_ptr[3 - i] =
|
||||
(UINT32)laddr[2 * i + 1] |
|
||||
(UINT32)laddr[2 * i] << 16 |
|
||||
(UINT32)raddr[l] |
|
||||
@@ -785,6 +791,91 @@ static PTOKEN_NAME WinDivertTokenLookup(PTOKEN_NAME token_names,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate token for layer.
|
||||
*/
|
||||
static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
switch (kind)
|
||||
{
|
||||
case TOKEN_INBOUND:
|
||||
case TOKEN_OUTBOUND:
|
||||
return (layer != WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
case TOKEN_PROCESS_ID:
|
||||
case TOKEN_LOCAL_ADDR:
|
||||
case TOKEN_REMOTE_ADDR:
|
||||
case TOKEN_LOCAL_PORT:
|
||||
case TOKEN_REMOTE_PORT:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
switch (kind)
|
||||
{
|
||||
case TOKEN_ICMP_BODY:
|
||||
case TOKEN_ICMP_CHECKSUM:
|
||||
case TOKEN_ICMP_CODE:
|
||||
case TOKEN_ICMP_TYPE:
|
||||
case TOKEN_ICMPV6_BODY:
|
||||
case TOKEN_ICMPV6_CHECKSUM:
|
||||
case TOKEN_ICMPV6_CODE:
|
||||
case TOKEN_ICMPV6_TYPE:
|
||||
case TOKEN_IP_CHECKSUM:
|
||||
case TOKEN_IP_DF:
|
||||
case TOKEN_IP_DST_ADDR:
|
||||
case TOKEN_IP_FRAG_OFF:
|
||||
case TOKEN_IP_HDR_LENGTH:
|
||||
case TOKEN_IP_ID:
|
||||
case TOKEN_IP_LENGTH:
|
||||
case TOKEN_IP_MF:
|
||||
case TOKEN_IP_PROTOCOL:
|
||||
case TOKEN_IP_SRC_ADDR:
|
||||
case TOKEN_IP_TOS:
|
||||
case TOKEN_IP_TTL:
|
||||
case TOKEN_IPV6_DST_ADDR:
|
||||
case TOKEN_IPV6_FLOW_LABEL:
|
||||
case TOKEN_IPV6_HOP_LIMIT:
|
||||
case TOKEN_IPV6_LENGTH:
|
||||
case TOKEN_IPV6_NEXT_HDR:
|
||||
case TOKEN_IPV6_SRC_ADDR:
|
||||
case TOKEN_IPV6_TRAFFIC_CLASS:
|
||||
case TOKEN_TCP_ACK:
|
||||
case TOKEN_TCP_ACK_NUM:
|
||||
case TOKEN_TCP_CHECKSUM:
|
||||
case TOKEN_TCP_DST_PORT:
|
||||
case TOKEN_TCP_FIN:
|
||||
case TOKEN_TCP_HDR_LENGTH:
|
||||
case TOKEN_TCP_PAYLOAD_LENGTH:
|
||||
case TOKEN_TCP_PSH:
|
||||
case TOKEN_TCP_RST:
|
||||
case TOKEN_TCP_SEQ_NUM:
|
||||
case TOKEN_TCP_SRC_PORT:
|
||||
case TOKEN_TCP_SYN:
|
||||
case TOKEN_TCP_URG:
|
||||
case TOKEN_TCP_URG_PTR:
|
||||
case TOKEN_TCP_WINDOW:
|
||||
case TOKEN_UDP_CHECKSUM:
|
||||
case TOKEN_UDP_DST_PORT:
|
||||
case TOKEN_UDP_LENGTH:
|
||||
case TOKEN_UDP_PAYLOAD_LENGTH:
|
||||
case TOKEN_UDP_SRC_PORT:
|
||||
case TOKEN_IF_IDX:
|
||||
case TOKEN_SUB_IF_IDX:
|
||||
case TOKEN_IMPOSTOR:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenize the given filter string.
|
||||
*/
|
||||
@@ -829,10 +920,16 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"ipv6.NextHdr", TOKEN_IPV6_NEXT_HDR},
|
||||
{"ipv6.SrcAddr", TOKEN_IPV6_SRC_ADDR},
|
||||
{"ipv6.TrafficClass", TOKEN_IPV6_TRAFFIC_CLASS},
|
||||
{"localAddr", TOKEN_LOCAL_ADDR},
|
||||
{"localPort", TOKEN_LOCAL_PORT},
|
||||
{"loopback", TOKEN_LOOPBACK},
|
||||
{"not", TOKEN_NOT},
|
||||
{"or", TOKEN_OR},
|
||||
{"outbound", TOKEN_OUTBOUND},
|
||||
{"processId", TOKEN_PROCESS_ID},
|
||||
{"protocol", TOKEN_PROTOCOL},
|
||||
{"remoteAddr", TOKEN_REMOTE_ADDR},
|
||||
{"remotePort", TOKEN_REMOTE_PORT},
|
||||
{"subIfIdx", TOKEN_SUB_IF_IDX},
|
||||
{"tcp", TOKEN_TCP},
|
||||
{"tcp.Ack", TOKEN_TCP_ACK},
|
||||
@@ -986,18 +1083,9 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
sizeof(token_names) / sizeof(TOKEN_NAME), token);
|
||||
if (result != NULL)
|
||||
{
|
||||
switch (layer)
|
||||
if (!WinDivertCheckTokenKindForLayer(layer, result->kind))
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
if (result->kind == TOKEN_INBOUND ||
|
||||
result->kind == TOKEN_OUTBOUND)
|
||||
{
|
||||
return MAKE_ERROR(
|
||||
WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER, i-j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return MAKE_ERROR(WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER, i-j);
|
||||
}
|
||||
tokens[tp++].kind = result->kind;
|
||||
continue;
|
||||
@@ -1023,6 +1111,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
// Check for IPv4 address:
|
||||
if (WinDivertHelperParseIPv4Address(token, tokens[tp].val))
|
||||
{
|
||||
tokens[tp].val[1] = 0x0000FFFF;
|
||||
tokens[tp].kind = TOKEN_NUMBER;
|
||||
tp++;
|
||||
continue;
|
||||
@@ -1032,16 +1121,6 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
SetLastError(0);
|
||||
if (WinDivertHelperParseIPv6Address(token, tokens[tp].val))
|
||||
{
|
||||
// Work-around the different word orderings between the
|
||||
// DLL vs SYS.
|
||||
UINT32 tmp;
|
||||
tmp = tokens[tp].val[0];
|
||||
tokens[tp].val[0] = tokens[tp].val[3];
|
||||
tokens[tp].val[3] = tmp;
|
||||
tmp = tokens[tp].val[1];
|
||||
tokens[tp].val[1] = tokens[tp].val[2];
|
||||
tokens[tp].val[2] = tmp;
|
||||
|
||||
tokens[tp].kind = TOKEN_NUMBER;
|
||||
tp++;
|
||||
continue;
|
||||
@@ -1140,7 +1219,13 @@ static PEXPR WinDivertMakeVar(PPOOL pool, KIND kind)
|
||||
{{{0}}, TOKEN_IF_IDX},
|
||||
{{{0}}, TOKEN_SUB_IF_IDX},
|
||||
{{{0}}, TOKEN_LOOPBACK},
|
||||
{{{0}}, TOKEN_IMPOSTOR}
|
||||
{{{0}}, TOKEN_IMPOSTOR},
|
||||
{{{0}}, TOKEN_PROCESS_ID},
|
||||
{{{0}}, TOKEN_LOCAL_ADDR},
|
||||
{{{0}}, TOKEN_REMOTE_ADDR},
|
||||
{{{0}}, TOKEN_LOCAL_PORT},
|
||||
{{{0}}, TOKEN_REMOTE_PORT},
|
||||
{{{0}}, TOKEN_PROTOCOL},
|
||||
};
|
||||
|
||||
// Binary search:
|
||||
@@ -1268,6 +1353,12 @@ static PEXPR WinDivertParseTest(PPOOL pool, TOKEN *toks, UINT *i)
|
||||
case TOKEN_ICMPV6:
|
||||
case TOKEN_TCP:
|
||||
case TOKEN_UDP:
|
||||
case TOKEN_PROCESS_ID:
|
||||
case TOKEN_LOCAL_ADDR:
|
||||
case TOKEN_REMOTE_ADDR:
|
||||
case TOKEN_LOCAL_PORT:
|
||||
case TOKEN_REMOTE_PORT:
|
||||
case TOKEN_PROTOCOL:
|
||||
case TOKEN_IP_HDR_LENGTH:
|
||||
case TOKEN_IP_TOS:
|
||||
case TOKEN_IP_LENGTH:
|
||||
@@ -1524,6 +1615,7 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
case TOKEN_ICMP_CODE:
|
||||
case TOKEN_ICMPV6_TYPE:
|
||||
case TOKEN_ICMPV6_CODE:
|
||||
case TOKEN_PROCESS_ID:
|
||||
lb = 0; ub = 0xFF;
|
||||
break;
|
||||
case TOKEN_IP_FRAG_OFF:
|
||||
@@ -1547,13 +1639,19 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
case TOKEN_UDP_LENGTH:
|
||||
case TOKEN_UDP_CHECKSUM:
|
||||
case TOKEN_UDP_PAYLOAD_LENGTH:
|
||||
case TOKEN_LOCAL_PORT:
|
||||
case TOKEN_REMOTE_PORT:
|
||||
lb = 0; ub = 0xFFFF;
|
||||
break;
|
||||
case TOKEN_IPV6_FLOW_LABEL:
|
||||
lb = 0; ub = 0x000FFFFF;
|
||||
break;
|
||||
case TOKEN_IP_SRC_ADDR:
|
||||
case TOKEN_IP_DST_ADDR:
|
||||
case TOKEN_IPV6_SRC_ADDR:
|
||||
case TOKEN_IPV6_DST_ADDR:
|
||||
case TOKEN_LOCAL_ADDR:
|
||||
case TOKEN_REMOTE_ADDR:
|
||||
return FALSE;
|
||||
default:
|
||||
lb = 0; ub = 0xFFFFFFFF;
|
||||
@@ -1735,6 +1833,21 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
case TOKEN_IMPOSTOR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IMPOSTOR;
|
||||
break;
|
||||
case TOKEN_PROCESS_ID:
|
||||
object->field = WINDIVERT_FILTER_FIELD_PROCESSID;
|
||||
break;
|
||||
case TOKEN_LOCAL_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_LOCALADDR;
|
||||
break;
|
||||
case TOKEN_REMOTE_ADDR:
|
||||
object->field = WINDIVERT_FILTER_FIELD_REMOTEADDR;
|
||||
break;
|
||||
case TOKEN_LOCAL_PORT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_LOCALPORT;
|
||||
break;
|
||||
case TOKEN_REMOTE_PORT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_REMOTEPORT;
|
||||
break;
|
||||
case TOKEN_IP:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IP;
|
||||
break;
|
||||
@@ -2118,18 +2231,17 @@ static int WinDivertBigNumCompare(const UINT32 *a, const UINT32 *b)
|
||||
/*
|
||||
* Evaluate the given filter with the given packet as input.
|
||||
*/
|
||||
extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
WINDIVERT_LAYER layer, PVOID packet, UINT packet_len,
|
||||
PWINDIVERT_ADDRESS addr)
|
||||
extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
UINT packet_len, PWINDIVERT_ADDRESS addr)
|
||||
{
|
||||
UINT16 pc;
|
||||
ERROR err;
|
||||
PWINDIVERT_IPHDR iphdr;
|
||||
PWINDIVERT_IPV6HDR ipv6hdr;
|
||||
PWINDIVERT_ICMPHDR icmphdr;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6hdr;
|
||||
PWINDIVERT_TCPHDR tcphdr;
|
||||
PWINDIVERT_UDPHDR udphdr;
|
||||
PWINDIVERT_IPHDR iphdr = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6hdr = NULL;
|
||||
PWINDIVERT_ICMPHDR icmphdr = NULL;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6hdr = NULL;
|
||||
PWINDIVERT_TCPHDR tcphdr = NULL;
|
||||
PWINDIVERT_UDPHDR udphdr = NULL;
|
||||
UINT payload_len;
|
||||
UINT32 val[4];
|
||||
BOOL pass;
|
||||
@@ -2137,22 +2249,48 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
struct windivert_ioctl_filter_s object[WINDIVERT_FILTER_MAXLEN];
|
||||
UINT obj_len;
|
||||
|
||||
if (filter == NULL || packet == NULL || addr == NULL)
|
||||
if (filter == NULL || addr == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
switch (addr->Layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
if (packet == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertHelperParsePacket(packet, packet_len, &iphdr, &ipv6hdr,
|
||||
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, NULL, &payload_len);
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
(!addr->IPv6 && iphdr == NULL))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
if (packet != NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = WinDivertCompileFilter(filter, layer, object, &obj_len);
|
||||
err = WinDivertCompileFilter(filter, addr->Layer, object, &obj_len);
|
||||
if (IS_ERROR(err))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WinDivertHelperParsePacket(packet, packet_len, &iphdr, &ipv6hdr, &icmphdr,
|
||||
&icmpv6hdr, &tcphdr, &udphdr, NULL, &payload_len);
|
||||
|
||||
pc = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
@@ -2232,6 +2370,23 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
pass = (udphdr != NULL);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
pass = (addr->Layer != WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
|
||||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PROCESSID:
|
||||
case WINDIVERT_FILTER_FIELD_LOCALADDR:
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
|
||||
case WINDIVERT_FILTER_FIELD_LOCALPORT:
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
|
||||
case WINDIVERT_FILTER_FIELD_PROTOCOL:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_FLOW);
|
||||
break;
|
||||
default:
|
||||
pass = TRUE;
|
||||
break;
|
||||
@@ -2248,16 +2403,16 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
val[0] = 0;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
val[0] = (addr->Direction == WINDIVERT_DIRECTION_INBOUND);
|
||||
val[0] = !addr->Outbound;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
val[0] = (addr->Direction == WINDIVERT_DIRECTION_OUTBOUND);
|
||||
val[0] = addr->Outbound;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
val[0] = addr->IfIdx;
|
||||
val[0] = addr->Network.IfIdx;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
val[0] = addr->SubIfIdx;
|
||||
val[0] = addr->Network.SubIfIdx;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOOPBACK:
|
||||
val[0] = addr->Loopback;
|
||||
@@ -2266,22 +2421,26 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
val[0] = addr->Impostor;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP:
|
||||
val[0] = (iphdr != NULL);
|
||||
val[0] = !addr->IPv6;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6:
|
||||
val[0] = (ipv6hdr != NULL);
|
||||
val[0] = addr->IPv6;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP:
|
||||
val[0] = (icmphdr != NULL);
|
||||
val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
|
||||
addr->Flow.Protocol == IPPROTO_ICMP: icmphdr != NULL);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6:
|
||||
val[0] = (icmpv6hdr != NULL);
|
||||
val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
|
||||
addr->Flow.Protocol == IPPROTO_ICMPV6: icmpv6hdr != NULL);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP:
|
||||
val[0] = (tcphdr != NULL);
|
||||
val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
|
||||
addr->Flow.Protocol == IPPROTO_TCP: tcphdr != NULL);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP:
|
||||
val[0] = (udphdr != NULL);
|
||||
val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
|
||||
addr->Flow.Protocol == IPPROTO_UDP: udphdr != NULL);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
|
||||
val[0] = iphdr->HdrLength;
|
||||
@@ -2314,9 +2473,11 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
val[0] = ntohs(iphdr->Checksum);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_SRCADDR:
|
||||
val[1] = 0x0000FFFF;
|
||||
val[0] = ntohl(iphdr->SrcAddr);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_DSTADDR:
|
||||
val[1] = 0x0000FFFF;
|
||||
val[0] = ntohl(iphdr->DstAddr);
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS:
|
||||
@@ -2430,6 +2591,30 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter,
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
val[0] = payload_len;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PROCESSID:
|
||||
val[0] = addr->Flow.ProcessId;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOCALADDR:
|
||||
val[0] = addr->Flow.LocalAddr[0];
|
||||
val[1] = addr->Flow.LocalAddr[1];
|
||||
val[2] = addr->Flow.LocalAddr[2];
|
||||
val[3] = addr->Flow.LocalAddr[3];
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
|
||||
val[0] = addr->Flow.RemoteAddr[0];
|
||||
val[1] = addr->Flow.RemoteAddr[1];
|
||||
val[2] = addr->Flow.RemoteAddr[2];
|
||||
val[3] = addr->Flow.RemoteAddr[3];
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_LOCALPORT:
|
||||
val[0] = addr->Flow.LocalPort;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
|
||||
val[0] = addr->Flow.RemotePort;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_PROTOCOL:
|
||||
val[0] = addr->Flow.Protocol;
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
|
||||
+12
-11
@@ -1260,8 +1260,8 @@ Use <tt>GetLastError()</tt> to get the reason for the error.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
Parses an IPv4 address stored in <tt>addrStr</tt>.
|
||||
If non-<tt>NULL</tt>, the result is stored in <tt>pAddr</tt>
|
||||
in host-byte-order.
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, the is be stored in
|
||||
host-byte-order.
|
||||
Use <tt>htonl()</tt> to convert the result into network-byte-order.
|
||||
</p>
|
||||
<dd></dl>
|
||||
@@ -1289,21 +1289,22 @@ Use <tt>GetLastError()</tt> to get the reason for the error.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
Parses an IPv6 address stored in <tt>addrStr</tt>.
|
||||
If non-<tt>NULL</tt>, the result is stored in <tt>pAddr</tt>.
|
||||
The <tt>pAddr</tt> parameter is assumed to point to a buffer large enough
|
||||
to hold a 16-byte IPv6 address.
|
||||
Given an IPv6 address of the form
|
||||
If <tt>pAddr</tt> is non-<tt>NULL</tt>, the buffer assumed
|
||||
to be large enough to hold a 16-byte IPv6 address.
|
||||
The result is stored in host-byte-order.
|
||||
For example, given an IPv6 address of the form
|
||||
<tt>0011:2233:4455:6677:8899:aabb:ccdd:eeff</tt>, then
|
||||
the result is ordered as follows:
|
||||
<pre>
|
||||
pAddr[0] = 0x00112233
|
||||
pAddr[1] = 0x44556677
|
||||
pAddr[2] = 0x8899aabb
|
||||
pAddr[3] = 0xccddeeff
|
||||
pAddr[0] = 0xccddeeff
|
||||
pAddr[1] = 0x8899aabb
|
||||
pAddr[2] = 0x44556677
|
||||
pAddr[3] = 0x00112233
|
||||
</pre>
|
||||
where each <tt>pAddr[i]</tt> is in host-byte-order.
|
||||
The result can be converted into network-byte-order by setting
|
||||
<tt>pAddr[i] = htonl(pAddr[i])</tt> for each <tt>i</tt>.
|
||||
<tt>pAddr[i] = htonl(pAddr[i])</tt> for each <tt>i</tt> and
|
||||
swapping the array indexes.
|
||||
</p>
|
||||
<dd></dl>
|
||||
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* streamdump.c
|
||||
* (C) 2018, all rights reserved,
|
||||
*
|
||||
* This file is part of WinDivert.
|
||||
*
|
||||
* WinDivert is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* WinDivert is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* usage: flowtrack.exe [filter]
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAX_FLOWS 256
|
||||
|
||||
/*
|
||||
* Flow tracking.
|
||||
*/
|
||||
typedef struct FLOW
|
||||
{
|
||||
WINDIVERT_ADDRESS addr;
|
||||
struct FLOW *next;
|
||||
} FLOW, *PFLOW;
|
||||
|
||||
static HANDLE lock;
|
||||
static PFLOW flows = NULL;
|
||||
|
||||
/*
|
||||
* Print an IP address.
|
||||
*/
|
||||
static void print_address(const UINT32 *addr)
|
||||
{
|
||||
if (addr[3] == 0 && addr[2] == 0 && addr[1] == 0x0000FFFF)
|
||||
{
|
||||
// IPv4 address:
|
||||
UINT32 a, b, c, d;
|
||||
a = (addr[0] >> 24) & 0xFF;
|
||||
b = (addr[0] >> 16) & 0xFF;
|
||||
c = (addr[0] >> 8) & 0xFF;
|
||||
d = (addr[0] >> 0) & 0xFF;
|
||||
printf("%u.%u.%u.%u", a, b, c, d);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv6 address:
|
||||
int i;
|
||||
for (i = 3; i >= 0; i--)
|
||||
{
|
||||
UINT32 a, b;
|
||||
a = (addr[i] >> 16) & 0xFFFF;
|
||||
b = (addr[i] >> 0) & 0xFFFF;
|
||||
printf("%x:%x", a, b);
|
||||
if (i != 0)
|
||||
{
|
||||
putchar(':');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw flows to console in a delayed loop.
|
||||
*
|
||||
* This function does minimal error checking.
|
||||
*/
|
||||
static DWORD draw(LPVOID arg)
|
||||
{
|
||||
const COORD top_left = {0, 0};
|
||||
HANDLE process, console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO screen;
|
||||
char path[MAX_PATH+1];
|
||||
char *filename;
|
||||
const char header[] = "PID PROGRAM PROT FLOW";
|
||||
DWORD rows, columns, written, fill_len, path_len, i;
|
||||
PFLOW flow;
|
||||
WINDIVERT_ADDRESS addrs[MAX_FLOWS], *addr;
|
||||
UINT num_addrs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GetConsoleScreenBufferInfo(console, &screen);
|
||||
SetConsoleCursorPosition(console, top_left);
|
||||
|
||||
rows = screen.srWindow.Bottom - screen.srWindow.Top + 1;
|
||||
columns = screen.srWindow.Right - screen.srWindow.Left + 1;
|
||||
|
||||
// Copy a snapshot of the current flows:
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow = flows;
|
||||
num_addrs = 0;
|
||||
for (i = 0; flow != NULL && i < rows && i < MAX_FLOWS; i++)
|
||||
{
|
||||
memcpy(&addrs[i], &flow->addr, sizeof(addrs[i]));
|
||||
num_addrs++;
|
||||
flow = flow->next;
|
||||
}
|
||||
ReleaseMutex(lock);
|
||||
|
||||
// Print the flows:
|
||||
SetConsoleTextAttribute(console, BACKGROUND_RED | BACKGROUND_GREEN |
|
||||
BACKGROUND_BLUE);
|
||||
WriteConsole(console, header, sizeof(header)-1, &written, NULL);
|
||||
fill_len = columns - (sizeof(header)-1);
|
||||
if (fill_len > 0)
|
||||
{
|
||||
COORD pos = {sizeof(header)-1, 0};
|
||||
FillConsoleOutputCharacterA(console, ' ', fill_len, pos,
|
||||
&written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
|
||||
fill_len, pos, &written);
|
||||
}
|
||||
putchar('\n');
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
for (i = 0; i < num_addrs && i < rows-1; i++)
|
||||
{
|
||||
COORD pos = {0, i+1};
|
||||
addr = &addrs[i];
|
||||
FillConsoleOutputCharacterA(console, ' ', columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
SetConsoleCursorPosition(console, pos);
|
||||
if (i == rows-2 && (i+1) < num_addrs)
|
||||
{
|
||||
fputs("...", stdout);
|
||||
fflush(stdout);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%-10d ", addr->Flow.ProcessId);
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
|
||||
addr->Flow.ProcessId);
|
||||
path_len = 0;
|
||||
if (process != NULL)
|
||||
{
|
||||
path_len = GetProcessImageFileName(process, path, sizeof(path));
|
||||
CloseHandle(process);
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
if (path_len != 0)
|
||||
{
|
||||
filename = PathFindFileName(path);
|
||||
printf("%-20.20s ", filename);
|
||||
}
|
||||
else if (addr->Flow.ProcessId == 4)
|
||||
{
|
||||
fputs("Windows ", stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs("??? ", stdout);
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
switch (addr->Flow.Protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
printf("TCP ");
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("UDP ");
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("ICMP ");
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
printf("ICMPV6 ");
|
||||
break;
|
||||
default:
|
||||
printf("%-6u ", addr->Flow.Protocol);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
print_address(addr->Flow.LocalAddr);
|
||||
printf(":%u %s ", addr->Flow.LocalPort,
|
||||
(addr->Outbound? "---->": "<----"));
|
||||
print_address(addr->Flow.RemoteAddr);
|
||||
printf(":%u", addr->Flow.RemotePort);
|
||||
fflush(stdout);
|
||||
}
|
||||
for (; i < rows-1; i++)
|
||||
{
|
||||
COORD pos = {0, i+1};
|
||||
FillConsoleOutputCharacterA(console, ' ', columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
*/
|
||||
int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle, thread;
|
||||
INT16 priority = 776; // Arbitrary.
|
||||
const char *filter = "true", *err_str;
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
PFLOW flow, prev;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
filter = argv[1];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [filter]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Spawn the draw() thread.
|
||||
lock = CreateMutex(NULL, FALSE, NULL);
|
||||
thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)draw, NULL, 0,
|
||||
NULL);
|
||||
if (thread == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to create thread (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
CloseHandle(thread);
|
||||
|
||||
// Open WinDivert FLOW handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_FLOW, priority,
|
||||
WINDIVERT_FLAGS_LAYER_FLOW);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCheckFilter(filter, WINDIVERT_LAYER_FLOW,
|
||||
&err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Main loop:
|
||||
while (TRUE)
|
||||
{
|
||||
if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_FLOW_ESTABLISHED:
|
||||
|
||||
// Flow established:
|
||||
flow = (PFLOW)malloc(sizeof(FLOW));
|
||||
if (flow == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to allocate memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memcpy(&flow->addr, &addr, sizeof(flow->addr));
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow->next = flows;
|
||||
flows = flow;
|
||||
ReleaseMutex(lock);
|
||||
break;
|
||||
|
||||
case WINDIVERT_EVENT_FLOW_DELETED:
|
||||
|
||||
// Flow deleted:
|
||||
prev = NULL;
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow = flows;
|
||||
while (flow != NULL)
|
||||
{
|
||||
if (memcmp(&addr.Flow, &flow->addr.Flow,
|
||||
sizeof(addr.Flow)) == 0)
|
||||
{
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = flow->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
flows = flow->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = flow;
|
||||
flow = flow->next;
|
||||
}
|
||||
ReleaseMutex(lock);
|
||||
free(flow);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -156,9 +156,8 @@ int __cdecl main(int argc, char **argv)
|
||||
(double)freq.QuadPart;
|
||||
printf("Packet [Timestamp=%.8g, Direction=%s IfIdx=%u SubIfIdx=%u "
|
||||
"Loopback=%u]\n",
|
||||
time_passed, (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND?
|
||||
"outbound": "inbound"), addr.IfIdx, addr.SubIfIdx,
|
||||
addr.Loopback);
|
||||
time_passed, (addr.Outbound? "outbound": "inbound"),
|
||||
addr.Network.IfIdx, addr.Network.SubIfIdx, addr.Loopback);
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
UINT8 *src_addr = (UINT8 *)&ip_header->SrcAddr;
|
||||
|
||||
@@ -287,7 +287,7 @@ int __cdecl main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET),
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)reset, sizeof(TCPPACKET),
|
||||
@@ -314,7 +314,7 @@ int __cdecl main(int argc, char **argv)
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)resetv6,
|
||||
sizeof(TCPV6PACKET), &send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET),
|
||||
@@ -340,7 +340,7 @@ int __cdecl main(int argc, char **argv)
|
||||
dnr->ip.DstAddr = ip_header->SrcAddr;
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)dnr, icmp_length,
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, &send_addr,
|
||||
@@ -363,7 +363,7 @@ int __cdecl main(int argc, char **argv)
|
||||
sizeof(dnrv6->ipv6.DstAddr));
|
||||
|
||||
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
|
||||
send_addr.Direction = !recv_addr.Direction;
|
||||
send_addr.Outbound = !recv_addr.Outbound;
|
||||
WinDivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length,
|
||||
&send_addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)dnrv6, icmpv6_length,
|
||||
|
||||
@@ -257,41 +257,39 @@ read_failed:
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Direction)
|
||||
if (addr.Outbound)
|
||||
{
|
||||
case WINDIVERT_DIRECTION_OUTBOUND:
|
||||
if (tcp_header->DstPort == htons(port))
|
||||
{
|
||||
// Reflect: PORT ---> PROXY
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->DstPort = htons(proxy_port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Direction = WINDIVERT_DIRECTION_INBOUND;
|
||||
}
|
||||
else if (tcp_header->SrcPort == htons(proxy_port))
|
||||
{
|
||||
// Reflect: PROXY ---> PORT
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->SrcPort = htons(port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Direction = WINDIVERT_DIRECTION_INBOUND;
|
||||
}
|
||||
else if (tcp_header->DstPort == htons(alt_port))
|
||||
{
|
||||
// Redirect: ALT ---> PORT
|
||||
tcp_header->DstPort = htons(port);
|
||||
}
|
||||
break;
|
||||
|
||||
case WINDIVERT_DIRECTION_INBOUND:
|
||||
if (tcp_header->SrcPort == htons(port))
|
||||
{
|
||||
// Redirect: PORT ---> ALT
|
||||
tcp_header->SrcPort = htons(alt_port);
|
||||
}
|
||||
break;
|
||||
if (tcp_header->DstPort == htons(port))
|
||||
{
|
||||
// Reflect: PORT ---> PROXY
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->DstPort = htons(proxy_port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Outbound = FALSE;
|
||||
}
|
||||
else if (tcp_header->SrcPort == htons(proxy_port))
|
||||
{
|
||||
// Reflect: PROXY ---> PORT
|
||||
UINT32 dst_addr = ip_header->DstAddr;
|
||||
tcp_header->SrcPort = htons(port);
|
||||
ip_header->DstAddr = ip_header->SrcAddr;
|
||||
ip_header->SrcAddr = dst_addr;
|
||||
addr.Outbound = FALSE;
|
||||
}
|
||||
else if (tcp_header->DstPort == htons(alt_port))
|
||||
{
|
||||
// Redirect: ALT ---> PORT
|
||||
tcp_header->DstPort = htons(port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tcp_header->SrcPort == htons(port))
|
||||
{
|
||||
// Redirect: PORT ---> ALT
|
||||
tcp_header->SrcPort = htons(alt_port);
|
||||
}
|
||||
}
|
||||
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, &addr, 0);
|
||||
|
||||
@@ -238,7 +238,7 @@ int __cdecl main(int argc, char **argv)
|
||||
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
|
||||
blockpage->header.tcp.AckNum =
|
||||
htonl(ntohl(tcp_header->SeqNum) + payload_len);
|
||||
addr.Direction = !addr.Direction; // Reverse direction.
|
||||
addr.Outbound = !addr.Outbound; // Reverse direction.
|
||||
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, &addr, 0);
|
||||
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
|
||||
NULL))
|
||||
|
||||
+66
-20
@@ -70,43 +70,90 @@ extern "C" {
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Divert address.
|
||||
* WinDivert NETWORK and NETWORK_FORWARD layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 IfIdx; /* Packet's interface index. */
|
||||
UINT32 SubIfIdx; /* Packet's sub-interface index. */
|
||||
} WINDIVERT_NETWORK_DATA, *PWINDIVERT_NETWORK_DATA;
|
||||
|
||||
/*
|
||||
* WinDivert FLOW layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ProcessId; /* Process ID. */
|
||||
UINT32 LocalAddr[4]; /* Local address. */
|
||||
UINT32 RemoteAddr[4]; /* Remote address. */
|
||||
UINT16 LocalPort; /* Local port. */
|
||||
UINT16 RemotePort; /* Remote port. */
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_FLOW_DATA, *PWINDIVERT_FLOW_DATA;
|
||||
|
||||
/*
|
||||
* WinDivert address.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Packet's timestamp. */
|
||||
UINT32 IfIdx; /* Packet's interface index. */
|
||||
UINT32 SubIfIdx; /* Packet's sub-interface index. */
|
||||
UINT8 Direction:1; /* Packet's direction. */
|
||||
UINT8 Loopback:1; /* Packet is loopback? */
|
||||
UINT8 Impostor:1; /* Packet is impostor? */
|
||||
UINT8 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
|
||||
UINT8 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
|
||||
UINT8 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
|
||||
UINT8 Reserved:2;
|
||||
UINT32 Layer:8; /* Packet's layer. */
|
||||
UINT32 Event:8; /* Packet event. */
|
||||
UINT32 Outbound:1; /* Packet is outound? */
|
||||
UINT32 Loopback:1; /* Packet is loopback? */
|
||||
UINT32 Impostor:1; /* Packet is impostor? */
|
||||
UINT32 IPv6:1; /* Packet is IPv6? */
|
||||
UINT32 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
|
||||
UINT32 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
|
||||
UINT32 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
|
||||
UINT32 Reserved:9;
|
||||
union
|
||||
{
|
||||
WINDIVERT_NETWORK_DATA Network; /* Network layer data. */
|
||||
WINDIVERT_FLOW_DATA Flow; /* Flow layer data. */
|
||||
};
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
|
||||
#define WINDIVERT_DIRECTION_OUTBOUND 0
|
||||
#define WINDIVERT_DIRECTION_INBOUND 1
|
||||
|
||||
/*
|
||||
* Divert layers.
|
||||
* WinDivert layers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 1 /* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_NETWORK = 1, /* Network layer. */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 2,/* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_FLOW = 3 /* Flow layer. */
|
||||
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
|
||||
|
||||
/*
|
||||
* Divert flags.
|
||||
* WinDivert events.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_EVENT_NETWORK_PACKET = 0, /* Network packet. */
|
||||
WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
|
||||
/* Flow established. */
|
||||
WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
|
||||
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAG_SNIFF 1
|
||||
#define WINDIVERT_FLAG_DROP 2
|
||||
#define WINDIVERT_FLAG_DEBUG 4
|
||||
#define WINDIVERT_FLAG_RECV_ONLY 4
|
||||
#define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY
|
||||
#define WINDIVERT_FLAG_SEND_ONLY 8
|
||||
#define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY
|
||||
#define WINDIVERT_FLAG_DEBUG 16
|
||||
|
||||
#define WINDIVERT_FLAGS_LAYER_NETWORK 0
|
||||
#define WINDIVERT_FLAGS_LAYER_NETWORK_FORWARD \
|
||||
0
|
||||
#define WINDIVERT_FLAGS_LAYER_FLOW \
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY)
|
||||
|
||||
/*
|
||||
* Divert parameters.
|
||||
* WinDivert parameters.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@@ -396,7 +443,6 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperCheckFilter(
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__in PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__in PWINDIVERT_ADDRESS pAddr);
|
||||
|
||||
+25
-18
@@ -44,8 +44,8 @@
|
||||
#define WINDIVERT_KERNEL
|
||||
#include "windivert.h"
|
||||
|
||||
#define WINDIVERT_VERSION 1
|
||||
#define WINDIVERT_VERSION_MINOR 4
|
||||
#define WINDIVERT_VERSION 2
|
||||
#define WINDIVERT_VERSION_MINOR 0
|
||||
|
||||
#define WINDIVERT_STR2(s) #s
|
||||
#define WINDIVERT_STR(s) WINDIVERT_STR2(s)
|
||||
@@ -59,8 +59,8 @@
|
||||
#define WINDIVERT_DEVICE_NAME \
|
||||
L"WinDivert" WINDIVERT_VERSION_LSTR
|
||||
|
||||
#define WINDIVERT_IOCTL_VERSION 6
|
||||
#define WINDIVERT_IOCTL_MAGIC 0xA2BF
|
||||
#define WINDIVERT_IOCTL_VERSION 7
|
||||
#define WINDIVERT_IOCTL_MAGIC 0xC7C9
|
||||
|
||||
#define WINDIVERT_FILTER_FIELD_ZERO 0
|
||||
#define WINDIVERT_FILTER_FIELD_INBOUND 1
|
||||
@@ -122,8 +122,14 @@
|
||||
#define WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH 57
|
||||
#define WINDIVERT_FILTER_FIELD_LOOPBACK 58
|
||||
#define WINDIVERT_FILTER_FIELD_IMPOSTOR 59
|
||||
#define WINDIVERT_FILTER_FIELD_PROCESSID 60
|
||||
#define WINDIVERT_FILTER_FIELD_LOCALADDR 61
|
||||
#define WINDIVERT_FILTER_FIELD_REMOTEADDR 62
|
||||
#define WINDIVERT_FILTER_FIELD_LOCALPORT 63
|
||||
#define WINDIVERT_FILTER_FIELD_REMOTEPORT 64
|
||||
#define WINDIVERT_FILTER_FIELD_PROTOCOL 65
|
||||
#define WINDIVERT_FILTER_FIELD_MAX \
|
||||
WINDIVERT_FILTER_FIELD_IMPOSTOR
|
||||
WINDIVERT_FILTER_FIELD_PROTOCOL
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
@@ -142,20 +148,21 @@
|
||||
* WinDivert layers.
|
||||
*/
|
||||
#define WINDIVERT_LAYER_DEFAULT WINDIVERT_LAYER_NETWORK
|
||||
#define WINDIVERT_LAYER_MAX \
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAGS_ALL \
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_DEBUG)
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_DEBUG)
|
||||
#define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \
|
||||
(((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2)))
|
||||
#define WINDIVERT_FLAGS_VALID(flags) \
|
||||
((((flags) & ~WINDIVERT_FLAGS_ALL) == 0) && \
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_SNIFF, \
|
||||
WINDIVERT_FLAG_DROP))
|
||||
WINDIVERT_FLAG_DROP) && \
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_RECV_ONLY, \
|
||||
WINDIVERT_FLAG_SEND_ONLY))
|
||||
|
||||
/*
|
||||
* WinDivert priorities.
|
||||
@@ -197,7 +204,7 @@ typedef struct windivert_ioctl_s *windivert_ioctl_t;
|
||||
*/
|
||||
struct windivert_ioctl_filter_s
|
||||
{
|
||||
UINT8 field; // WINDIVERT_FILTER_FIELD_IP_*
|
||||
UINT8 field; // WINDIVERT_FILTER_FIELD_*
|
||||
UINT8 test; // WINDIVERT_FILTER_TEST_*
|
||||
UINT16 success; // Success continuation.
|
||||
UINT16 failure; // Fail continuation.
|
||||
@@ -210,20 +217,20 @@ typedef struct windivert_ioctl_filter_s *windivert_ioctl_filter_t;
|
||||
* IOCTL codes.
|
||||
*/
|
||||
#define IOCTL_WINDIVERT_RECV \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x908, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x918, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_SEND \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x909, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x919, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_START_FILTER \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90A, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91A, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_SET_LAYER \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90B, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91B, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_SET_PRIORITY \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90C, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91C, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_SET_FLAGS \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90D, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91D, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_SET_PARAM \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90E, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91E, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WINDIVERT_GET_PARAM \
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x90F, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_NETWORK, 0x91F, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#endif /* __WINDIVERT_DEVICE_H */
|
||||
|
||||
@@ -97,6 +97,10 @@ do
|
||||
$CC -s -O2 -Iinclude/ examples/streamdump/streamdump.c \
|
||||
-o "install/MINGW/$CPU/streamdump.exe" -lWinDivert -lws2_32 \
|
||||
-L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/flowtrack.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/flowtrack/flowtrack.c \
|
||||
-o "install/MINGW/$CPU/flowtrack.exe" -lWinDivert -lws2_32 -lpsapi \
|
||||
-lshlwapi -L"install/MINGW/$CPU/"
|
||||
echo "\tcopy install/MINGW/$CPU/WinDivert$BITS.sys..."
|
||||
cp install/WDDK/$CPU/WinDivert$BITS.sys install/MINGW/$CPU
|
||||
else
|
||||
|
||||
@@ -90,6 +90,8 @@ do
|
||||
cp install/$TARGET/i386/webfilter.exe $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/x86/streamdump.exe..."
|
||||
cp install/$TARGET/i386/streamdump.exe $INSTALL/x86
|
||||
echo "\tcopy $INSTALL/i386/flowtrack.exe..."
|
||||
cp install/$TARGET/i386/flowtrack.exe $INSTALL/amd64
|
||||
if [ -d "install/$TARGET/amd64" ]
|
||||
then
|
||||
echo "\tmake $INSTALL/amd64..."
|
||||
@@ -115,6 +117,8 @@ do
|
||||
cp install/$TARGET/amd64/webfilter.exe $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/streamdump.exe..."
|
||||
cp install/$TARGET/amd64/streamdump.exe $INSTALL/amd64
|
||||
echo "\tcopy $INSTALL/amd64/flowtrack.exe..."
|
||||
cp install/$TARGET/amd64/flowtrack.exe $INSTALL/amd64
|
||||
else
|
||||
echo "\tWARNING: skipping missing AMD64 build..."
|
||||
fi
|
||||
|
||||
+1213
-529
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user