Add a new REFLECT layer to WinDivert (see #156).
Adds a new REFLECT layer for monitoring WinDivert handles. This includes: - three new REFLECT events: ESTABLISHED, OPEN and CLOSE; - modifying the ADDRESS for REFLECT data: open time, process-id, layer, flags, and priority of the opened handle; and - allowing WinDivertRecv() to read a representation of the opened filter. This change also includes a new "object" representation for WinDivert filter strings. The API has been updated as follows: - WinDivertHelperCompileFilter (replaces CheckFilter) compiles filter strings into the object form; and - WinDivertHelperFormatFilter can "decompile" an object back into a human-readable filter string. Other: - New NO_INSTALL flag. - New windivertctl.exe sample program.
This commit is contained in:
+23
-276
@@ -119,13 +119,10 @@ static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped);
|
||||
static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len);
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
static void WinDivertFilterDump(windivert_ioctl_filter_t filter, UINT16 len);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include the helper API implementation.
|
||||
*/
|
||||
#include "windivert_shared.c"
|
||||
#include "windivert_helper.c"
|
||||
|
||||
/*
|
||||
@@ -379,7 +376,7 @@ static BOOL WinDivertIoControl(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
UINT64 arg, PVOID buf, UINT len, UINT *iolen, LPOVERLAPPED overlapped)
|
||||
{
|
||||
struct windivert_ioctl_s ioctl;
|
||||
WINDIVERT_IOCTL ioctl;
|
||||
BOOL result;
|
||||
DWORD iolen0;
|
||||
|
||||
@@ -402,24 +399,21 @@ static BOOL WinDivertIoControlEx(HANDLE handle, DWORD code, UINT8 arg8,
|
||||
extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
INT16 priority, UINT64 flags)
|
||||
{
|
||||
struct windivert_ioctl_filter_s object[WINDIVERT_FILTER_MAXLEN];
|
||||
WINDIVERT_FILTER object[WINDIVERT_FILTER_MAXLEN];
|
||||
UINT obj_len;
|
||||
ERROR comp_err;
|
||||
DWORD err;
|
||||
HANDLE handle;
|
||||
SC_HANDLE service;
|
||||
UINT32 priority32;
|
||||
|
||||
UINT64 priority64, filter_flags;
|
||||
|
||||
// Parameter checking.
|
||||
if (layer == 0)
|
||||
{
|
||||
layer = WINDIVERT_LAYER_NETWORK;
|
||||
}
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
break;
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
@@ -431,25 +425,21 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
priority32 = WINDIVERT_PRIORITY(priority);
|
||||
if (priority32 < WINDIVERT_PRIORITY_MIN ||
|
||||
priority32 > WINDIVERT_PRIORITY_MAX)
|
||||
if (priority < WINDIVERT_PRIORITY_MIN ||
|
||||
priority > WINDIVERT_PRIORITY_MAX)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Compile the filter:
|
||||
// Compile & analyze the filter:
|
||||
comp_err = WinDivertCompileFilter(filter, layer, object, &obj_len);
|
||||
if (IS_ERROR(comp_err))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
WinDivertFilterDump(object, obj_len);
|
||||
#endif
|
||||
filter_flags = WinDivertAnalyzeFilter(object, obj_len);
|
||||
|
||||
// Attempt to open the WinDivert device:
|
||||
handle = CreateFile(L"\\\\.\\" WINDIVERT_DEVICE_NAME,
|
||||
@@ -464,6 +454,11 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Open failed because the device isn't installed; install it now.
|
||||
if ((flags & WINDIVERT_FLAG_NO_INSTALL) != 0)
|
||||
{
|
||||
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
SetLastError(0);
|
||||
service = WinDivertDriverInstall();
|
||||
if (service == NULL)
|
||||
@@ -503,8 +498,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
// Set the flags:
|
||||
if (flags != 0)
|
||||
{
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_FLAGS, 0,
|
||||
(UINT64)flags, NULL, 0, NULL))
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_FLAGS, 0, flags,
|
||||
NULL, 0, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -512,10 +507,12 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Set the priority:
|
||||
if (priority32 != WINDIVERT_PRIORITY_DEFAULT)
|
||||
if (priority != WINDIVERT_PRIORITY_DEFAULT)
|
||||
{
|
||||
// Make positive:
|
||||
priority64 = (UINT64)((INT64)priority + WINDIVERT_PRIORITY_MAX);
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_SET_PRIORITY, 0,
|
||||
(UINT64)priority32, NULL, 0, NULL))
|
||||
priority64, NULL, 0, NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -523,8 +520,8 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
}
|
||||
|
||||
// Start the filter:
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_START_FILTER, 0, 0,
|
||||
object, obj_len*sizeof(struct windivert_ioctl_filter_s), NULL))
|
||||
if (!WinDivertIoControl(handle, IOCTL_WINDIVERT_START_FILTER, 0,
|
||||
filter_flags, object, obj_len * sizeof(WINDIVERT_FILTER), NULL))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@@ -856,253 +853,3 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* DEBUGGING */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef WINDIVERT_DEBUG
|
||||
/*
|
||||
* Print a filter (debugging).
|
||||
*/
|
||||
static void WinDivertFilterDump(windivert_ioctl_filter_t filter, UINT16 len)
|
||||
{
|
||||
UINT16 i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
printf("label_%u:\n\tif (", i);
|
||||
switch (filter[i].field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
printf("zero ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
printf("inbound ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
printf("outbound ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
printf("ifIdx ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
printf("subIfIdx ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP:
|
||||
printf("ip ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6:
|
||||
printf("ipv6 ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP:
|
||||
printf("icmp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6:
|
||||
printf("icmpv6 ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP:
|
||||
printf("tcp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP:
|
||||
printf("udp ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
|
||||
printf("ip.HdrLength ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_TOS:
|
||||
printf("ip.TOS ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_LENGTH:
|
||||
printf("ip.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_ID:
|
||||
printf("ip.Id ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_DF:
|
||||
printf("ip.DF ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_MF:
|
||||
printf("ip.MF ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_FRAGOFF:
|
||||
printf("ip.FragOff ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_TTL:
|
||||
printf("ip.TTL ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_PROTOCOL:
|
||||
printf("ip.Protocol ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_CHECKSUM:
|
||||
printf("ip.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_SRCADDR:
|
||||
printf("ip.SrcAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_DSTADDR:
|
||||
printf("ip.DstAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS:
|
||||
printf("ipv6.TrafficClass ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL:
|
||||
printf("ipv6.FlowLabel ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_LENGTH:
|
||||
printf("ipv6.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR:
|
||||
printf("ipv6.NextHdr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT:
|
||||
printf("ipv6.HopLimit ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
|
||||
printf("ipv6.SrcAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
|
||||
printf("ipv6.DstAddr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_TYPE:
|
||||
printf("icmp.Type ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_CODE:
|
||||
printf("icmp.Code ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM:
|
||||
printf("icmp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMP_BODY:
|
||||
printf("icmp.Body ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE:
|
||||
printf("icmpv6.Type ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_CODE:
|
||||
printf("icmpv6.Code ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM:
|
||||
printf("icmpv6.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_ICMPV6_BODY:
|
||||
printf("icmpv6.Body ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SRCPORT:
|
||||
printf("tcp.SrcPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_DSTPORT:
|
||||
printf("tcp.DstPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SEQNUM:
|
||||
printf("tcp.SeqNum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_ACKNUM:
|
||||
printf("tcp.AckNum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH:
|
||||
printf("tcp.HdrLength ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URG:
|
||||
printf("tcp.Urg ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_ACK:
|
||||
printf("tcp.Ack ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PSH:
|
||||
printf("tcp.Psh ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_RST:
|
||||
printf("tcp.Rst ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_SYN:
|
||||
printf("tcp.Syn ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_FIN:
|
||||
printf("tcp.Fin ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_WINDOW:
|
||||
printf("tcp.Window ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM:
|
||||
printf("tcp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_URGPTR:
|
||||
printf("tcp.UrgPtr ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH:
|
||||
printf("tcp.PayloadLength " );
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_SRCPORT:
|
||||
printf("udp.SrcPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_DSTPORT:
|
||||
printf("udp.DstPort ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_LENGTH:
|
||||
printf("udp.Length ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM:
|
||||
printf("udp.Checksum ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
|
||||
printf("udp.PayloadLength ");
|
||||
break;
|
||||
default:
|
||||
printf("unknown.Field ");
|
||||
break;
|
||||
}
|
||||
switch (filter[i].test)
|
||||
{
|
||||
case WINDIVERT_FILTER_TEST_EQ:
|
||||
printf("== ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_NEQ:
|
||||
printf("!= ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_LT:
|
||||
printf("< ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_LEQ:
|
||||
printf("<= ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_GT:
|
||||
printf("> ");
|
||||
break;
|
||||
case WINDIVERT_FILTER_TEST_GEQ:
|
||||
printf(">= ");
|
||||
break;
|
||||
default:
|
||||
printf("?? ");
|
||||
break;
|
||||
}
|
||||
printf("%u)\n", filter[i].arg[0]);
|
||||
switch (filter[i].success)
|
||||
{
|
||||
case WINDIVERT_FILTER_RESULT_ACCEPT:
|
||||
printf("\t\treturn ACCEPT;\n");
|
||||
break;
|
||||
case WINDIVERT_FILTER_RESULT_REJECT:
|
||||
printf("\t\treturn REJECT;\n");
|
||||
break;
|
||||
default:
|
||||
printf("\t\tgoto label_%u;\n", filter[i].success);
|
||||
break;
|
||||
}
|
||||
printf("\telse\n");
|
||||
switch (filter[i].failure)
|
||||
{
|
||||
case WINDIVERT_FILTER_RESULT_ACCEPT:
|
||||
printf("\t\treturn ACCEPT;\n");
|
||||
break;
|
||||
case WINDIVERT_FILTER_RESULT_REJECT:
|
||||
printf("\t\treturn REJECT;\n");
|
||||
break;
|
||||
default:
|
||||
printf("\t\tgoto label_%u;\n", filter[i].failure);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WINDIVERT_DEBUG */
|
||||
|
||||
|
||||
+2
-1
@@ -13,5 +13,6 @@ EXPORTS
|
||||
WinDivertHelperParsePacket
|
||||
WinDivertHelperParseIPv4Address
|
||||
WinDivertHelperParseIPv6Address
|
||||
WinDivertHelperCheckFilter
|
||||
WinDivertHelperCompileFilter
|
||||
WinDivertHelperEvalFilter
|
||||
WinDivertHelperFormatFilter
|
||||
|
||||
+1573
-116
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ static void print_address(const UINT32 *addr)
|
||||
if (addr[3] == 0 && addr[2] == 0 && addr[1] == 0x0000FFFF)
|
||||
{
|
||||
// IPv4 address:
|
||||
UINT32 a, b, c, d;
|
||||
UINT32 a, b, c, d;
|
||||
a = (addr[0] >> 24) & 0xFF;
|
||||
b = (addr[0] >> 16) & 0xFF;
|
||||
c = (addr[0] >> 8) & 0xFF;
|
||||
@@ -82,9 +82,9 @@ static void print_address(const UINT32 *addr)
|
||||
int i;
|
||||
for (i = 3; i >= 0; i--)
|
||||
{
|
||||
UINT32 a, b;
|
||||
a = (addr[i] >> 16) & 0xFFFF;
|
||||
b = (addr[i] >> 0) & 0xFFFF;
|
||||
UINT32 a, b;
|
||||
a = (addr[i] >> 16) & 0xFFFF;
|
||||
b = (addr[i] >> 0) & 0xFFFF;
|
||||
printf("%x:%x", a, b);
|
||||
if (i != 0)
|
||||
{
|
||||
@@ -114,8 +114,8 @@ static DWORD draw(LPVOID arg)
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GetConsoleScreenBufferInfo(console, &screen);
|
||||
SetConsoleCursorPosition(console, top_left);
|
||||
GetConsoleScreenBufferInfo(console, &screen);
|
||||
SetConsoleCursorPosition(console, top_left);
|
||||
|
||||
rows = screen.srWindow.Bottom - screen.srWindow.Top + 1;
|
||||
columns = screen.srWindow.Right - screen.srWindow.Left + 1;
|
||||
@@ -132,7 +132,7 @@ static DWORD draw(LPVOID arg)
|
||||
}
|
||||
ReleaseMutex(lock);
|
||||
|
||||
// Print the flows:
|
||||
// Print the flows:
|
||||
SetConsoleTextAttribute(console, BACKGROUND_RED | BACKGROUND_GREEN |
|
||||
BACKGROUND_BLUE);
|
||||
WriteConsole(console, header, sizeof(header)-1, &written, NULL);
|
||||
@@ -142,21 +142,21 @@ static DWORD draw(LPVOID arg)
|
||||
COORD pos = {sizeof(header)-1, 0};
|
||||
FillConsoleOutputCharacterA(console, ' ', fill_len, pos,
|
||||
&written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FillConsoleOutputAttribute(console,
|
||||
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
|
||||
fill_len, pos, &written);
|
||||
fill_len, pos, &written);
|
||||
}
|
||||
putchar('\n');
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
for (i = 0; i < num_addrs && i < rows-1; i++)
|
||||
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);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
SetConsoleCursorPosition(console, pos);
|
||||
if (i == rows-2 && (i+1) < num_addrs)
|
||||
{
|
||||
@@ -191,7 +191,7 @@ static DWORD draw(LPVOID arg)
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
switch (addr->Flow.Protocol)
|
||||
switch (addr->Flow.Protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
@@ -227,9 +227,9 @@ static DWORD draw(LPVOID arg)
|
||||
{
|
||||
COORD pos = {0, i+1};
|
||||
FillConsoleOutputCharacterA(console, ' ', columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
FillConsoleOutputAttribute(console,
|
||||
FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
columns, pos, &written);
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
@@ -260,7 +260,24 @@ int __cdecl main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Spawn the draw() thread.
|
||||
// Open WinDivert FLOW handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_FLOW, priority,
|
||||
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_FLOW,
|
||||
NULL, 0, &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;
|
||||
}
|
||||
|
||||
// Spawn the draw() thread.
|
||||
lock = CreateMutex(NULL, FALSE, NULL);
|
||||
thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)draw, NULL, 0,
|
||||
NULL);
|
||||
@@ -272,23 +289,6 @@ int __cdecl main(int argc, char **argv)
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -302,7 +302,7 @@ int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
case WINDIVERT_EVENT_FLOW_ESTABLISHED:
|
||||
|
||||
// Flow established:
|
||||
// Flow established:
|
||||
flow = (PFLOW)malloc(sizeof(FLOW));
|
||||
if (flow == NULL)
|
||||
{
|
||||
@@ -318,7 +318,7 @@ int __cdecl main(int argc, char **argv)
|
||||
|
||||
case WINDIVERT_EVENT_FLOW_DELETED:
|
||||
|
||||
// Flow deleted:
|
||||
// Flow deleted:
|
||||
prev = NULL;
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
flow = flows;
|
||||
|
||||
@@ -100,8 +100,8 @@ int __cdecl main(int argc, char **argv)
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCheckFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
&err_str, NULL))
|
||||
!WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -170,8 +170,8 @@ int __cdecl main(int argc, char **argv)
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCheckFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
&err_str, NULL))
|
||||
!WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK,
|
||||
NULL, 0, &err_str, NULL))
|
||||
{
|
||||
fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* 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: windivertctl.exe list
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAX_PACKET 0xFFFF
|
||||
#define MAX_FILTER_LEN 30000
|
||||
|
||||
/*
|
||||
* Process info.
|
||||
*/
|
||||
typedef struct INFO
|
||||
{
|
||||
UINT32 process_id;
|
||||
UINT32 ref_count;
|
||||
HANDLE process;
|
||||
struct INFO *next;
|
||||
} INFO, *PINFO;
|
||||
|
||||
static INFO *open = NULL; // All open handles
|
||||
|
||||
/*
|
||||
* Modes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LIST,
|
||||
WATCH,
|
||||
KILLALL
|
||||
} MODE;
|
||||
|
||||
/*
|
||||
* Months.
|
||||
*/
|
||||
static const char *months[12] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
||||
"Nov", "Dec"
|
||||
};
|
||||
|
||||
/*
|
||||
* Add a new process.
|
||||
*/
|
||||
static HANDLE add_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open;
|
||||
HANDLE process;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
info->ref_count++;
|
||||
return info->process;
|
||||
}
|
||||
info = info->next;
|
||||
}
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE,
|
||||
FALSE, process_id);
|
||||
info = (INFO *)malloc(sizeof(INFO));
|
||||
if (info == NULL)
|
||||
{
|
||||
fprintf(stderr, "error: failed to allocate memory (%d)\n",
|
||||
GetLastError());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
info->process_id = process_id;
|
||||
info->process = process;
|
||||
info->ref_count = 1;
|
||||
info->next = open;
|
||||
open = info;
|
||||
return process;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a process.
|
||||
*/
|
||||
static HANDLE lookup_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
return info->process;
|
||||
}
|
||||
info = info->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an old process.
|
||||
*/
|
||||
static void remove_process(UINT32 process_id)
|
||||
{
|
||||
PINFO info = open, prev = NULL;
|
||||
|
||||
while (info != NULL)
|
||||
{
|
||||
if (info->process_id == process_id)
|
||||
{
|
||||
info->ref_count--;
|
||||
if (info->ref_count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = info;
|
||||
info = info->next;
|
||||
}
|
||||
|
||||
if (info->process != NULL)
|
||||
{
|
||||
CloseHandle(info->process);
|
||||
}
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = info->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
open = info->next;
|
||||
}
|
||||
free(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry.
|
||||
*/
|
||||
int __cdecl main(int argc, char **argv)
|
||||
{
|
||||
HANDLE handle, process, console;
|
||||
INT16 priority = -333; // Arbitrary.
|
||||
UINT packet_len;
|
||||
static UINT8 packet[MAX_PACKET];
|
||||
static char path[MAX_PATH+1];
|
||||
static char filter_str[MAX_FILTER_LEN];
|
||||
PVOID object;
|
||||
DWORD path_len;
|
||||
BOOL or;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
ULONGLONG freq, start_count;
|
||||
LARGE_INTEGER li;
|
||||
MODE mode;
|
||||
const char *filter = "true";
|
||||
const char *err_str = NULL;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
{
|
||||
usage:
|
||||
fprintf(stderr, "usage: %s (list|watch|killall) [filter]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (strcmp(argv[1], "list") == 0)
|
||||
{
|
||||
mode = LIST;
|
||||
}
|
||||
else if (strcmp(argv[1], "watch") == 0)
|
||||
{
|
||||
mode = WATCH;
|
||||
}
|
||||
else if (strcmp(argv[1], "killall") == 0)
|
||||
{
|
||||
mode = KILLALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
if (argc == 3)
|
||||
{
|
||||
filter = argv[2];
|
||||
}
|
||||
|
||||
// Time management
|
||||
QueryPerformanceFrequency(&li);
|
||||
freq = li.QuadPart;
|
||||
QueryPerformanceCounter(&li);
|
||||
start_count = li.QuadPart;
|
||||
|
||||
// Open WinDivert REFLECT handle:
|
||||
handle = WinDivertOpen(filter, WINDIVERT_LAYER_REFLECT, priority,
|
||||
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY |
|
||||
(mode == WATCH? 0: WINDIVERT_FLAG_NO_INSTALL));
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (mode != WATCH && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
|
||||
{
|
||||
// WinDivert driver is not running, so no open handles.
|
||||
return 0;
|
||||
}
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_FLOW,
|
||||
NULL, 0, &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:
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
while (TRUE)
|
||||
{
|
||||
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
|
||||
{
|
||||
fprintf(stderr, "failed to event (%d)\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (addr.Event)
|
||||
{
|
||||
case WINDIVERT_EVENT_REFLECT_ESTABLISHED:
|
||||
case WINDIVERT_EVENT_REFLECT_OPEN:
|
||||
// Open handle:
|
||||
process = add_process(addr.Reflect.ProcessId);
|
||||
if (mode == KILLALL)
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
fputs("KILL", stdout);
|
||||
TerminateProcess(process, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
|
||||
fputs("OPEN", stdout);
|
||||
}
|
||||
break;
|
||||
|
||||
case WINDIVERT_EVENT_REFLECT_CLOSE:
|
||||
// Close handle:
|
||||
if (mode != WATCH)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
process = lookup_process(addr.Reflect.ProcessId);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED);
|
||||
fputs("CLOSE", stdout);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" time=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%.3fs", (double)(addr.Reflect.Timestamp - (INT64)start_count) /
|
||||
(double)freq);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" pid=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%u", addr.Reflect.ProcessId);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" exe=", stdout);
|
||||
path_len = 0;
|
||||
if (process != NULL)
|
||||
{
|
||||
path_len = GetProcessImageFileName(process, path, sizeof(path));
|
||||
}
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%s", (path_len != 0? path: "???"));
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" layer=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
switch (addr.Reflect.Layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
fputs("NETWORK", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
fputs("NETWORK_FORWARD", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
fputs("FLOW", stdout);
|
||||
break;
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
fputs("REFLECT", stdout);
|
||||
break;
|
||||
default:
|
||||
fputs("???", stdout);
|
||||
break;
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" flags=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
if (addr.Reflect.Flags == 0)
|
||||
{
|
||||
fputs("0", stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
or = FALSE;
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_SNIFF) != 0)
|
||||
{
|
||||
fputs("SNIFF", stdout);
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_DROP) != 0)
|
||||
{
|
||||
printf("%sDROP", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_RECV_ONLY) != 0)
|
||||
{
|
||||
printf("%sRECV_ONLY", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_SEND_ONLY) != 0)
|
||||
{
|
||||
printf("%sSEND_ONLY", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_DEBUG) != 0)
|
||||
{
|
||||
printf("%sDEBUG", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
if ((addr.Reflect.Flags & WINDIVERT_FLAG_NO_INSTALL) != 0)
|
||||
{
|
||||
printf("%sNO_INSTALL", (or? "|": ""));
|
||||
or = TRUE;
|
||||
}
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" priority=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("%d", addr.Reflect.Priority);
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
fputs(" filter=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, &object, NULL);
|
||||
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
|
||||
filter_str, sizeof(filter_str)))
|
||||
{
|
||||
printf("\"%s\" \"%s\"", filter_str, (char *)object); // XXX
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
putchar('\n');
|
||||
|
||||
if (addr.Event == WINDIVERT_EVENT_REFLECT_CLOSE)
|
||||
{
|
||||
remove_process(addr.Reflect.ProcessId);
|
||||
}
|
||||
if (mode != WATCH && addr.Final)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+49
-24
@@ -69,6 +69,17 @@ extern "C" {
|
||||
/* WINDIVERT API */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* WinDivert layers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
|
||||
WINDIVERT_LAYER_REFLECT = 3, /* Reflect layer. */
|
||||
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
|
||||
|
||||
/*
|
||||
* WinDivert NETWORK and NETWORK_FORWARD layer data.
|
||||
*/
|
||||
@@ -91,6 +102,18 @@ typedef struct
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_FLOW_DATA, *PWINDIVERT_FLOW_DATA;
|
||||
|
||||
/*
|
||||
* WinDivert REFLECTION layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Handle open time. */
|
||||
UINT32 ProcessId; /* Handle process ID. */
|
||||
WINDIVERT_LAYER Layer; /* Handle layer. */
|
||||
UINT64 Flags; /* Handle flags. */
|
||||
INT16 Priority; /* Handle priority. */
|
||||
} WINDIVERT_REFLECT_DATA, *PWINDIVERT_REFLECT_DATA;
|
||||
|
||||
/*
|
||||
* WinDivert address.
|
||||
*/
|
||||
@@ -106,24 +129,16 @@ typedef struct
|
||||
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;
|
||||
UINT32 Final:1; /* Packet is final event? */
|
||||
UINT32 Reserved:8;
|
||||
union
|
||||
{
|
||||
WINDIVERT_NETWORK_DATA Network; /* Network layer data. */
|
||||
WINDIVERT_FLOW_DATA Flow; /* Flow layer data. */
|
||||
WINDIVERT_REFLECT_DATA Reflect; /* Reflect layer data. */
|
||||
};
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
|
||||
/*
|
||||
* WinDivert layers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
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;
|
||||
|
||||
/*
|
||||
* WinDivert events.
|
||||
*/
|
||||
@@ -133,24 +148,23 @@ typedef enum
|
||||
WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
|
||||
/* Flow established. */
|
||||
WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
|
||||
WINDIVERT_EVENT_REFLECT_ESTABLISHED = 3,
|
||||
/* Previously open WinDivert handle. */
|
||||
WINDIVERT_EVENT_REFLECT_OPEN = 4, /* Open new WinDivert handle. */
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE = 5, /* Close existing WinDivert handle. */
|
||||
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAG_SNIFF 1
|
||||
#define WINDIVERT_FLAG_DROP 2
|
||||
#define WINDIVERT_FLAG_RECV_ONLY 4
|
||||
#define WINDIVERT_FLAG_SNIFF 0x01
|
||||
#define WINDIVERT_FLAG_DROP 0x02
|
||||
#define WINDIVERT_FLAG_RECV_ONLY 0x04
|
||||
#define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY
|
||||
#define WINDIVERT_FLAG_SEND_ONLY 8
|
||||
#define WINDIVERT_FLAG_SEND_ONLY 0x08
|
||||
#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)
|
||||
#define WINDIVERT_FLAG_DEBUG 0x10
|
||||
#define WINDIVERT_FLAG_NO_INSTALL 0x20
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
@@ -430,11 +444,13 @@ extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums(
|
||||
__in UINT64 flags);
|
||||
|
||||
/*
|
||||
* Check the given filter string.
|
||||
* Compile the given filter string.
|
||||
*/
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperCheckFilter(
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperCompileFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out_opt char *object,
|
||||
__in UINT objLen,
|
||||
__out_opt const char **errorStr,
|
||||
__out_opt UINT *errorPos);
|
||||
|
||||
@@ -447,6 +463,15 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
|
||||
__in UINT packetLen,
|
||||
__in PWINDIVERT_ADDRESS pAddr);
|
||||
|
||||
/*
|
||||
* Format the given filter string.
|
||||
*/
|
||||
extern BOOL WinDivertHelperFormatFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+27
-16
@@ -128,8 +128,9 @@
|
||||
#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_MAX \
|
||||
WINDIVERT_FILTER_FIELD_PROTOCOL
|
||||
WINDIVERT_FILTER_FIELD_LAYER
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
@@ -139,7 +140,7 @@
|
||||
#define WINDIVERT_FILTER_TEST_GEQ 5
|
||||
#define WINDIVERT_FILTER_TEST_MAX WINDIVERT_FILTER_TEST_GEQ
|
||||
|
||||
#define WINDIVERT_FILTER_MAXLEN 128
|
||||
#define WINDIVERT_FILTER_MAXLEN (0xFF-2)
|
||||
|
||||
#define WINDIVERT_FILTER_RESULT_ACCEPT (WINDIVERT_FILTER_MAXLEN+1)
|
||||
#define WINDIVERT_FILTER_RESULT_REJECT (WINDIVERT_FILTER_MAXLEN+2)
|
||||
@@ -148,13 +149,15 @@
|
||||
* WinDivert layers.
|
||||
*/
|
||||
#define WINDIVERT_LAYER_DEFAULT WINDIVERT_LAYER_NETWORK
|
||||
#define WINDIVERT_LAYER_MAX WINDIVERT_LAYER_REFLECT
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAGS_ALL \
|
||||
(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_DEBUG)
|
||||
WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_DEBUG | \
|
||||
WINDIVERT_FLAG_NO_INSTALL)
|
||||
#define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \
|
||||
(((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2)))
|
||||
#define WINDIVERT_FLAGS_VALID(flags) \
|
||||
@@ -164,14 +167,24 @@
|
||||
WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_RECV_ONLY, \
|
||||
WINDIVERT_FLAG_SEND_ONLY))
|
||||
|
||||
/*
|
||||
* WinDivert filter flags.
|
||||
*/
|
||||
#define WINDIVERT_FILTER_FLAG_INBOUND 0x0000000000000001ull
|
||||
#define WINDIVERT_FILTER_FLAG_OUTBOUND 0x0000000000000002ull
|
||||
#define WINDIVERT_FILTER_FLAG_IP 0x0000000000000004ull
|
||||
#define WINDIVERT_FILTER_FLAG_IPV6 0x0000000000000008ull
|
||||
|
||||
#define WINDIVERT_FILTER_FLAGS_ALL \
|
||||
(WINDIVERT_FILTER_FLAG_INBOUND | WINDIVERT_FILTER_FLAG_OUTBOUND | \
|
||||
WINDIVERT_FILTER_FLAG_IP | WINDIVERT_FILTER_FLAG_IPV6)
|
||||
|
||||
/*
|
||||
* WinDivert priorities.
|
||||
*/
|
||||
#define WINDIVERT_PRIORITY(priority16) \
|
||||
((UINT32)((INT32)(priority16) + 0x7FFF + 1))
|
||||
#define WINDIVERT_PRIORITY_DEFAULT WINDIVERT_PRIORITY(0)
|
||||
#define WINDIVERT_PRIORITY_MAX WINDIVERT_PRIORITY(1000)
|
||||
#define WINDIVERT_PRIORITY_MIN WINDIVERT_PRIORITY(-1000)
|
||||
#define WINDIVERT_PRIORITY_DEFAULT 0
|
||||
#define WINDIVERT_PRIORITY_MAX 30000
|
||||
#define WINDIVERT_PRIORITY_MIN -WINDIVERT_PRIORITY_MAX
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
@@ -190,27 +203,25 @@
|
||||
* WinDivert message definitions.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct windivert_ioctl_s
|
||||
typedef struct
|
||||
{
|
||||
UINT16 magic; // WINDIVERT_IOCTL_MAGIC
|
||||
UINT8 version; // WINDIVERT_IOCTL_VERSION
|
||||
UINT8 arg8; // 8-bit argument
|
||||
UINT64 arg; // 64-bit argument
|
||||
};
|
||||
typedef struct windivert_ioctl_s *windivert_ioctl_t;
|
||||
} WINDIVERT_IOCTL, *PWINDIVERT_IOCTL;
|
||||
|
||||
/*
|
||||
* WinDivert IOCTL structures.
|
||||
*/
|
||||
struct windivert_ioctl_filter_s
|
||||
typedef struct
|
||||
{
|
||||
UINT8 field; // WINDIVERT_FILTER_FIELD_*
|
||||
UINT8 test; // WINDIVERT_FILTER_TEST_*
|
||||
UINT16 success; // Success continuation.
|
||||
UINT16 failure; // Fail continuation.
|
||||
UINT8 success; // Success continuation.
|
||||
UINT8 failure; // Fail continuation.
|
||||
UINT32 arg[4]; // Argument.
|
||||
};
|
||||
typedef struct windivert_ioctl_filter_s *windivert_ioctl_filter_t;
|
||||
} WINDIVERT_FILTER, *PWINDIVERT_FILTER;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
|
||||
+5
-1
@@ -59,7 +59,7 @@ do
|
||||
fi
|
||||
echo "BUILD MINGW-$CPU"
|
||||
CC="$ENV-gcc"
|
||||
COPTS="-shared -Wall -Wno-pointer-to-int-cast -O2 -Iinclude/
|
||||
COPTS="-shared -Wall -Wno-pointer-to-int-cast -Os -Iinclude/
|
||||
-Wl,--enable-stdcall-fixup -Wl,--entry=${MANGLE}WinDivertDllEntry"
|
||||
CLIBS="-lgcc -lkernel32 -ladvapi32"
|
||||
STRIP="$ENV-strip"
|
||||
@@ -101,6 +101,10 @@ do
|
||||
$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/windivertctl.exe..."
|
||||
$CC -s -O2 -Iinclude/ examples/windivertctl/windivertctl.c \
|
||||
-o "install/MINGW/$CPU/windivertctl.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
|
||||
|
||||
+1
-1
@@ -19,6 +19,6 @@ NTTARGETFILES=
|
||||
KMDF_VERSION_MAJOR=1
|
||||
C_DEFINES=$(C_DEFINES) -DBINARY_COMPATIBLE=0 -DNT -DUNICODE -D_UNICODE \
|
||||
-DNDIS60 -DNDIS_SUPPORT_NDIS60
|
||||
INCLUDES=$(DDK_INC_PATH);..\include
|
||||
INCLUDES=$(DDK_INC_PATH);..\include;..\dll
|
||||
SOURCES=windivert.rc windivert.c
|
||||
|
||||
|
||||
+711
-395
File diff suppressed because it is too large
Load Diff
+14
-6
@@ -241,6 +241,9 @@ static struct test tests[] =
|
||||
"false): false): false): false)", &pkt_http_request, TRUE},
|
||||
{"(outbound? (ip? (tcp.DstPort == 80? (tcp.PayloadLength == 0? true: "
|
||||
"false): false): false): false)", &pkt_http_request, FALSE},
|
||||
{"(ipv6? tcp and tcp.DstPort = 1234 and (tcp.SrcPort = 999? !tcp.UrgPtr: "
|
||||
"tcp.Syn) or udp: ip and tcp.DstPort == 80)",
|
||||
&pkt_http_request, TRUE},
|
||||
{"udp", &pkt_dns_request, TRUE},
|
||||
{"udp && udp.SrcPort > 1 && ipv6", &pkt_dns_request, FALSE},
|
||||
{"udp.DstPort == 53", &pkt_dns_request, TRUE},
|
||||
@@ -388,21 +391,26 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
|
||||
OVERLAPPED overlapped;
|
||||
const char *err_str;
|
||||
UINT err_pos;
|
||||
PWINDIVERT_IPHDR iphdr = NULL;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE, handle0 = INVALID_HANDLE_VALUE,
|
||||
event = NULL;
|
||||
|
||||
// (0) Verify the test data:
|
||||
if (!WinDivertHelperCheckFilter(filter, WINDIVERT_LAYER_NETWORK, &err_str,
|
||||
&err_pos))
|
||||
if (!WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_NETWORK,
|
||||
NULL, 0, &err_str, &err_pos))
|
||||
{
|
||||
fprintf(stderr, "error: filter string \"%s\" is invalid with error "
|
||||
"\"%s\" (position=%u)\n", filter, err_str, err_pos);
|
||||
goto failed;
|
||||
}
|
||||
WinDivertHelperParsePacket((PVOID)packet, packet_len, &iphdr, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.Direction = WINDIVERT_DIRECTION_OUTBOUND;
|
||||
if (WinDivertHelperEvalFilter(filter, WINDIVERT_LAYER_NETWORK,
|
||||
(PVOID)packet, packet_len, &addr) != match)
|
||||
addr.Outbound = TRUE;
|
||||
addr.Layer = WINDIVERT_LAYER_NETWORK;
|
||||
addr.IPv6 = (iphdr == NULL);
|
||||
if (WinDivertHelperEvalFilter(filter, (PVOID)packet, packet_len, &addr)
|
||||
!= match)
|
||||
{
|
||||
fprintf(stderr, "error: filter \"%s\" does not match the given "
|
||||
"packet\n", filter);
|
||||
@@ -481,7 +489,7 @@ read_failed:
|
||||
}
|
||||
buf_len = (UINT)iolen;
|
||||
}
|
||||
if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
if (addr.Outbound)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(buf, buf_len, NULL, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user