├── .github └── FUNDING.yml ├── README ├── USBPcapCMD ├── SOURCES ├── USBPcapCMD.manifest ├── USBPcapCMD.rc ├── cmd.c ├── descriptors.c ├── descriptors.h ├── enum.c ├── enum.h ├── filters.c ├── filters.h ├── getopt.c ├── getopt.h ├── iocontrol.c ├── iocontrol.h ├── roothubs.c ├── roothubs.h ├── thread.c ├── thread.h └── version.h ├── USBPcapDriver ├── SOURCES ├── USBPcap.inx ├── USBPcap.rc ├── USBPcapBuffer.c ├── USBPcapBuffer.h ├── USBPcapDeviceControl.c ├── USBPcapFilterManager.c ├── USBPcapGenReq.c ├── USBPcapHelperFunctions.c ├── USBPcapHelperFunctions.h ├── USBPcapMain.c ├── USBPcapMain.h ├── USBPcapPnP.c ├── USBPcapPower.c ├── USBPcapQueue.c ├── USBPcapQueue.h ├── USBPcapRootHubControl.c ├── USBPcapRootHubControl.h ├── USBPcapTables.c ├── USBPcapTables.h ├── USBPcapURB.c ├── USBPcapURB.h ├── include │ └── USBPcap.h └── makefile.inc ├── appveyor_build.bat ├── build_release.bat ├── certificates ├── Certum Trusted Network CA.crt ├── Readme.txt ├── USBPcapTestCert.cer ├── USBPcapTestCert.pfx ├── USBPcapTestCert.pvk └── VeriSign Class 3 Public Primary Certification Authority - G5.cer ├── config.bat ├── dirs ├── driver_attestation_signing.bat ├── driver_build.bat ├── driver_build_win7_64bit.bat ├── driver_build_win8.bat ├── nsis ├── SysRestore.dll ├── USBPcap.nsi ├── bsd-2clause.txt ├── build_installer.bat └── gpl-2.0.txt └── wix ├── USBPcap.wxs ├── build.bat └── gpl-2.0.rtf /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [desowin] 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | USBPcap - USB Packet capture for Windows 2 | 3 | End-user installer is available at: http://desowin.org/usbpcap 4 | Following informations are intended for developers and power users only. 5 | 6 | Directory overview: 7 | USBPcapCMD - sample user space application 8 | USBPcapDriver - filter driver used to capture data 9 | 10 | Build instructions: 11 | Download and install Windows Driver Kit 7.1.0 from Microsoft 12 | http://www.microsoft.com/en-us/download/details.aspx?id=11800 13 | 14 | Adjust driver_build_win7_64bit.bat (first line of that file): 15 | * To change to checked build: replace 'fre' with 'chk' 16 | * To build for x86: replace 'x64' with 'x86' 17 | * To build for Windows XP: replace 'WIN7' with 'WXP' 18 | 19 | Windows 8 Build instructions: 20 | In order to compile for Windows 8, you need to have Visual Studio 2013 21 | Community and install Windows Driver Kit 8.1 Update. 22 | To create solution file use the following command from Visual Studio 2013 23 | Command Prompt (while being chdired into usbpcap sources directory): 24 | > Nmake2MsBuild dirs 25 | 26 | This will create solution dirs.sln. You can build the driver from the 27 | Visual Studio 2013 Command Prompt: 28 | > MSBuild dirs.sln /p:Configuration="Win8 Debug" 29 | 30 | Installation: 31 | TESTSIGNING must be enabled in order to install this driver on 64 bit 32 | Windows. To do so, issue following command (as administrator): 33 | Bcdedit.exe -set TESTSIGNING ON 34 | and reboot. 35 | 36 | Right click on the USBPcap.inf file and select Install. 37 | 38 | After installing, reboot. 39 | 40 | Usage: 41 | Currently there is no capture engine dll. 42 | You can use the USBPcapCMD.exe to select the filter instance (there is one 43 | instance per root hub) and specify the output pcap file name. 44 | 45 | Licensing: 46 | USBPcapDriver is licensed under GPLv2 license. 47 | USBPcapCMD is licensed under BSD 2-Clause license. 48 | 49 | -------------------------------------------------------------------------------- /USBPcapCMD/SOURCES: -------------------------------------------------------------------------------- 1 | TARGETNAME = USBPcapCMD 2 | TARGETTYPE = PROGRAM 3 | 4 | _NT_TARGET_VERSION = $(_NT_TARGET_VERSION_WINXP) 5 | 6 | USE_MSVCRT = 1 7 | 8 | UMTYPE = windows 9 | UMBASE = 0x01000000 10 | 11 | SXS_APPLICATION_MANIFEST=USBPcapCMD.manifest 12 | SXS_ASSEMBLY_VERSION=1.0 13 | SXS_ASSEMBLY_NAME=USBPcapCMD 14 | SXS_ASSEMBLY_LANGUAGE=0000 15 | 16 | INCLUDES = $(DDK_INC_PATH);..\USBPcapDriver\include 17 | 18 | TARGETLIBS = $(SDK_LIB_PATH)\hid.lib \ 19 | $(SDK_LIB_PATH)\setupapi.lib \ 20 | $(SDK_LIB_PATH)\comdlg32.lib \ 21 | $(DDK_LIB_PATH)\advapi32.lib \ 22 | $(DDK_LIB_PATH)\Cfgmgr32.lib \ 23 | $(DDK_LIB_PATH)\Shell32.lib \ 24 | $(DDK_LIB_PATH)\Shlwapi.lib 25 | 26 | SOURCES = USBPcapCMD.rc \ 27 | cmd.c \ 28 | descriptors.c \ 29 | enum.c \ 30 | filters.c \ 31 | getopt.c \ 32 | iocontrol.c \ 33 | roothubs.c \ 34 | thread.c 35 | -------------------------------------------------------------------------------- /USBPcapCMD/USBPcapCMD.manifest: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | USBPcapCMD 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /USBPcapCMD/USBPcapCMD.rc: -------------------------------------------------------------------------------- 1 | #include "Windows.h" 2 | #include "version.h" 3 | 4 | 1 VERSIONINFO 5 | FILEVERSION USBPCAPCMD_VERSION_MAJOR,USBPCAPCMD_VERSION_MINOR,USBPCAPCMD_VERSION_REVISION,USBPCAPCMD_VERSION_BUILD 6 | PRODUCTVERSION USBPCAPCMD_VERSION_MAJOR,USBPCAPCMD_VERSION_MINOR,USBPCAPCMD_VERSION_REVISION,USBPCAPCMD_VERSION_BUILD 7 | FILEFLAGSMASK 0 8 | FILEFLAGS (VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE|VS_FF_DEBUG) 9 | FILEOS VOS__WINDOWS32 10 | FILETYPE VFT_APP 11 | FILESUBTYPE 0 12 | BEGIN 13 | BLOCK "StringFileInfo" 14 | BEGIN 15 | BLOCK "040904E4" 16 | BEGIN 17 | VALUE "CompanyName", "USBPcap" 18 | VALUE "FileDescription", "USBPcap commandline interface" 19 | VALUE "FileVersion", USBPCAPCMD_VERSION_STR 20 | VALUE "InternalName", "USBPcap" 21 | VALUE "LegalCopyright", "(c) 2013-2020 Tomasz Mon" 22 | VALUE "OriginalFilename", "USBPcapCMD.exe" 23 | VALUE "ProductName", "USBPcap" 24 | VALUE "ProductVersion", USBPCAPCMD_VERSION_STR 25 | END 26 | END 27 | 28 | BLOCK "VarFileInfo" 29 | BEGIN 30 | VALUE "Translation", 0x409, 1252 31 | END 32 | END 33 | -------------------------------------------------------------------------------- /USBPcapCMD/descriptors.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/USBPcapCMD/descriptors.c -------------------------------------------------------------------------------- /USBPcapCMD/descriptors.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/USBPcapCMD/descriptors.h -------------------------------------------------------------------------------- /USBPcapCMD/enum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_CMD_ENUM_H 8 | #define USBPCAP_CMD_ENUM_H 9 | 10 | #include 11 | #include 12 | 13 | #define EXTCAP_ARGNUM_MULTICHECK 99 14 | 15 | typedef void (*EnumConnectedPortCallback)(HANDLE hub, ULONG port, USHORT deviceAddress, PUSB_DEVICE_DESCRIPTOR desc, void *ctx); 16 | 17 | void enumerate_print_usbpcap_interactive(const char *filter); 18 | void enumerate_print_extcap_config(const char *filter); 19 | void enumerate_all_connected_devices(const char *filter, EnumConnectedPortCallback cb, void *ctx); 20 | 21 | #endif /* USBPCAP_CMD_ENUM_H */ 22 | -------------------------------------------------------------------------------- /USBPcapCMD/filters.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "filters.h" 12 | 13 | struct filters **usbpcapFilters = NULL; 14 | 15 | struct list_entry; 16 | 17 | struct list 18 | { 19 | struct list_entry *head; 20 | struct list_entry *tail; 21 | int count; 22 | }; 23 | 24 | struct list_entry 25 | { 26 | char *device; 27 | struct list_entry *next; 28 | }; 29 | 30 | #define BUFFER_SIZE 0x1000 31 | 32 | /* Following typedefs and defines are for UNDOCUMENTED functions */ 33 | #define NTSTATUS ULONG 34 | #define STATUS_SUCCESS 0x00000000 35 | 36 | typedef struct _LSA_UNICODE_STRING 37 | { 38 | USHORT Length; 39 | USHORT MaximumLength; 40 | PWSTR Buffer; 41 | } UNICODE_STRING, *PUNICODE_STRING; 42 | 43 | typedef struct _OBJDIR_INFORMATION 44 | { 45 | UNICODE_STRING ObjectName; 46 | UNICODE_STRING ObjectTypeName; 47 | BYTE Data[1]; 48 | } OBJDIR_INFORMATION, *POBJDIR_INFORMATION; 49 | 50 | typedef struct _OBJECT_ATTRIBUTES 51 | { 52 | ULONG Length; 53 | HANDLE RootDirectory; 54 | UNICODE_STRING *ObjectName; 55 | ULONG Attributes; 56 | PVOID SecurityDescriptor; 57 | PVOID SecurityQualityOfService; 58 | } OBJECT_ATTRIBUTES; 59 | 60 | typedef NTSTATUS (WINAPI* NTQUERYDIRECTORYOBJECT)(HANDLE, 61 | OBJDIR_INFORMATION*, 62 | DWORD, 63 | DWORD, 64 | DWORD, 65 | DWORD*, 66 | DWORD*); 67 | 68 | typedef NTSTATUS (WINAPI* NTOPENDIRECTORYOBJECT)(HANDLE*, 69 | DWORD, 70 | OBJECT_ATTRIBUTES*); 71 | 72 | #define InitializeObjectAttributes(p, n, a, r, s) { \ 73 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 74 | (p)->RootDirectory = r; \ 75 | (p)->Attributes = a; \ 76 | (p)->ObjectName = n; \ 77 | (p)->SecurityDescriptor = s; \ 78 | (p)->SecurityQualityOfService = NULL; \ 79 | } 80 | 81 | typedef NTSTATUS (WINAPI* NTCLOSE)(HANDLE); 82 | 83 | static HMODULE ntdll_handle; 84 | NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject; 85 | NTOPENDIRECTORYOBJECT NtOpenDirectoryObject; 86 | NTCLOSE NtClose; 87 | 88 | #define DIRECTORY_QUERY 0x0001 89 | 90 | static void __cdecl unload_undocumented(void) 91 | { 92 | FreeLibrary(ntdll_handle); 93 | } 94 | 95 | /* Initialize handles to undocumented functions 96 | * 97 | * Returns TRUE on success, FALSE otherwise 98 | */ 99 | static BOOL init_undocumented() 100 | { 101 | ntdll_handle = LoadLibrary(_T("ntdll.dll")); 102 | 103 | if (ntdll_handle == NULL) 104 | { 105 | return FALSE; 106 | } 107 | 108 | atexit(unload_undocumented); 109 | 110 | NtQueryDirectoryObject = 111 | (NTQUERYDIRECTORYOBJECT) GetProcAddress(ntdll_handle, 112 | "NtQueryDirectoryObject"); 113 | 114 | if (NtQueryDirectoryObject == NULL) 115 | { 116 | return FALSE; 117 | } 118 | 119 | NtOpenDirectoryObject = 120 | (NTOPENDIRECTORYOBJECT) GetProcAddress(ntdll_handle, 121 | "NtOpenDirectoryObject"); 122 | if (NtOpenDirectoryObject == NULL) 123 | { 124 | return FALSE; 125 | } 126 | 127 | NtClose = (NTCLOSE) GetProcAddress(ntdll_handle, "NtClose"); 128 | if (NtClose == NULL) 129 | { 130 | return FALSE; 131 | } 132 | 133 | return TRUE; 134 | } 135 | 136 | /* Searches \Device for USBPcap filters. 137 | * init_undocumented() must be called prior this function. 138 | * 139 | * Returns TRUE on success, FALSE otherwise 140 | */ 141 | static BOOL find_usbpcap_filters(struct list *list, 142 | void (*callback)(struct list *list, 143 | PUNICODE_STRING str)) 144 | { 145 | UNICODE_STRING str; 146 | OBJECT_ATTRIBUTES attr; 147 | DWORD index; 148 | DWORD written; 149 | HANDLE handle; 150 | NTSTATUS status; 151 | POBJDIR_INFORMATION info; 152 | PWSTR path = L"\\Device"; 153 | 154 | str.Length = wcslen(path)*2; 155 | str.MaximumLength = wcslen(path)*2+2; 156 | str.Buffer = path; 157 | 158 | InitializeObjectAttributes(&attr, 159 | &str, 160 | 0, /* No Attributes */ 161 | NULL, /* No Root Directory */ 162 | NULL); /* No Security Descriptor */ 163 | 164 | index = 0; 165 | written = 0; 166 | 167 | info = (POBJDIR_INFORMATION) HeapAlloc(GetProcessHeap(), 168 | 0, 169 | BUFFER_SIZE); 170 | 171 | if (info == NULL) 172 | { 173 | fprintf(stderr, "HeapAlloc() failed\n"); 174 | return FALSE; 175 | } 176 | 177 | status = NtOpenDirectoryObject(&handle, 178 | DIRECTORY_QUERY, 179 | &attr); 180 | if (status != 0) 181 | { 182 | fprintf(stderr, "NtOpenDirectoryObject() failed\n"); 183 | HeapFree(GetProcessHeap(), 0, info); 184 | return FALSE; 185 | } 186 | 187 | status = NtQueryDirectoryObject(handle, 188 | info, 189 | BUFFER_SIZE, 190 | TRUE, /* Get Next Index */ 191 | TRUE, /* Ignore Input Index */ 192 | &index, 193 | &written); 194 | 195 | if (status != 0) 196 | { 197 | fprintf(stderr, "NtQueryDirectoryObject() failed\n"); 198 | HeapFree(GetProcessHeap(), 0, info); 199 | return FALSE; 200 | } 201 | 202 | while (NtQueryDirectoryObject(handle, info, BUFFER_SIZE, 203 | TRUE, FALSE, &index, &written) == 0) 204 | { 205 | const wchar_t *prefix = L"USBPcap"; 206 | size_t prefix_chars = 7; 207 | 208 | if (wcsncmp(prefix, info->ObjectName.Buffer, prefix_chars) == 0) 209 | { 210 | callback(list, &info->ObjectName); 211 | } 212 | } 213 | 214 | NtClose(handle); 215 | HeapFree(GetProcessHeap(), 0, info); 216 | 217 | return TRUE; 218 | } 219 | 220 | static void list_insert(struct list *list, struct list_entry *entry) 221 | { 222 | if (list->head == NULL) 223 | { 224 | list->head = entry; 225 | list->tail = entry; 226 | list->count = 1; 227 | } 228 | else 229 | { 230 | list->tail->next = entry; 231 | list->tail = entry; 232 | list->count++; 233 | } 234 | } 235 | 236 | static void list_free(struct list *list, BOOL free_data) 237 | { 238 | struct list_entry *entry; 239 | struct list_entry *next; 240 | 241 | entry = list->head; 242 | while (entry != NULL) 243 | { 244 | next = entry->next; 245 | if (free_data == TRUE) 246 | { 247 | free(entry->device); 248 | } 249 | free(entry); 250 | entry = next; 251 | } 252 | 253 | list->head = NULL; 254 | list->tail = NULL; 255 | list->count = 0; 256 | } 257 | 258 | static void add_to_list(struct list *list, 259 | PUNICODE_STRING str) 260 | { 261 | char *device; 262 | const char *prefix = "\\\\.\\"; 263 | int prefix_len = 4; 264 | int i; 265 | int len; 266 | struct list_entry *entry; 267 | 268 | len = str->Length / sizeof(WCHAR); 269 | device = malloc(len + 1 + prefix_len); 270 | 271 | for (i = 0; i < prefix_len; i++) 272 | { 273 | device[i] = prefix[i]; 274 | } 275 | 276 | for (i = 0; i < len; i++) 277 | { 278 | device[i+prefix_len] = (char)str->Buffer[i]; 279 | } 280 | device[prefix_len+len] = '\0'; 281 | 282 | entry = malloc(sizeof(struct list_entry)); 283 | entry->device = device; 284 | entry->next = NULL; 285 | 286 | list_insert(list, entry); 287 | } 288 | 289 | void filters_initialize() 290 | { 291 | struct list list; 292 | struct list_entry *entry; 293 | int i; 294 | 295 | list.head = NULL; 296 | list.tail = NULL; 297 | list.count = 0; 298 | 299 | init_undocumented(); 300 | find_usbpcap_filters(&list, add_to_list); 301 | 302 | usbpcapFilters = (struct filters**)malloc(sizeof(struct filters*) * (list.count + 1)); 303 | entry = list.head; 304 | for (i = 0; i < list.count && entry != NULL; i++) 305 | { 306 | usbpcapFilters[i] = (struct filters*)malloc(sizeof(struct filters)); 307 | usbpcapFilters[i]->device = entry->device; 308 | 309 | entry = entry->next; 310 | } 311 | usbpcapFilters[list.count] = NULL; 312 | 313 | list_free(&list, FALSE); 314 | } 315 | 316 | void filters_free() 317 | { 318 | int i = 0; 319 | 320 | if (usbpcapFilters == NULL) 321 | { 322 | return; 323 | } 324 | 325 | while (usbpcapFilters[i] != NULL) 326 | { 327 | free(usbpcapFilters[i]->device); 328 | free(usbpcapFilters[i]); 329 | i++; 330 | } 331 | free(usbpcapFilters); 332 | } 333 | 334 | BOOL is_usbpcap_upper_filter_installed() 335 | { 336 | LONG regVal; 337 | HKEY hkey; 338 | LONG length; 339 | DWORD type; 340 | LPTSTR multisz; 341 | 342 | PTSTR lookup = _T("\0USBPcap\0"); 343 | int i, j; 344 | 345 | regVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 346 | _T("System\\CurrentControlSet\\Control\\Class\\{36FC9E60-C465-11CF-8056-444553540000}"), 347 | 0, KEY_QUERY_VALUE, &hkey); 348 | 349 | if (regVal != ERROR_SUCCESS) 350 | { 351 | fprintf(stderr, "Failed to open USB Class registry key! Code %d\n", regVal); 352 | return FALSE; 353 | } 354 | 355 | regVal = RegQueryValueEx(hkey, _T("UpperFilters"), 356 | NULL, &type, NULL, &length); 357 | 358 | if (regVal != ERROR_SUCCESS) 359 | { 360 | fprintf(stderr, "Failed to query UpperFilters value size! Code %d\n", regVal); 361 | RegCloseKey(hkey); 362 | return FALSE; 363 | } 364 | 365 | if (type != REG_MULTI_SZ) 366 | { 367 | fprintf(stderr, "Invalid UpperFilters type (%d)!\n", type); 368 | RegCloseKey(hkey); 369 | return FALSE; 370 | } 371 | 372 | if (length <= 0) 373 | { 374 | RegCloseKey(hkey); 375 | return FALSE; 376 | } 377 | 378 | multisz = (LPTSTR)malloc(length); 379 | regVal = RegQueryValueEx(hkey, _T("UpperFilters"), 380 | NULL, NULL, multisz, &length); 381 | 382 | if (regVal != ERROR_SUCCESS) 383 | { 384 | fprintf(stderr, "Failed to read UpperFilters value! Code %d\n", regVal); 385 | free(multisz); 386 | RegCloseKey(hkey); 387 | return FALSE; 388 | } 389 | 390 | RegCloseKey(hkey); 391 | 392 | /* i walks over multisz, j walks over lookup. 393 | * j starts from 1 as the multisz does not start with '\0'. 394 | */ 395 | for (i = 0, j = 1; i < length; i++) 396 | { 397 | if (multisz[i] == lookup[j]) 398 | { 399 | j++; 400 | if (j == 9) /* whole lookup string */ 401 | { 402 | free(multisz); 403 | return TRUE; 404 | } 405 | } 406 | else 407 | { 408 | /* when first character does not match start searching from 409 | * beginning (including '\0' as it has to be new substring) 410 | */ 411 | j = 0; 412 | } 413 | } 414 | 415 | free(multisz); 416 | return FALSE; 417 | } 418 | -------------------------------------------------------------------------------- /USBPcapCMD/filters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_CMD_FILTERS_H 8 | #define USBPCAP_CMD_FILTERS_H 9 | 10 | struct filters 11 | { 12 | char *device; /* \\.\USBPcapX */ 13 | }; 14 | 15 | /* NULL-terminated array of pointers to struct filters */ 16 | extern struct filters **usbpcapFilters; 17 | 18 | void filters_initialize(); 19 | void filters_free(); 20 | 21 | BOOL is_usbpcap_upper_filter_installed(); 22 | 23 | #endif /* USBPCAP_CMD_FILTERS_H */ 24 | -------------------------------------------------------------------------------- /USBPcapCMD/getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef __GETOPT_H__ 2 | /** 3 | * DISCLAIMER 4 | * This file has no copyright assigned and is placed in the Public Domain. 5 | * This file is a part of the w64 mingw-runtime package. 6 | * 7 | * The w64 mingw-runtime package and its code is distributed in the hope that it 8 | * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR 9 | * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to 10 | * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | */ 12 | 13 | #define __GETOPT_H__ 14 | 15 | /* All the headers include this file. */ 16 | #include 17 | 18 | #if defined( WINGETOPT_SHARED_LIB ) 19 | # if defined( BUILDING_WINGETOPT_DLL ) 20 | # define WINGETOPT_API __declspec(dllexport) 21 | # else 22 | # define WINGETOPT_API __declspec(dllimport) 23 | # endif 24 | #else 25 | # define WINGETOPT_API 26 | #endif 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | WINGETOPT_API extern int optind; /* index of first non-option in argv */ 33 | WINGETOPT_API extern int optopt; /* single option character, as parsed */ 34 | WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */ 35 | /* (user may set to zero, to suppress) */ 36 | 37 | WINGETOPT_API extern char *optarg; /* pointer to argument of current option */ 38 | 39 | extern int getopt(int nargc, char * const *nargv, const char *options); 40 | 41 | #ifdef _BSD_SOURCE 42 | /* 43 | * BSD adds the non-standard `optreset' feature, for reinitialisation 44 | * of `getopt' parsing. We support this feature, for applications which 45 | * proclaim their BSD heritage, before including this header; however, 46 | * to maintain portability, developers are advised to avoid it. 47 | */ 48 | # define optreset __mingw_optreset 49 | extern int optreset; 50 | #endif 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | /* 55 | * POSIX requires the `getopt' API to be specified in `unistd.h'; 56 | * thus, `unistd.h' includes this header. However, we do not want 57 | * to expose the `getopt_long' or `getopt_long_only' APIs, when 58 | * included in this manner. Thus, close the standard __GETOPT_H__ 59 | * declarations block, and open an additional __GETOPT_LONG_H__ 60 | * specific block, only when *not* __UNISTD_H_SOURCED__, in which 61 | * to declare the extended API. 62 | */ 63 | #endif /* !defined(__GETOPT_H__) */ 64 | 65 | #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) 66 | #define __GETOPT_LONG_H__ 67 | 68 | #ifdef __cplusplus 69 | extern "C" { 70 | #endif 71 | 72 | struct option /* specification for a long form option... */ 73 | { 74 | const char *name; /* option name, without leading hyphens */ 75 | int has_arg; /* does it take an argument? */ 76 | int *flag; /* where to save its status, or NULL */ 77 | int val; /* its associated status value */ 78 | }; 79 | 80 | enum /* permitted values for its `has_arg' field... */ 81 | { 82 | no_argument = 0, /* option never takes an argument */ 83 | required_argument, /* option always requires an argument */ 84 | optional_argument /* option may take an argument */ 85 | }; 86 | 87 | extern int getopt_long(int nargc, char * const *nargv, const char *options, 88 | const struct option *long_options, int *idx); 89 | extern int getopt_long_only(int nargc, char * const *nargv, const char *options, 90 | const struct option *long_options, int *idx); 91 | /* 92 | * Previous MinGW implementation had... 93 | */ 94 | #ifndef HAVE_DECL_GETOPT 95 | /* 96 | * ...for the long form API only; keep this for compatibility. 97 | */ 98 | # define HAVE_DECL_GETOPT 1 99 | #endif 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ 106 | -------------------------------------------------------------------------------- /USBPcapCMD/iocontrol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "iocontrol.h" 11 | 12 | /* 13 | * Determines range and index for given address. 14 | * 15 | * Returns TRUE on success (address is within <0; 127>), FALSE otherwise. 16 | */ 17 | static BOOLEAN USBPcapGetAddressRangeAndIndex(int address, UINT8 *range, UINT8 *index) 18 | { 19 | if ((address < 0) || (address > 127)) 20 | { 21 | fprintf(stderr, "Invalid address: %d\n", address); 22 | return FALSE; 23 | } 24 | 25 | *range = address / 32; 26 | *index = address % 32; 27 | return TRUE; 28 | } 29 | 30 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address) 31 | { 32 | BOOLEAN filtered = FALSE; 33 | UINT8 range; 34 | UINT8 index; 35 | 36 | if (filter->filterAll == TRUE) 37 | { 38 | /* Do not check individual bit if all devices are filtered. */ 39 | return TRUE; 40 | } 41 | 42 | if (USBPcapGetAddressRangeAndIndex(address, &range, &index) == FALSE) 43 | { 44 | /* Assume that invalid addresses are filtered. */ 45 | return TRUE; 46 | } 47 | 48 | if (filter->addresses[range] & (1 << index)) 49 | { 50 | filtered = TRUE; 51 | } 52 | 53 | return filtered; 54 | } 55 | 56 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address) 57 | { 58 | UINT8 range; 59 | UINT8 index; 60 | 61 | if (USBPcapGetAddressRangeAndIndex(address, &range, &index) == FALSE) 62 | { 63 | return FALSE; 64 | } 65 | 66 | filter->addresses[range] |= (1 << index); 67 | return TRUE; 68 | } 69 | 70 | /* 71 | * Initializes address filter with given NULL-terminated, comma separated list of addresses. 72 | * 73 | * Returns TRUE on success, FALSE otherwise (malformed list or invalid filter pointer). 74 | */ 75 | BOOLEAN USBPcapInitAddressFilter(PUSBPCAP_ADDRESS_FILTER filter, PCHAR list, BOOLEAN filterAll) 76 | { 77 | USBPCAP_ADDRESS_FILTER tmp; 78 | 79 | if (filter == NULL) 80 | { 81 | return FALSE; 82 | } 83 | 84 | memset(&tmp, 0, sizeof(USBPCAP_ADDRESS_FILTER)); 85 | tmp.filterAll = filterAll; 86 | 87 | if (list != NULL) 88 | { 89 | while (*list) 90 | { 91 | if (isdigit(*list)) 92 | { 93 | int number; 94 | number = atoi(list); 95 | 96 | if (USBPcapSetDeviceFiltered(&tmp, number) == FALSE) 97 | { 98 | /* Address list contains invalid address. */ 99 | return FALSE; 100 | } 101 | 102 | /* Move past number. */ 103 | do 104 | { 105 | list++; 106 | } 107 | while (isdigit(*list)); 108 | } 109 | else if (*list == ',') 110 | { 111 | /* Found valid separator, advance to next number. */ 112 | list++; 113 | } 114 | else 115 | { 116 | fprintf(stderr, "Malformed address list. Invalid character: %c.\n", *list); 117 | return FALSE; 118 | } 119 | } 120 | } 121 | 122 | /* Address list was valid. Copy resulting structure. */ 123 | memcpy(filter, &tmp, sizeof(USBPCAP_ADDRESS_FILTER)); 124 | return TRUE; 125 | } 126 | -------------------------------------------------------------------------------- /USBPcapCMD/iocontrol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_CMD_IOCONTROL_H 8 | #define USBPCAP_CMD_IOCONTROL_H 9 | 10 | #include 11 | #include 12 | #include "USBPcap.h" 13 | 14 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address); 15 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address); 16 | BOOLEAN USBPcapInitAddressFilter(PUSBPCAP_ADDRESS_FILTER filter, PCHAR list, BOOLEAN filterAll); 17 | 18 | #endif /* USBPCAP_CMD_IOCONTROL_H */ 19 | -------------------------------------------------------------------------------- /USBPcapCMD/roothubs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * Based on devcon sample 5 | * Copyright (c) Microsoft Corporation 6 | * 7 | * SPDX-License-Identifier: BSD-2-Clause 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | typedef struct { 19 | LPTSTR *array; 20 | int used; 21 | int size; 22 | } StringArray; 23 | 24 | static StringArray non_standard_hwids; /* Stores non standard HWIDs. */ 25 | 26 | static void init_string_array(StringArray *a, int initial_size) 27 | { 28 | a->array = (LPTSTR *)malloc(initial_size * sizeof(LPTSTR)); 29 | a->used = 0; 30 | a->size = initial_size; 31 | } 32 | 33 | static void insert_string_array(StringArray *a, LPTSTR hwid) 34 | { 35 | if (a->used == a->size) 36 | { 37 | LPTSTR *tmp; 38 | 39 | a->size *= 2; 40 | tmp = (LPTSTR *)realloc(a->array, a->size * sizeof(LPTSTR)); 41 | if (tmp == NULL) 42 | { 43 | fprintf(stderr, "failed to insert %s to string array!\n", 44 | hwid); 45 | return; 46 | } 47 | a->array = tmp; 48 | } 49 | 50 | a->array[a->used++] = _tcsdup(hwid); 51 | } 52 | 53 | static void free_string_array(StringArray *a) 54 | { 55 | int i; 56 | for (i = 0; i < a->used; i++) 57 | { 58 | free(a->array[i]); 59 | } 60 | free(a->array); 61 | a->array = NULL; 62 | a->used = a->size = 0; 63 | } 64 | 65 | static BOOL is_standard_hwid(LPTSTR hwid) 66 | { 67 | if (hwid == NULL) 68 | { 69 | return FALSE; 70 | } 71 | else if (_tcscmp("USB\\ROOT_HUB", hwid) == 0) 72 | { 73 | return TRUE; 74 | } 75 | else if (_tcscmp("USB\\ROOT_HUB20", hwid) == 0) 76 | { 77 | return TRUE; 78 | } 79 | else if (_tcscmp("USB\\ROOT_HUB30", hwid) == 0) 80 | { 81 | return TRUE; 82 | } 83 | 84 | return FALSE; 85 | } 86 | 87 | static void add_non_standard_hwid(LPTSTR hwid) 88 | { 89 | insert_string_array(&non_standard_hwids, hwid); 90 | } 91 | 92 | static BOOL is_non_standard_hwid_known(LPTSTR hwid) 93 | { 94 | int i; 95 | for (i = 0; i < non_standard_hwids.used; i++) 96 | { 97 | if (_tcscmp(non_standard_hwids.array[i], hwid) == 0) 98 | { 99 | return TRUE; 100 | } 101 | } 102 | 103 | return FALSE; 104 | } 105 | 106 | static PTSTR build_non_standard_reg_multi_sz(StringArray *a, 107 | int *length) 108 | { 109 | PTSTR multi_sz; 110 | PTSTR ptr; 111 | 112 | int i; 113 | int len; 114 | 115 | for (len=1, i=0; iused; i++) 116 | { 117 | len += _tcslen(a->array[i]) + 1; 118 | } 119 | 120 | len *= sizeof(TCHAR); 121 | 122 | multi_sz = malloc(len); 123 | memset(multi_sz, 0, len); 124 | 125 | for (ptr = multi_sz, i = 0; i < a->used; i++) 126 | { 127 | _tcscpy_s(ptr, len - (ptr - multi_sz), a->array[i]); 128 | ptr += _tcslen(a->array[i]) + 1; 129 | } 130 | 131 | *length = len; 132 | return multi_sz; 133 | } 134 | 135 | static void set_non_standard_hwids_reg_key(PTSTR multi_sz, int length) 136 | { 137 | HKEY hkey; 138 | LONG regVal; 139 | 140 | regVal = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 141 | _T("SYSTEM\\CurrentControlSet\\services\\USBPcap"), 142 | 0, 143 | KEY_SET_VALUE, 144 | &hkey); 145 | 146 | if (regVal == ERROR_SUCCESS) 147 | { 148 | regVal = RegSetValueEx(hkey, 149 | _T("NonStandardHWIDs"), 150 | 0, 151 | REG_MULTI_SZ, 152 | (const BYTE*)multi_sz, 153 | length); 154 | 155 | if (regVal != ERROR_SUCCESS) 156 | { 157 | fprintf(stderr, "Failed to set NonStandardHWIDs value\n"); 158 | } 159 | 160 | RegCloseKey(hkey); 161 | } 162 | else 163 | { 164 | fprintf(stderr, "Failed to open USBPcap service key\n"); 165 | } 166 | } 167 | 168 | /* 169 | * Returns index array for given MultiSz. 170 | * 171 | * Returns NULL-terminated array of strings on success. 172 | * Array must be freed using DelMultiSz(). 173 | * Returns NULL on failure. 174 | */ 175 | __drv_allocatesMem(object) 176 | static LPTSTR * GetMultiSzIndexArray(__in __drv_aliasesMem LPTSTR MultiSz) 177 | { 178 | LPTSTR scan; 179 | LPTSTR *array; 180 | int elements; 181 | 182 | for (scan = MultiSz, elements = 0; scan[0] ;elements++) 183 | { 184 | scan += lstrlen(scan)+1; 185 | } 186 | array = (LPTSTR*)malloc(sizeof(LPTSTR) * (elements+2)); 187 | if(!array) 188 | { 189 | return NULL; 190 | } 191 | array[0] = MultiSz; 192 | array++; 193 | if (elements) 194 | { 195 | for (scan = MultiSz, elements = 0; scan[0]; elements++) 196 | { 197 | array[elements] = scan; 198 | scan += lstrlen(scan) + 1; 199 | } 200 | } 201 | array[elements] = NULL; 202 | return array; 203 | } 204 | 205 | /* 206 | * Retrieves multi-sz devnode registry property for given DEVINST. 207 | * 208 | * Returns NULL-terminated array of strings on success. 209 | * Array must be freed using DelMultiSz(). 210 | * Returns NULL on failure. 211 | */ 212 | __drv_allocatesMem(object) 213 | static LPTSTR *GetDevMultiSz(DEVINST roothub, ULONG property) 214 | { 215 | LPTSTR buffer; 216 | ULONG size; 217 | ULONG dataType; 218 | LPTSTR * array; 219 | DWORD szChars; 220 | CONFIGRET ret; 221 | 222 | size = 0; 223 | buffer = NULL; 224 | 225 | ret = CM_Get_DevNode_Registry_Property(roothub, property, &dataType, 226 | buffer, &size, 0); 227 | 228 | if (ret != CR_BUFFER_SMALL || dataType != REG_MULTI_SZ) 229 | { 230 | goto failed; 231 | } 232 | 233 | if (size == 0) 234 | { 235 | goto failed; 236 | } 237 | buffer = malloc(sizeof(TCHAR)*((size/sizeof(TCHAR))+2)); 238 | if (!buffer) 239 | { 240 | goto failed; 241 | } 242 | 243 | ret = CM_Get_DevNode_Registry_Property(roothub, property, &dataType, 244 | buffer, &size, 0); 245 | 246 | if (ret == CR_SUCCESS) 247 | { 248 | szChars = size/sizeof(TCHAR); 249 | buffer[szChars] = TEXT('\0'); 250 | buffer[szChars+1] = TEXT('\0'); 251 | array = GetMultiSzIndexArray(buffer); 252 | if (array) 253 | { 254 | return array; 255 | } 256 | } 257 | 258 | failed: 259 | if (buffer) 260 | { 261 | free(buffer); 262 | } 263 | return NULL; 264 | } 265 | 266 | /* 267 | * Frees array allocated by GetDevMultiSz() 268 | */ 269 | static void DelMultiSz(__in_opt __drv_freesMem(object) LPTSTR* Array) 270 | { 271 | if(Array) 272 | { 273 | Array--; 274 | if(Array[0]) 275 | { 276 | free(Array[0]); 277 | } 278 | free(Array); 279 | } 280 | } 281 | 282 | 283 | void find_non_standard_hwids(HDEVINFO devs, 284 | PSP_DEVINFO_DATA devInfo, 285 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail) 286 | { 287 | LPTSTR *hwIds = NULL; 288 | LPTSTR *compatIds = NULL; 289 | LPTSTR *tmpIds = NULL; 290 | CONFIGRET cr; 291 | DEVINST roothub; 292 | 293 | /* Assume that all host controller children are Root Hubs */ 294 | cr = CM_Get_Child(&roothub, devInfo->DevInst, 0); 295 | 296 | while (cr == CR_SUCCESS) 297 | { 298 | BOOL standard = FALSE; 299 | 300 | hwIds = GetDevMultiSz(roothub, CM_DRP_HARDWAREID); 301 | compatIds = GetDevMultiSz(roothub, CM_DRP_COMPATIBLEIDS); 302 | 303 | if (hwIds) 304 | { 305 | for (tmpIds = hwIds; tmpIds[0] != NULL; tmpIds++) 306 | { 307 | printf("Hardware ID: %s\n", tmpIds[0]); 308 | if (is_standard_hwid(tmpIds[0]) == TRUE) 309 | { 310 | printf("Found standard HWID\n"); 311 | standard = TRUE; 312 | } 313 | } 314 | 315 | if (standard == FALSE) 316 | { 317 | printf("RootHub does not have standard HWID! "); 318 | 319 | if (is_non_standard_hwid_known(hwIds[0]) == TRUE) 320 | { 321 | printf("%s is already in the non-standard list.\n", hwIds[0]); 322 | } 323 | else 324 | { 325 | add_non_standard_hwid(hwIds[0]); 326 | printf("Added %s to non-standard list.\n", hwIds[0]); 327 | } 328 | } 329 | } 330 | 331 | if (compatIds) 332 | { 333 | for (tmpIds = compatIds; tmpIds[0] != NULL; tmpIds++) 334 | { 335 | printf("Compatible ID: %s\n", tmpIds[0]); 336 | } 337 | } 338 | 339 | DelMultiSz(hwIds); 340 | DelMultiSz(compatIds); 341 | 342 | cr = CM_Get_Sibling(&roothub, roothub, 0); 343 | } 344 | } 345 | 346 | void restart_device(HDEVINFO devs, 347 | PSP_DEVINFO_DATA devInfo, 348 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail) 349 | { 350 | SP_PROPCHANGE_PARAMS pcp; 351 | SP_DEVINSTALL_PARAMS devParams; 352 | TCHAR devID[MAX_DEVICE_ID_LEN]; 353 | 354 | if (CM_Get_Device_ID_Ex(devInfo->DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail->RemoteMachineHandle) != CR_SUCCESS) 355 | { 356 | devID[0] = TEXT('\0'); 357 | printf("Unknown instance ID: "); 358 | } 359 | else 360 | { 361 | printf("%s: ", devID); 362 | } 363 | 364 | pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 365 | pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; 366 | pcp.StateChange = DICS_PROPCHANGE; 367 | pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; 368 | pcp.HwProfile = 0; 369 | 370 | if (!SetupDiSetClassInstallParams(devs, devInfo, &pcp.ClassInstallHeader, sizeof(pcp)) || 371 | !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, devs, devInfo)) 372 | { 373 | fprintf(stderr, "Failed to invoke DIF_PROPERTYCHANGE! Please reboot.\n"); 374 | } 375 | else 376 | { 377 | devParams.cbSize = sizeof(devParams); 378 | 379 | if (SetupDiGetDeviceInstallParams(devs,devInfo,&devParams) && 380 | (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) 381 | { 382 | printf("Reboot required.\n"); 383 | } 384 | else 385 | { 386 | printf("Restarted.\n"); 387 | } 388 | } 389 | } 390 | 391 | static void foreach_host_controller( 392 | void (*callback)(HDEVINFO devs, 393 | PSP_DEVINFO_DATA devInfo, 394 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail)) 395 | { 396 | HDEVINFO devs = INVALID_HANDLE_VALUE; 397 | DWORD devIndex; 398 | SP_DEVINFO_DATA devInfo; 399 | SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; 400 | 401 | devs = SetupDiGetClassDevsEx(&GUID_DEVINTERFACE_USB_HOST_CONTROLLER, 402 | NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT, 403 | NULL, NULL, NULL); 404 | 405 | if(devs == INVALID_HANDLE_VALUE) 406 | { 407 | fprintf(stderr, "SetupDiCreateDeviceInfoListEx() failed\n"); 408 | goto final; 409 | } 410 | 411 | devInfoListDetail.cbSize = sizeof(devInfoListDetail); 412 | if (!SetupDiGetDeviceInfoListDetail(devs, &devInfoListDetail)) 413 | { 414 | fprintf(stderr, "SetupDiGetDeviceInfoListDetail() failed\n"); 415 | goto final; 416 | } 417 | 418 | devInfo.cbSize = sizeof(devInfo); 419 | for (devIndex = 0; SetupDiEnumDeviceInfo(devs, devIndex, &devInfo); devIndex++) 420 | { 421 | callback(devs, &devInfo, &devInfoListDetail); 422 | } 423 | 424 | final: 425 | if (devs != INVALID_HANDLE_VALUE) 426 | { 427 | SetupDiDestroyDeviceInfoList(devs); 428 | } 429 | } 430 | 431 | void init_non_standard_roothub_hwid() 432 | { 433 | int length; 434 | PTSTR multi_sz; 435 | 436 | init_string_array(&non_standard_hwids, 1); 437 | 438 | foreach_host_controller(find_non_standard_hwids); 439 | 440 | if (non_standard_hwids.used > 0) 441 | { 442 | multi_sz = build_non_standard_reg_multi_sz(&non_standard_hwids, &length); 443 | set_non_standard_hwids_reg_key(multi_sz, length); 444 | free(multi_sz); 445 | } 446 | 447 | free_string_array(&non_standard_hwids); 448 | } 449 | 450 | void restart_all_usb_devices() 451 | { 452 | foreach_host_controller(restart_device); 453 | } 454 | -------------------------------------------------------------------------------- /USBPcapCMD/roothubs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_CMD_ROOTHUBS_H 8 | #define USBPCAP_CMD_ROOTHUBS_H 9 | 10 | void init_non_standard_roothub_hwid(); 11 | void restart_all_usb_devices(); 12 | 13 | #endif /* USBPCAP_CMD_ROOTHUBS_H */ 14 | -------------------------------------------------------------------------------- /USBPcapCMD/thread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "USBPcap.h" 12 | #include "thread.h" 13 | #include "iocontrol.h" 14 | #include "descriptors.h" 15 | 16 | HANDLE create_filter_read_handle(struct thread_data *data) 17 | { 18 | HANDLE filter_handle = INVALID_HANDLE_VALUE; 19 | char* inBuf = NULL; 20 | DWORD inBufSize = 0; 21 | DWORD bytes_ret; 22 | 23 | if (data->capture_new) 24 | { 25 | USBPcapSetDeviceFiltered(&data->filter, 0); 26 | } 27 | 28 | filter_handle = CreateFileA(data->device, 29 | GENERIC_READ|GENERIC_WRITE, 30 | 0, 31 | 0, 32 | OPEN_EXISTING, 33 | FILE_FLAG_OVERLAPPED, 34 | 0); 35 | 36 | if (filter_handle == INVALID_HANDLE_VALUE) 37 | { 38 | fprintf(stderr, "Couldn't open device - %d\n", GetLastError()); 39 | goto finish; 40 | } 41 | 42 | inBuf = malloc(sizeof(USBPCAP_IOCTL_SIZE)); 43 | ((PUSBPCAP_IOCTL_SIZE)inBuf)->size = data->snaplen; 44 | inBufSize = sizeof(USBPCAP_IOCTL_SIZE); 45 | 46 | if (!DeviceIoControl(filter_handle, 47 | IOCTL_USBPCAP_SET_SNAPLEN_SIZE, 48 | inBuf, 49 | inBufSize, 50 | NULL, 51 | 0, 52 | &bytes_ret, 53 | 0)) 54 | { 55 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n", 56 | GetLastError(), 57 | bytes_ret); 58 | goto finish; 59 | } 60 | 61 | ((PUSBPCAP_IOCTL_SIZE)inBuf)->size = data->bufferlen; 62 | 63 | if (!DeviceIoControl(filter_handle, 64 | IOCTL_USBPCAP_SETUP_BUFFER, 65 | inBuf, 66 | inBufSize, 67 | NULL, 68 | 0, 69 | &bytes_ret, 70 | 0)) 71 | { 72 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n", 73 | GetLastError(), 74 | bytes_ret); 75 | goto finish; 76 | } 77 | 78 | if (!DeviceIoControl(filter_handle, 79 | IOCTL_USBPCAP_START_FILTERING, 80 | (char*)&data->filter, 81 | sizeof(USBPCAP_ADDRESS_FILTER), 82 | NULL, 83 | 0, 84 | &bytes_ret, 85 | 0)) 86 | { 87 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n", 88 | GetLastError(), 89 | bytes_ret); 90 | goto finish; 91 | } 92 | 93 | free(inBuf); 94 | return filter_handle; 95 | 96 | finish: 97 | if (inBuf != NULL) 98 | { 99 | free(inBuf); 100 | } 101 | 102 | if (filter_handle != INVALID_HANDLE_VALUE) 103 | { 104 | CloseHandle(filter_handle); 105 | } 106 | 107 | return INVALID_HANDLE_VALUE; 108 | } 109 | 110 | static void write_data(struct thread_data* data, LPOVERLAPPED write_overlapped, 111 | void *buffer, DWORD bytes) 112 | { 113 | /* Write data to the end of the file. */ 114 | write_overlapped->Offset = 0xFFFFFFFF; 115 | write_overlapped->OffsetHigh = 0xFFFFFFFF; 116 | if (!WriteFile(data->write_handle, buffer, bytes, NULL, write_overlapped)) 117 | { 118 | DWORD err = GetLastError(); 119 | if (err == ERROR_IO_PENDING) 120 | { 121 | DWORD written; 122 | if (!GetOverlappedResult(data->write_handle, write_overlapped, &written, TRUE)) 123 | { 124 | fprintf(stderr, "GetOverlappedResult() on write handle failed: %d\n", GetLastError()); 125 | } 126 | else if (written != bytes) 127 | { 128 | fprintf(stderr, "Wrote %d bytes instead of %d. Stopping capture.\n", written, bytes); 129 | data->process = FALSE; 130 | } 131 | } 132 | else 133 | { 134 | /* Failed to write to output. Quit. */ 135 | fprintf(stderr, "Write failed (%d). Stopping capture.\n", err); 136 | data->process = FALSE; 137 | } 138 | } 139 | FlushFileBuffers(data->write_handle); 140 | ResetEvent(write_overlapped->hEvent); 141 | } 142 | 143 | static void process_data(struct thread_data* data, LPOVERLAPPED write_overlapped, 144 | unsigned char *buffer, DWORD bytes) 145 | { 146 | if (data->descriptors.buf_written < sizeof(pcap_hdr_t)) 147 | { 148 | DWORD to_write = sizeof(pcap_hdr_t) - data->descriptors.buf_written; 149 | if (to_write > bytes) 150 | { 151 | to_write = bytes; 152 | } 153 | memcpy(&data->descriptors.buf[data->descriptors.buf_written], buffer, to_write); 154 | data->descriptors.buf_written += to_write; 155 | 156 | if (data->descriptors.buf_written == sizeof(pcap_hdr_t)) 157 | { 158 | pcap_hdr_t *hdr = (pcap_hdr_t *)data->descriptors.buf; 159 | write_data(data, write_overlapped, data->descriptors.buf, sizeof(pcap_hdr_t)); 160 | if ((hdr->magic_number == 0xA1B2C3D4) && (hdr->network == DLT_USBPCAP) && (data->descriptors.descriptors_len > 0)) 161 | { 162 | write_data(data, write_overlapped, data->descriptors.descriptors, data->descriptors.descriptors_len); 163 | } 164 | } 165 | buffer += to_write; 166 | bytes -= to_write; 167 | 168 | if (bytes == 0) 169 | { 170 | /* Nothing more to write */ 171 | return; 172 | } 173 | } 174 | write_data(data, write_overlapped, buffer, bytes); 175 | } 176 | 177 | DWORD WINAPI read_thread(LPVOID param) 178 | { 179 | struct thread_data* data = (struct thread_data*)param; 180 | unsigned char* buffer; 181 | DWORD dummy_read; 182 | unsigned char dummy_buf; 183 | OVERLAPPED read_overlapped; 184 | OVERLAPPED write_overlapped; 185 | OVERLAPPED connect_overlapped; 186 | OVERLAPPED write_handle_read_overlapped; /* Used to detect broken pipe. */ 187 | DWORD read; 188 | DWORD err; 189 | HANDLE table[5]; 190 | int table_count = 0; 191 | 192 | memset(&table, 0, sizeof(table)); 193 | 194 | buffer = malloc(data->bufferlen); 195 | if (buffer == NULL) 196 | { 197 | fprintf(stderr, "Failed to allocate user-mode buffer (length %d)\n", 198 | data->bufferlen); 199 | goto finish; 200 | } 201 | 202 | if (data->read_handle == INVALID_HANDLE_VALUE) 203 | { 204 | fprintf(stderr, "Thread started with invalid read handle!\n"); 205 | goto finish; 206 | } 207 | 208 | if (data->write_handle == INVALID_HANDLE_VALUE) 209 | { 210 | fprintf(stderr, "Thread started with invalid write handle!\n"); 211 | goto finish; 212 | } 213 | 214 | memset(&read_overlapped, 0, sizeof(read_overlapped)); 215 | memset(&connect_overlapped, 0, sizeof(connect_overlapped)); 216 | memset(&write_overlapped, 0, sizeof(write_overlapped)); 217 | memset(&write_handle_read_overlapped, 0, sizeof(write_handle_read_overlapped)); 218 | read_overlapped.hEvent = CreateEvent(NULL, 219 | TRUE /* Manual Reset */, 220 | FALSE /* Default non signaled */, 221 | NULL /* No name */); 222 | connect_overlapped.hEvent = CreateEvent(NULL, 223 | TRUE /* Manual Reset */, 224 | FALSE /* Default non signaled */, 225 | NULL /* No name */); 226 | write_overlapped.hEvent = CreateEvent(NULL, 227 | TRUE /* Manual Reset */, 228 | FALSE /* Default non signaled */, 229 | NULL /* No name */); 230 | write_handle_read_overlapped.hEvent = CreateEvent(NULL, 231 | TRUE /* Manual Reset */, 232 | FALSE /* Default non signaled */, 233 | NULL /* No name */); 234 | table[table_count] = read_overlapped.hEvent; 235 | table_count++; 236 | table[table_count] = write_overlapped.hEvent; 237 | table_count++; 238 | if (GetFileType(data->write_handle) == FILE_TYPE_PIPE) 239 | { 240 | /* Setup dummy reads from write handle so we can detect broken pipe 241 | * even ifthere isn't any data read from read handle. 242 | */ 243 | table[table_count] = write_handle_read_overlapped.hEvent; 244 | table_count++; 245 | ReadFile(data->write_handle, &dummy_buf, sizeof(dummy_buf), NULL, &write_handle_read_overlapped); 246 | } 247 | if (data->exit_event != INVALID_HANDLE_VALUE) 248 | { 249 | table[table_count] = data->exit_event; 250 | table_count++; 251 | } 252 | 253 | if (GetFileType(data->read_handle) == FILE_TYPE_PIPE) 254 | { 255 | table[table_count] = connect_overlapped.hEvent; 256 | table_count++; 257 | if (!ConnectNamedPipe(data->read_handle, &connect_overlapped)) 258 | { 259 | err = GetLastError(); 260 | if ((err != ERROR_IO_PENDING) && (err != ERROR_PIPE_CONNECTED)) 261 | { 262 | fprintf(stderr, "ConnectNamedPipe() failed with code %d\n", err); 263 | data->process = FALSE; 264 | } 265 | } 266 | } 267 | else 268 | { 269 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, NULL, &read_overlapped); 270 | } 271 | 272 | for (; data->process == TRUE;) 273 | { 274 | DWORD dw; 275 | 276 | dw = WaitForMultipleObjects(table_count, 277 | table, 278 | FALSE, 279 | INFINITE); 280 | #pragma warning(default : 4296) 281 | if ((dw >= WAIT_OBJECT_0) && dw < (WAIT_OBJECT_0 + table_count)) 282 | { 283 | int i = dw - WAIT_OBJECT_0; 284 | if (table[i] == read_overlapped.hEvent) 285 | { 286 | GetOverlappedResult(data->read_handle, &read_overlapped, &read, TRUE); 287 | ResetEvent(read_overlapped.hEvent); 288 | process_data(data, &write_overlapped, buffer, read); 289 | /* Start new read. */ 290 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, &read, &read_overlapped); 291 | } 292 | else if (table[i] == write_overlapped.hEvent) 293 | { 294 | ResetEvent(write_overlapped.hEvent); 295 | } 296 | else if (table[i] == write_handle_read_overlapped.hEvent) 297 | { 298 | /* Most likely broken pipe detected */ 299 | GetOverlappedResult(data->write_handle, &write_handle_read_overlapped, &dummy_read, TRUE); 300 | err = GetLastError(); 301 | ResetEvent(write_handle_read_overlapped.hEvent); 302 | if (err == ERROR_BROKEN_PIPE) 303 | { 304 | /* We should quit. */ 305 | data->process = FALSE; 306 | } 307 | else 308 | { 309 | /* Don't care about result. Start read again. */ 310 | ReadFile(data->write_handle, &dummy_buf, sizeof(dummy_buf), NULL, &write_handle_read_overlapped); 311 | } 312 | } 313 | else if (table[i] == data->exit_event) 314 | { 315 | /* We should quit as exit_event is set. */ 316 | data->process = FALSE; 317 | } 318 | else if (table[i] == connect_overlapped.hEvent) 319 | { 320 | ResetEvent(connect_overlapped.hEvent); 321 | /* Start reading data. */ 322 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, &read, &read_overlapped); 323 | } 324 | } 325 | else if (dw == WAIT_FAILED) 326 | { 327 | fprintf(stderr, "WaitForMultipleObjects failed in read_thread(): %d", GetLastError()); 328 | break; 329 | } 330 | } 331 | 332 | CancelIo(data->read_handle); 333 | CancelIo(data->write_handle); 334 | CloseHandle(read_overlapped.hEvent); 335 | CloseHandle(connect_overlapped.hEvent); 336 | CloseHandle(write_overlapped.hEvent); 337 | CloseHandle(write_handle_read_overlapped.hEvent); 338 | 339 | finish: 340 | if (buffer != NULL) 341 | { 342 | free(buffer); 343 | } 344 | 345 | /* Notify main thread that we are done. 346 | * If we are exiting due to exit_event being set by another thread, 347 | * setting the exit_event here isn't a problem (it is already set). 348 | */ 349 | if (data->exit_event != INVALID_HANDLE_VALUE) 350 | { 351 | SetEvent(data->exit_event); 352 | } 353 | 354 | return 0; 355 | } 356 | -------------------------------------------------------------------------------- /USBPcapCMD/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_CMD_THREAD_H 8 | #define USBPCAP_CMD_THREAD_H 9 | 10 | #include 11 | #include "USBPcap.h" 12 | 13 | struct inject_descriptors 14 | { 15 | void *descriptors; /* Packets to inject after pcap header on capture start */ 16 | int descriptors_len; /* inject_packets length in bytes */ 17 | 18 | /* Buffer to keep track of pcap data read from driver. Once it is filled, the magic 19 | * and DLT is checked and if it matches, the the inject_packets are written after 20 | * the header and then the normal capture continues. 21 | */ 22 | unsigned char buf[sizeof(pcap_hdr_t)]; 23 | int buf_written; 24 | }; 25 | 26 | struct thread_data 27 | { 28 | char *device; /* Filter device object name */ 29 | char *filename; /* Output filename */ 30 | char *address_list; /* Comma separated list with addresses of device to capture. */ 31 | USBPCAP_ADDRESS_FILTER filter; /* Addresses that should be filtered */ 32 | BOOLEAN capture_all; /* TRUE if all devices should be captured despite address_list. */ 33 | BOOLEAN capture_new; /* TRUE if we should automatically capture from new devices. */ 34 | UINT32 snaplen; /* Snapshot length */ 35 | UINT32 bufferlen; /* Internal kernel-mode buffer size */ 36 | volatile BOOL process; /* FALSE if thread should stop */ 37 | HANDLE read_handle; /* Handle to read data from. */ 38 | HANDLE write_handle; /* Handle to write data to. */ 39 | HANDLE job_handle; /* Handle to job object of worker process. */ 40 | HANDLE worker_process_thread; /* Handle to breakaway worker process main thread. */ 41 | HANDLE exit_event; /* Handle to event that indicates that main thread should exit. */ 42 | 43 | BOOLEAN inject_descriptors; /* TRUE if descriptors should be injected into capture. */ 44 | struct inject_descriptors descriptors; 45 | }; 46 | 47 | HANDLE create_filter_read_handle(struct thread_data *data); 48 | DWORD WINAPI read_thread(LPVOID param); 49 | 50 | #endif /* USBPCAP_CMD_THREAD_H */ 51 | -------------------------------------------------------------------------------- /USBPcapCMD/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | 8 | #ifndef USBPCAPCMD_VERSION_H 9 | #define USBPCAPCMD_VERSION_H 10 | 11 | #define USBPCAPCMD_VERSION_MAJOR 1 12 | #define USBPCAPCMD_VERSION_MINOR 5 13 | #define USBPCAPCMD_VERSION_REVISION 4 14 | #define USBPCAPCMD_VERSION_BUILD 0 15 | 16 | #define makeStr(x) #x 17 | #define makeString(x) makeStr(x) 18 | 19 | #define USBPCAPCMD_VERSION_STR \ 20 | makeString(USBPCAPCMD_VERSION_MAJOR) "." \ 21 | makeString(USBPCAPCMD_VERSION_MINOR) "." \ 22 | makeString(USBPCAPCMD_VERSION_REVISION) "." \ 23 | makeString(USBPCAPCMD_VERSION_BUILD) 24 | 25 | #endif /* USBPCAPCMD_VERSION_H */ 26 | -------------------------------------------------------------------------------- /USBPcapDriver/SOURCES: -------------------------------------------------------------------------------- 1 | TARGETNAME = USBPcap 2 | 3 | TARGETTYPE = DRIVER 4 | 5 | DRIVERTYPE = WDM 6 | 7 | INF_NAME=USBPcap 8 | USBPCAP_VERSION=1.5.4.0 9 | NTTARGETFILE2=$(OBJ_PATH)\$(O)\$(INF_NAME).inf 10 | 11 | TARGETLIBS = $(DDK_LIB_PATH)\Wdm.lib \ 12 | $(DDK_LIB_PATH)\Wdmsec.lib \ 13 | $(DDK_LIB_PATH)\Ntstrsafe.lib \ 14 | $(DDK_LIB_PATH)\Ntoskrnl.lib \ 15 | $(DDK_LIB_PATH)\USBd.lib 16 | 17 | C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN=1 18 | 19 | INCLUDES = $(DDK_INC_PATH); \ 20 | $(WDM_INC_PATH); 21 | 22 | SOURCES = USBPcap.rc \ 23 | USBPcapBuffer.c \ 24 | USBPcapDeviceControl.c \ 25 | USBPcapFilterManager.c \ 26 | USBPcapGenReq.c \ 27 | USBPcapHelperFunctions.c \ 28 | USBPcapMain.c \ 29 | USBPcapPnP.c \ 30 | USBPcapPower.c \ 31 | USBPcapRootHubControl.c \ 32 | USBPcapQueue.c \ 33 | USBPcapTables.c \ 34 | USBPcapURB.c 35 | 36 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcap.inx: -------------------------------------------------------------------------------- 1 | [Version] 2 | Signature = "$WINDOWS NT$" 3 | Class = USB 4 | ClassGuid = {36FC9E60-C465-11CF-8056-444553540000} 5 | DriverPackageType = ClassFilter 6 | Provider = %PROVIDER% 7 | CatalogFile.NTx86 = USBPcapx86.cat 8 | CatalogFile.NTamd64 = USBPcapamd64.cat 9 | 10 | [DestinationDirs] 11 | DefaultDestDir = 12 12 | 13 | [SourceDisksNames] 14 | 1 = %DiskId1%,,,"." 15 | 16 | [SourceDisksFiles] 17 | USBPcap.sys = 1,, 18 | 19 | [DefaultInstall.NTx86] 20 | CopyFiles = @USBPcap.sys 21 | AddReg = USBPcap.AddReg 22 | 23 | [DefaultUninstall.NTx86] 24 | DelFiles = @USBPcap.sys 25 | DelReg = USBPcap.DelReg 26 | 27 | [DefaultInstall.NTamd64] 28 | CopyFiles = @USBPcap.sys 29 | AddReg = USBPcap.AddReg 30 | 31 | [DefaultUninstall.NTamd64] 32 | DelFiles = @USBPcap.sys 33 | DelReg = USBPcap.DelReg 34 | 35 | [USBPcap.AddReg] 36 | ;Add USBPcap to UpperFilters 37 | HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, UpperFilters, 0x00010008, USBPcap 38 | 39 | [USBPcap.DelReg] 40 | ;Delete USBPcap from UpperFilters 41 | HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, UpperFilters, 0x00018002, USBPcap 42 | 43 | [DefaultInstall.NTx86.Services] 44 | AddService = USBPcap,,Service.AddService 45 | 46 | [DefaultUninstall.NTx86.Services] 47 | DelService = USBPcap,0x00000200 48 | 49 | [DefaultInstall.NTamd64.Services] 50 | AddService = USBPcap,,Service.AddService 51 | 52 | [DefaultUninstall.NTamd64.Services] 53 | DelService = USBPcap,0x00000200 54 | 55 | [Service.AddService] 56 | DisplayName = %USBPcap.SvcDesc% 57 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 58 | StartType = 3 ; SERVICE_DEMAND_START 59 | ErrorControl = 2 ; SERVICE_ERROR_SEVERE 60 | ServiceBinary = %12%\USBPcap.sys 61 | 62 | [Strings] 63 | PROVIDER = "USBPcap" 64 | StdMfg = "USBPcap Developers" 65 | DiskId1 = "USBPcap Installation Disk #1" 66 | USBPcap.DeviceDesc = "USBPcap Filter Driver" 67 | USBPcap.SvcDesc = "USBPcap Capture Service" 68 | 69 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcap.rc: -------------------------------------------------------------------------------- 1 | #include "Windows.h" 2 | 3 | 1 VERSIONINFO 4 | FILEVERSION 1,5,4,0 5 | PRODUCTVERSION 1,5,4,0 6 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 7 | FILEFLAGS (VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE|VS_FF_DEBUG) 8 | FILEOS VOS__WINDOWS32 9 | FILETYPE VFT_APP 10 | FILESUBTYPE VFT2_UNKNOWN 11 | BEGIN 12 | BLOCK "StringFileInfo" 13 | BEGIN 14 | BLOCK "040904E4" 15 | BEGIN 16 | VALUE "CompanyName", "USBPcap" 17 | VALUE "FileDescription", "USBPcap Driver" 18 | VALUE "FileVersion", "1.5.4.0" 19 | VALUE "InternalName", "USBPcap" 20 | VALUE "LegalCopyright", "(c) 2013-2020 Tomasz Mon" 21 | VALUE "OriginalFilename", "USBPcap" 22 | VALUE "ProductName", "USBPcap Sniffer Driver" 23 | VALUE "ProductVersion", "1.5.4.0" 24 | END 25 | END 26 | 27 | BLOCK "VarFileInfo" 28 | BEGIN 29 | VALUE "Translation", 0x409, 1252 30 | END 31 | END 32 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_BUFFER_H 8 | #define USBPCAP_BUFFER_H 9 | 10 | #include "USBPcapMain.h" 11 | 12 | typedef struct 13 | { 14 | UINT32 size; 15 | PVOID buffer; 16 | } USBPCAP_PAYLOAD_ENTRY, *PUSBPCAP_PAYLOAD_ENTRY; 17 | 18 | NTSTATUS USBPcapSetUpBuffer(PUSBPCAP_ROOTHUB_DATA pData, 19 | UINT32 bytes); 20 | NTSTATUS USBPcapSetSnaplenSize(PUSBPCAP_ROOTHUB_DATA pData, 21 | UINT32 bytes); 22 | 23 | VOID USBPcapBufferRemoveBuffer(PDEVICE_EXTENSION pDevExt); 24 | VOID USBPcapBufferInitializeBuffer(PDEVICE_EXTENSION pDevExt); 25 | NTSTATUS USBPcapBufferHandleReadIrp(PIRP pIrp, 26 | PDEVICE_EXTENSION pDevExt, 27 | PUINT32 pBytesRead); 28 | 29 | /* Same as USBPcapBufferWriteTimestampedPacket but take {0, NULL} terminated 30 | * array of payload entries instead of single buffer pointer. 31 | */ 32 | NTSTATUS USBPcapBufferWriteTimestampedPayload(PUSBPCAP_ROOTHUB_DATA pRootData, 33 | LARGE_INTEGER timestamp, 34 | PUSBPCAP_BUFFER_PACKET_HEADER header, 35 | PUSBPCAP_PAYLOAD_ENTRY payload); 36 | /* Same as USBPcapBufferWritePacket but take {0, NULL} terminated 37 | * array of payload entries instead of single buffer pointer. 38 | */ 39 | NTSTATUS USBPcapBufferWritePayload(PUSBPCAP_ROOTHUB_DATA pRootData, 40 | PUSBPCAP_BUFFER_PACKET_HEADER header, 41 | PUSBPCAP_PAYLOAD_ENTRY payload); 42 | 43 | NTSTATUS USBPcapBufferWriteTimestampedPacket(PUSBPCAP_ROOTHUB_DATA pRootData, 44 | LARGE_INTEGER timestamp, 45 | PUSBPCAP_BUFFER_PACKET_HEADER header, 46 | PVOID buffer); 47 | NTSTATUS USBPcapBufferWritePacket(PUSBPCAP_ROOTHUB_DATA pRootData, 48 | PUSBPCAP_BUFFER_PACKET_HEADER header, 49 | PVOID buffer); 50 | 51 | #endif /* USBPCAP_BUFFER_H */ 52 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapDeviceControl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "include\USBPcap.h" 9 | #include "USBPcapURB.h" 10 | #include "USBPcapRootHubControl.h" 11 | #include "USBPcapBuffer.h" 12 | #include "USBPcapHelperFunctions.h" 13 | 14 | static NTSTATUS 15 | HandleUSBPcapControlIOCTL(PIRP pIrp, PIO_STACK_LOCATION pStack, 16 | PDEVICE_EXTENSION rootExt, PUSBPCAP_ROOTHUB_DATA pRootData, 17 | BOOLEAN allowCapture, 18 | SIZE_T *outLength) 19 | { 20 | NTSTATUS ntStat = STATUS_SUCCESS; 21 | if (pStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USBPCAP_GET_HUB_SYMLINK) 22 | { 23 | PWSTR interfaces; 24 | SIZE_T length; 25 | 26 | DkDbgStr("IOCTL_USBPCAP_GET_HUB_SYMLINK"); 27 | 28 | interfaces = USBPcapGetHubInterfaces(rootExt->pNextDevObj); 29 | if (interfaces == NULL) 30 | { 31 | return STATUS_NOT_FOUND; 32 | } 33 | 34 | length = wcslen(interfaces); 35 | length = (length+1)*sizeof(WCHAR); 36 | 37 | if (pStack->Parameters.DeviceIoControl.OutputBufferLength < length) 38 | { 39 | DkDbgVal("Too small buffer", length); 40 | ntStat = STATUS_BUFFER_TOO_SMALL; 41 | } 42 | else 43 | { 44 | RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, 45 | (PVOID)interfaces, 46 | length); 47 | *outLength = length; 48 | DkDbgVal("Successfully copied data", length); 49 | } 50 | ExFreePool((PVOID)interfaces); 51 | return ntStat; 52 | } 53 | 54 | /* Other IOCTLs are allowed only for the capture handle (exclusive) */ 55 | if (!allowCapture) 56 | { 57 | return STATUS_ACCESS_DENIED; 58 | } 59 | 60 | switch (pStack->Parameters.DeviceIoControl.IoControlCode) 61 | { 62 | case IOCTL_USBPCAP_SETUP_BUFFER: 63 | { 64 | PUSBPCAP_IOCTL_SIZE pBufferSize; 65 | 66 | if (pStack->Parameters.DeviceIoControl.InputBufferLength != 67 | sizeof(USBPCAP_IOCTL_SIZE)) 68 | { 69 | ntStat = STATUS_INVALID_PARAMETER; 70 | break; 71 | } 72 | 73 | pBufferSize = (PUSBPCAP_IOCTL_SIZE)pIrp->AssociatedIrp.SystemBuffer; 74 | DkDbgVal("IOCTL_USBPCAP_SETUP_BUFFER", pBufferSize->size); 75 | 76 | ntStat = USBPcapSetUpBuffer(pRootData, pBufferSize->size); 77 | break; 78 | } 79 | 80 | case IOCTL_USBPCAP_START_FILTERING: 81 | { 82 | PUSBPCAP_ADDRESS_FILTER pAddressFilter; 83 | 84 | if (pStack->Parameters.DeviceIoControl.InputBufferLength != 85 | sizeof(USBPCAP_ADDRESS_FILTER)) 86 | { 87 | ntStat = STATUS_INVALID_PARAMETER; 88 | break; 89 | } 90 | 91 | pAddressFilter = (PUSBPCAP_ADDRESS_FILTER)pIrp->AssociatedIrp.SystemBuffer; 92 | memcpy(&pRootData->filter, pAddressFilter, 93 | sizeof(USBPCAP_ADDRESS_FILTER)); 94 | 95 | DkDbgStr("IOCTL_USBPCAP_START_FILTERING"); 96 | DkDbgVal("", pAddressFilter->addresses[0]); 97 | DkDbgVal("", pAddressFilter->addresses[1]); 98 | DkDbgVal("", pAddressFilter->addresses[2]); 99 | DkDbgVal("", pAddressFilter->addresses[3]); 100 | DkDbgVal("", pAddressFilter->filterAll); 101 | break; 102 | } 103 | 104 | case IOCTL_USBPCAP_STOP_FILTERING: 105 | DkDbgStr("IOCTL_USBPCAP_STOP_FILTERING"); 106 | memset(&pRootData->filter, 0, 107 | sizeof(USBPCAP_ADDRESS_FILTER)); 108 | break; 109 | 110 | case IOCTL_USBPCAP_SET_SNAPLEN_SIZE: 111 | { 112 | PUSBPCAP_IOCTL_SIZE pSnaplen; 113 | 114 | if (pStack->Parameters.DeviceIoControl.InputBufferLength != 115 | sizeof(USBPCAP_IOCTL_SIZE)) 116 | { 117 | ntStat = STATUS_INVALID_PARAMETER; 118 | break; 119 | } 120 | 121 | pSnaplen = (PUSBPCAP_IOCTL_SIZE)pIrp->AssociatedIrp.SystemBuffer; 122 | DkDbgVal("IOCTL_USBPCAP_SET_SNAPLEN_SIZE", pSnaplen->size); 123 | 124 | ntStat = USBPcapSetSnaplenSize(pRootData, pSnaplen->size); 125 | break; 126 | } 127 | 128 | default: 129 | { 130 | ULONG ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode); 131 | DkDbgVal("This: IOCTL_XXXXX", ctlCode); 132 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 133 | break; 134 | } 135 | } 136 | return ntStat; 137 | } 138 | 139 | /////////////////////////////////////////////////////////////////////// 140 | // I/O device control request handlers 141 | // 142 | NTSTATUS DkDevCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) 143 | { 144 | NTSTATUS ntStat = STATUS_SUCCESS; 145 | PDEVICE_EXTENSION pDevExt = NULL; 146 | PIO_STACK_LOCATION pStack = NULL; 147 | ULONG ulRes = 0; 148 | 149 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 150 | 151 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 152 | if (!NT_SUCCESS(ntStat)) 153 | { 154 | DkDbgVal("Error lock!", ntStat); 155 | DkCompleteRequest(pIrp, ntStat, 0); 156 | return ntStat; 157 | } 158 | 159 | pStack = IoGetCurrentIrpStackLocation(pIrp); 160 | 161 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB || 162 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 163 | { 164 | IoSkipCurrentIrpStackLocation(pIrp); 165 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 166 | } 167 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL) 168 | { 169 | PDEVICE_EXTENSION rootExt; 170 | PUSBPCAP_ROOTHUB_DATA pRootData; 171 | BOOLEAN allowCapture = FALSE; 172 | SIZE_T length = 0; 173 | UINT_PTR info; 174 | 175 | rootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension; 176 | pRootData = (PUSBPCAP_ROOTHUB_DATA)rootExt->context.usb.pDeviceData->pRootData; 177 | if (InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL) == pStack->FileObject) 178 | { 179 | allowCapture = TRUE; 180 | } 181 | 182 | ntStat = HandleUSBPcapControlIOCTL(pIrp, pStack, rootExt, pRootData, allowCapture, &length); 183 | 184 | info = (UINT_PTR)length; 185 | 186 | DkCompleteRequest(pIrp, ntStat, info); 187 | } 188 | 189 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 190 | 191 | return ntStat; 192 | } 193 | 194 | 195 | // 196 | //-------------------------------------------------------------------------- 197 | // 198 | 199 | //////////////////////////////////////////////////////////////////////////// 200 | // Internal I/O device control request handlers 201 | // 202 | NTSTATUS DkInDevCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) 203 | { 204 | NTSTATUS ntStat = STATUS_SUCCESS; 205 | PDEVICE_EXTENSION pDevExt = NULL; 206 | PIO_STACK_LOCATION pStack = NULL; 207 | PDEVICE_OBJECT pNextDevObj = NULL; 208 | ULONG ctlCode = 0; 209 | 210 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 211 | 212 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 213 | if (!NT_SUCCESS(ntStat)) 214 | { 215 | DkDbgVal("Error lock!", ntStat); 216 | DkCompleteRequest(pIrp, ntStat, 0); 217 | return ntStat; 218 | } 219 | 220 | pStack = IoGetCurrentIrpStackLocation(pIrp); 221 | 222 | ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode); 223 | 224 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) 225 | { 226 | DkDbgVal("Hub Filter: IOCTL_INTERNAL_XXXXX", ctlCode); 227 | pNextDevObj = pDevExt->pNextDevObj; 228 | } 229 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 230 | { 231 | ntStat = DkTgtInDevCtl(pDevExt, pStack, pIrp); 232 | 233 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 234 | 235 | return ntStat; 236 | } 237 | else 238 | { 239 | DkDbgVal("This: IOCTL_INTERNAL_XXXXX", ctlCode); 240 | pNextDevObj = pDevExt->pNextDevObj; 241 | } 242 | 243 | if (pNextDevObj == NULL) 244 | { 245 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 246 | DkCompleteRequest(pIrp, ntStat, 0); 247 | } 248 | else 249 | { 250 | IoSkipCurrentIrpStackLocation(pIrp); 251 | ntStat = IoCallDriver(pNextDevObj, pIrp); 252 | } 253 | 254 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 255 | 256 | return ntStat; 257 | } 258 | 259 | 260 | NTSTATUS DkTgtInDevCtl(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) 261 | { 262 | NTSTATUS ntStat = STATUS_SUCCESS; 263 | PURB pUrb = NULL; 264 | ULONG ctlCode = 0; 265 | 266 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 267 | if (!NT_SUCCESS(ntStat)) 268 | { 269 | DkDbgVal("Error lock!", ntStat); 270 | DkCompleteRequest(pIrp, ntStat, 0); 271 | return ntStat; 272 | } 273 | 274 | ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode); 275 | 276 | // Our interest is IOCTL_INTERNAL_USB_SUBMIT_URB, where USB device driver send URB to 277 | // it's USB bus driver 278 | if (pStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB) 279 | { 280 | /* code here should cope with DISPATCH_LEVEL */ 281 | 282 | // URB is collected BEFORE forward to bus driver or next lower object 283 | pUrb = (PURB) pStack->Parameters.Others.Argument1; 284 | if (pUrb != NULL) 285 | { 286 | USBPcapAnalyzeURB(pIrp, pUrb, FALSE, 287 | pDevExt->context.usb.pDeviceData); 288 | } 289 | 290 | // Forward this request to bus driver or next lower object 291 | // with completion routine 292 | IoCopyCurrentIrpStackLocationToNext(pIrp); 293 | IoSetCompletionRoutine(pIrp, 294 | (PIO_COMPLETION_ROUTINE) DkTgtInDevCtlCompletion, 295 | NULL, TRUE, TRUE, TRUE); 296 | 297 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 298 | } 299 | else 300 | { 301 | DkDbgVal("IOCTL_INTERNAL_USB_XXXX", ctlCode); 302 | 303 | IoSkipCurrentIrpStackLocation(pIrp); 304 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 305 | 306 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 307 | } 308 | 309 | return ntStat; 310 | } 311 | 312 | NTSTATUS DkTgtInDevCtlCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx) 313 | { 314 | NTSTATUS status; 315 | PDEVICE_EXTENSION pDevExt = NULL; 316 | PURB pUrb = NULL; 317 | PIO_STACK_LOCATION pStack = NULL; 318 | 319 | if (pIrp->PendingReturned) 320 | IoMarkIrpPending(pIrp); 321 | 322 | status = pIrp->IoStatus.Status; 323 | 324 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 325 | 326 | // URB is collected AFTER forward to bus driver or next lower object 327 | pStack = IoGetCurrentIrpStackLocation(pIrp); 328 | pUrb = (PURB) pStack->Parameters.Others.Argument1; 329 | if (pUrb != NULL) 330 | { 331 | USBPcapAnalyzeURB(pIrp, pUrb, TRUE, 332 | pDevExt->context.usb.pDeviceData); 333 | } 334 | 335 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 336 | 337 | return status; 338 | } 339 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapFilterManager.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "USBPcapHelperFunctions.h" 9 | #include "USBPcapTables.h" 10 | #include "USBPcapRootHubControl.h" 11 | 12 | /* 13 | * Frees pDevExt.context.usb.pDeviceData 14 | */ 15 | static void USBPcapFreeDeviceData(IN PDEVICE_EXTENSION pDevExt) 16 | { 17 | PUSBPCAP_DEVICE_DATA pDeviceData; 18 | 19 | if (pDevExt == NULL) 20 | { 21 | return; 22 | } 23 | 24 | ASSERT((pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) || 25 | (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)); 26 | 27 | pDeviceData = pDevExt->context.usb.pDeviceData; 28 | 29 | if (pDeviceData != NULL) 30 | { 31 | if (pDeviceData->pRootData) 32 | { 33 | LONG count; 34 | 35 | count = InterlockedDecrement(&pDeviceData->pRootData->refCount); 36 | if (count == 0) 37 | { 38 | /* 39 | * RootHub is supposed to hold the last reference. 40 | * So if we enter here, this data can be safely removed. 41 | */ 42 | if (pDeviceData->pRootData->buffer != NULL) 43 | { 44 | ExFreePool((PVOID)pDeviceData->pRootData->buffer); 45 | } 46 | ExFreePool((PVOID)pDeviceData->pRootData); 47 | pDeviceData->pRootData = NULL; 48 | } 49 | } 50 | 51 | if (pDeviceData->endpointTable != NULL) 52 | { 53 | USBPcapFreeEndpointTable(pDeviceData->endpointTable); 54 | pDeviceData->endpointTable = NULL; 55 | } 56 | 57 | if (pDeviceData->URBIrpTable != NULL) 58 | { 59 | USBPcapFreeURBIRPInfoTable(pDeviceData->URBIrpTable); 60 | pDeviceData->URBIrpTable = NULL; 61 | } 62 | 63 | if (pDeviceData->previousChildren != NULL) 64 | { 65 | ExFreePool((PVOID)pDeviceData->previousChildren); 66 | pDeviceData->previousChildren = NULL; 67 | } 68 | 69 | if (pDeviceData->descriptor != NULL) 70 | { 71 | ExFreePool((PVOID)pDeviceData->descriptor); 72 | pDeviceData->descriptor = NULL; 73 | } 74 | 75 | ExFreePool((PVOID)pDeviceData); 76 | pDevExt->context.usb.pDeviceData = NULL; 77 | } 78 | } 79 | 80 | /* 81 | * Allocates USBPCAP_DEVICE_DATA. 82 | */ 83 | static NTSTATUS USBPcapAllocateDeviceData(IN PDEVICE_EXTENSION pDevExt, 84 | IN PDEVICE_EXTENSION pParentDevExt) 85 | { 86 | PUSBPCAP_DEVICE_DATA pDeviceData; 87 | NTSTATUS status = STATUS_SUCCESS; 88 | BOOLEAN allocRoothubData; 89 | 90 | allocRoothubData = (pParentDevExt == NULL); 91 | 92 | /* Allocate USBPCAP_DEVICE_DATA */ 93 | pDeviceData = ExAllocatePoolWithTag(NonPagedPool, 94 | sizeof(USBPCAP_DEVICE_DATA), 95 | DKPORT_MTAG); 96 | 97 | if (pDeviceData != NULL) 98 | { 99 | /* deviceAddress, port and isHub will be properly set up when 100 | * filter driver handles IRP_MN_START_DEVICE 101 | */ 102 | 103 | pDeviceData->deviceAddress = 255; /* UNKNOWN */ 104 | 105 | /* This will get changed to TRUE once the deviceAddress, 106 | * parentPort and isHub will be correctly set up. 107 | */ 108 | pDeviceData->properData = FALSE; 109 | 110 | /* Since 0 is invalid connection index, set that here */ 111 | pDeviceData->parentPort = 0; 112 | /* assume that roothub is a hub and all other devices are not. */ 113 | pDeviceData->isHub = allocRoothubData; 114 | 115 | pDeviceData->previousChildren = NULL; 116 | 117 | if (allocRoothubData == FALSE) 118 | { 119 | /* 120 | * This is not a roothub, just get the roothub data pointer 121 | * and increment the reference count 122 | */ 123 | pDeviceData->pRootData = 124 | pParentDevExt->context.usb.pDeviceData->pRootData; 125 | InterlockedIncrement(&pDeviceData->pRootData->refCount); 126 | } 127 | else 128 | { 129 | /* Allocate USBPCAP_ROOTHUB_DATA */ 130 | pDeviceData->pRootData = 131 | ExAllocatePoolWithTag(NonPagedPool, 132 | sizeof(USBPCAP_ROOTHUB_DATA), 133 | DKPORT_MTAG); 134 | if (pDeviceData->pRootData != NULL) 135 | { 136 | /* Initialize empty buffer */ 137 | KeInitializeSpinLock(&pDeviceData->pRootData->bufferLock); 138 | pDeviceData->pRootData->buffer = NULL; 139 | pDeviceData->pRootData->readOffset = 0; 140 | pDeviceData->pRootData->writeOffset = 0; 141 | pDeviceData->pRootData->bufferSize = 0; 142 | 143 | /* Initialize default snaplen size */ 144 | pDeviceData->pRootData->snaplen = USBPCAP_DEFAULT_SNAP_LEN; 145 | 146 | /* Setup initial filtering state to FALSE */ 147 | memset(&pDeviceData->pRootData->filter, 0, 148 | sizeof(USBPCAP_ADDRESS_FILTER)); 149 | 150 | /* 151 | * Set the reference count 152 | * 153 | * The reference count will drop down to zero once the 154 | * roothub filter object gets destroyed. 155 | */ 156 | pDeviceData->pRootData->refCount = 1L; 157 | } 158 | else 159 | { 160 | status = STATUS_INSUFFICIENT_RESOURCES; 161 | } 162 | } 163 | 164 | KeInitializeSpinLock(&pDeviceData->tablesSpinLock); 165 | pDeviceData->endpointTable = USBPcapInitializeEndpointTable(NULL); 166 | pDeviceData->URBIrpTable = USBPcapInitializeURBIRPInfoTable(NULL); 167 | 168 | pDeviceData->descriptor = NULL; 169 | } 170 | else 171 | { 172 | status = STATUS_INSUFFICIENT_RESOURCES; 173 | } 174 | 175 | pDevExt->context.usb.pDeviceData = pDeviceData; 176 | 177 | if (!NT_SUCCESS(status)) 178 | { 179 | USBPcapFreeDeviceData(pDevExt); 180 | } 181 | else if (allocRoothubData == FALSE) 182 | { 183 | /* Set up parent and target objects in USBPCAP_DEVICE_DATA */ 184 | pDeviceData->pParentFlt = pParentDevExt->pThisDevObj; 185 | pDeviceData->pNextParentFlt = pParentDevExt->pNextDevObj; 186 | } 187 | 188 | return status; 189 | } 190 | 191 | static ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo) 192 | { 193 | PDEVICE_OBJECT ldo = IoGetAttachedDeviceReference(pdo); 194 | ULONG devtype = FILE_DEVICE_UNKNOWN; 195 | 196 | if (ldo != NULL) 197 | { 198 | devtype = ldo->DeviceType; 199 | ObDereferenceObject(ldo); 200 | } 201 | 202 | return devtype; 203 | } 204 | 205 | ///////////////////////////////////////////////////////////////////// 206 | // Functions to attach and detach USB Root HUB filter 207 | #pragma prefast(suppress: 28152, "Suppress 28152 for path where filter was not created. Please remove this suppression after doing any changes to AddDevice()!") 208 | NTSTATUS AddDevice(IN PDRIVER_OBJECT pDrvObj, 209 | IN PDEVICE_OBJECT pTgtDevObj) 210 | { 211 | NTSTATUS ntStat = STATUS_SUCCESS; 212 | UNICODE_STRING usTgtName; 213 | PDEVICE_OBJECT pHubFilter = NULL; 214 | PDEVICE_EXTENSION pDevExt = NULL; 215 | BOOLEAN isRootHub; 216 | 217 | // 1. Check if device is Root Hub 218 | isRootHub = USBPcapIsDeviceRootHub(pTgtDevObj); 219 | if (isRootHub == FALSE) 220 | { 221 | /* Do not attach to non-RootHub devices */ 222 | return STATUS_SUCCESS; 223 | } 224 | 225 | // 2. Create filter object 226 | ntStat = IoCreateDevice(pDrvObj, 227 | sizeof(DEVICE_EXTENSION), NULL, 228 | GetDeviceTypeToUse(pTgtDevObj), 0, 229 | FALSE, &pHubFilter); 230 | if (!NT_SUCCESS(ntStat)) 231 | { 232 | DkDbgVal("Error create Hub Filter!", ntStat); 233 | goto EndFunc; 234 | } 235 | 236 | pDevExt = (PDEVICE_EXTENSION) pHubFilter->DeviceExtension; 237 | pDevExt->deviceMagic = USBPCAP_MAGIC_ROOTHUB; 238 | pDevExt->pThisDevObj = pHubFilter; 239 | pDevExt->pDrvObj = pDrvObj; 240 | pDevExt->parentRemoveLock = NULL; 241 | 242 | IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0); 243 | 244 | ntStat = USBPcapAllocateDeviceData(pDevExt, NULL); 245 | if (!NT_SUCCESS(ntStat)) 246 | { 247 | goto EndFunc; 248 | } 249 | 250 | // 3. Attach to bus driver 251 | pDevExt->pNextDevObj = NULL; 252 | pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pHubFilter, pTgtDevObj); 253 | if (pDevExt->pNextDevObj == NULL) 254 | { 255 | ntStat = STATUS_NO_SUCH_DEVICE; 256 | DkDbgStr("Error attach device!"); 257 | goto EndFunc; 258 | } 259 | 260 | pHubFilter->Flags |= 261 | (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE)); 262 | 263 | pHubFilter->Flags &= ~DO_DEVICE_INITIALIZING; 264 | 265 | if (NT_SUCCESS(ntStat)) 266 | { 267 | PDEVICE_OBJECT control = NULL; 268 | PUSBPCAP_ROOTHUB_DATA pRootData; 269 | USHORT id; 270 | 271 | ntStat = USBPcapCreateRootHubControlDevice(pDevExt, 272 | &control, 273 | &id); 274 | 275 | pRootData = pDevExt->context.usb.pDeviceData->pRootData; 276 | pRootData->controlDevice = control; 277 | pRootData->busId = id; 278 | } 279 | 280 | EndFunc: 281 | 282 | // If something bad happened 283 | if (!NT_SUCCESS(ntStat)) 284 | { 285 | USBPcapFreeDeviceData(pDevExt); 286 | if (pHubFilter) 287 | { 288 | IoDeleteDevice(pHubFilter); 289 | pHubFilter = NULL; 290 | } 291 | } 292 | 293 | return ntStat; 294 | } 295 | 296 | VOID DkDetachAndDeleteHubFilt(PDEVICE_EXTENSION pDevExt) 297 | { 298 | NTSTATUS status; 299 | if (pDevExt->parentRemoveLock) 300 | { 301 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL); 302 | } 303 | 304 | if (pDevExt->pNextDevObj) 305 | { 306 | IoDetachDevice(pDevExt->pNextDevObj); 307 | pDevExt->pNextDevObj = NULL; 308 | } 309 | if (pDevExt->pThisDevObj) 310 | { 311 | IoDeleteDevice(pDevExt->pThisDevObj); 312 | pDevExt->pThisDevObj = NULL; 313 | } 314 | USBPcapFreeDeviceData(pDevExt); 315 | } 316 | 317 | //////////////////////////////////////////////////////////////////////////// 318 | // Functions to attach and detach target device object 319 | // 320 | NTSTATUS DkCreateAndAttachTgt(PDEVICE_EXTENSION pParentDevExt, PDEVICE_OBJECT pTgtDevObj) 321 | { 322 | NTSTATUS ntStat = STATUS_SUCCESS; 323 | PDEVICE_OBJECT pDeviceObject = NULL; 324 | PDEVICE_EXTENSION pDevExt = NULL; 325 | 326 | // 1. Create filter object for target device object 327 | ntStat = IoCreateDevice(pParentDevExt->pDrvObj, 328 | sizeof(DEVICE_EXTENSION), NULL, 329 | pTgtDevObj->DeviceType, 0, 330 | FALSE, &pDeviceObject); 331 | if (!NT_SUCCESS(ntStat)) 332 | { 333 | DkDbgVal("Error create target device!", ntStat); 334 | return ntStat; 335 | } 336 | 337 | if (pDeviceObject == NULL) 338 | { 339 | DkDbgStr("IoCreateDevice() succeeded but pDeviceObject was not set."); 340 | return ntStat; 341 | } 342 | 343 | pDevExt = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; 344 | pDevExt->deviceMagic = USBPCAP_MAGIC_DEVICE; 345 | pDevExt->pThisDevObj = pDeviceObject; 346 | pDevExt->parentRemoveLock = &pParentDevExt->removeLock; 347 | pDevExt->pDrvObj = pParentDevExt->pDrvObj; 348 | 349 | ntStat = USBPcapAllocateDeviceData(pDevExt, pParentDevExt); 350 | if (!NT_SUCCESS(ntStat)) 351 | { 352 | goto EndAttDev; 353 | } 354 | 355 | // 2. Initilize remove lock for filter object of target device 356 | IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0); 357 | 358 | // 3. Attach to target device 359 | pDevExt->pNextDevObj = NULL; 360 | pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pDevExt->pThisDevObj, pTgtDevObj); 361 | if (pDevExt->pNextDevObj == NULL) 362 | { 363 | DkDbgStr("Error attach target device!"); 364 | ntStat = STATUS_NO_SUCH_DEVICE; 365 | goto EndAttDev; 366 | } 367 | 368 | 369 | // 4. Set up some filter device object flags 370 | pDevExt->pThisDevObj->Flags |= 371 | (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_DIRECT_IO)); 372 | pDevExt->pThisDevObj->Flags &= ~DO_DEVICE_INITIALIZING; 373 | 374 | IoAcquireRemoveLock(pDevExt->parentRemoveLock, NULL); 375 | 376 | EndAttDev: 377 | if (!NT_SUCCESS(ntStat)) 378 | { 379 | USBPcapFreeDeviceData(pDevExt); 380 | if (pDeviceObject) 381 | { 382 | IoDeleteDevice(pDeviceObject); 383 | pDeviceObject = NULL; 384 | } 385 | } 386 | 387 | return ntStat; 388 | } 389 | 390 | VOID DkDetachAndDeleteTgt(PDEVICE_EXTENSION pDevExt) 391 | { 392 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; 393 | 394 | if (pDevExt->parentRemoveLock) 395 | { 396 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL); 397 | } 398 | if (pDevExt->pNextDevObj) 399 | { 400 | IoDetachDevice(pDevExt->pNextDevObj); 401 | pDevExt->pNextDevObj = NULL; 402 | } 403 | if (pDevExt->pThisDevObj) 404 | { 405 | IoDeleteDevice(pDevExt->pThisDevObj); 406 | pDevExt->pThisDevObj = NULL; 407 | } 408 | USBPcapFreeDeviceData(pDevExt); 409 | } 410 | 411 | 412 | ////////////////////////////////////////////////////////////////////////// 413 | // Function to get USB Root Hub device name, e.g., \Device\USBPDO-4 414 | // 415 | NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes) 416 | { 417 | NTSTATUS ntStat = STATUS_SUCCESS, clStat = STATUS_SUCCESS; 418 | HANDLE hObj; 419 | OBJECT_ATTRIBUTES oa; 420 | UNICODE_STRING usHubPath, usTgtDev; 421 | ULONG ulRet; 422 | 423 | RtlInitUnicodeString(&usHubPath, (PCWSTR) pIrp->AssociatedIrp.SystemBuffer); 424 | 425 | InitializeObjectAttributes(&oa, &usHubPath, OBJ_KERNEL_HANDLE, NULL, NULL); 426 | 427 | ntStat = ZwOpenSymbolicLinkObject(&hObj, GENERIC_ALL, &oa); 428 | if (!NT_SUCCESS(ntStat)) 429 | { 430 | DkDbgVal("Error open symbolic link!", ntStat); 431 | return ntStat; 432 | } 433 | 434 | usTgtDev.Length = 0; 435 | usTgtDev.MaximumLength = 512; 436 | usTgtDev.Buffer = (PWSTR) ExAllocatePoolWithTag(NonPagedPool, 512, DKPORT_MTAG); 437 | RtlFillMemory(usTgtDev.Buffer, 512, '\0'); 438 | 439 | ntStat = ZwQuerySymbolicLinkObject(hObj, &usTgtDev, &ulRet); 440 | if (!NT_SUCCESS(ntStat)) 441 | { 442 | DkDbgVal("Error query symbolic link!", ntStat); 443 | pIrp->IoStatus.Status = ntStat; 444 | 445 | *pUlRes = 0; 446 | 447 | } 448 | else 449 | { 450 | RtlFillMemory(pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength, '\0'); 451 | RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, usTgtDev.Buffer, 512); 452 | 453 | pIrp->IoStatus.Information = usTgtDev.Length; 454 | pIrp->IoStatus.Status = ntStat; 455 | 456 | *pUlRes = (ULONG) usTgtDev.Length; 457 | } 458 | 459 | ExFreePoolWithTag(usTgtDev.Buffer, DKPORT_MTAG); 460 | 461 | clStat = ZwClose(hObj); 462 | if (!NT_SUCCESS(clStat)) 463 | { 464 | DkDbgVal("Error close symbolic link!", clStat); 465 | } 466 | 467 | return ntStat; 468 | } 469 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapGenReq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "USBPcapBuffer.h" 9 | 10 | //////////////////////////////////////////////////////////////////////////// 11 | // Create, close and clean up handlers 12 | // 13 | NTSTATUS DkCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) 14 | { 15 | NTSTATUS ntStat = STATUS_SUCCESS; 16 | PDEVICE_EXTENSION pDevExt = NULL; 17 | PIO_STACK_LOCATION pStack = NULL; 18 | PDEVICE_OBJECT pNextDevObj = NULL; 19 | 20 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 21 | 22 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 23 | if (!NT_SUCCESS(ntStat)) 24 | { 25 | DkDbgVal("Error acquire lock!", ntStat); 26 | DkCompleteRequest(pIrp, ntStat, 0); 27 | return ntStat; 28 | } 29 | 30 | pStack = IoGetCurrentIrpStackLocation(pIrp); 31 | 32 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB || 33 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 34 | { 35 | // Handling Create, Close and Cleanup request for Hub Filter and 36 | // target devices 37 | IoSkipCurrentIrpStackLocation(pIrp); 38 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 39 | } 40 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL) 41 | { 42 | // Handling Create, Close and Cleanup request for this object 43 | switch (pStack->MajorFunction) 44 | { 45 | case IRP_MJ_CREATE: 46 | /* When elevated USBPcapCMD worker is opening the USBPcapX device, the DesiredAccess is: 47 | * SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | 48 | * FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA 49 | * 50 | * When unpriviledged USBPcapCMD opens USBPcapX to get hub symlink, the DesiredAccess is: 51 | * SYNCHRONIZE | FILE_READ_ATTRIBUTES 52 | * 53 | * Check for Read flags and allow only one such interface. 54 | */ 55 | if (pStack->Parameters.Create.SecurityContext->DesiredAccess & (READ_CONTROL | FILE_READ_DATA)) 56 | { 57 | PFILE_OBJECT *previous; 58 | previous = InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, pStack->FileObject, NULL); 59 | if (previous) 60 | { 61 | /* There is another handle that has the READ access - fail this one */ 62 | ntStat = STATUS_ACCESS_DENIED; 63 | } 64 | } 65 | else 66 | { 67 | /* Handle will be only able to call IOCTL_USBPCAP_GET_HUB_SYMLINK - allow it */ 68 | } 69 | break; 70 | 71 | 72 | case IRP_MJ_CLEANUP: 73 | if (InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL) == pStack->FileObject) 74 | { 75 | PDEVICE_EXTENSION rootExt; 76 | PUSBPCAP_ROOTHUB_DATA pRootData; 77 | DkCsqCleanUpQueue(pDevObj, pIrp); 78 | /* Stop filtering */ 79 | rootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension; 80 | pRootData = (PUSBPCAP_ROOTHUB_DATA)rootExt->context.usb.pDeviceData->pRootData; 81 | memset(&pRootData->filter, 0, sizeof(USBPCAP_ADDRESS_FILTER)); 82 | /* Free the buffer allocated for this device. */ 83 | USBPcapBufferRemoveBuffer(pDevExt); 84 | } 85 | break; 86 | 87 | 88 | case IRP_MJ_CLOSE: 89 | /* Clear the pCaptureObject if the priviledged (able to capture) handle is closed. */ 90 | InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, pStack->FileObject); 91 | break; 92 | 93 | 94 | default: 95 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 96 | break; 97 | } 98 | 99 | DkCompleteRequest(pIrp, ntStat, 0); 100 | } 101 | 102 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 103 | 104 | return ntStat; 105 | } 106 | 107 | 108 | // 109 | //-------------------------------------------------------------------------- 110 | // 111 | 112 | //////////////////////////////////////////////////////////////////////////// 113 | // Read and write request handlers 114 | // 115 | NTSTATUS DkReadWrite(PDEVICE_OBJECT pDevObj, PIRP pIrp) 116 | { 117 | NTSTATUS ntStat = STATUS_SUCCESS; 118 | PDEVICE_EXTENSION pDevExt = NULL; 119 | PIO_STACK_LOCATION pStack = NULL; 120 | 121 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 122 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 123 | if (!NT_SUCCESS(ntStat)){ 124 | DkDbgVal("Error acquire lock!", ntStat); 125 | DkCompleteRequest(pIrp, ntStat, 0); 126 | return ntStat; 127 | } 128 | 129 | pStack = IoGetCurrentIrpStackLocation(pIrp); 130 | 131 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB || 132 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 133 | { 134 | // Handling Read/Write request for Hub Filter object and 135 | // target devices 136 | IoSkipCurrentIrpStackLocation(pIrp); 137 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 138 | } 139 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL) 140 | { 141 | UINT32 bytesRead = 0; 142 | /* Handling Read/Write for control object */ 143 | switch (pStack->MajorFunction) 144 | { 145 | case IRP_MJ_READ: 146 | { 147 | if (pStack->FileObject == InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL)) 148 | { 149 | ntStat = USBPcapBufferHandleReadIrp(pIrp, pDevExt, 150 | &bytesRead); 151 | } 152 | else 153 | { 154 | ntStat = STATUS_ACCESS_DENIED; 155 | } 156 | break; 157 | } 158 | 159 | case IRP_MJ_WRITE: 160 | /* Writing to the control device is not supported */ 161 | ntStat = STATUS_NOT_SUPPORTED; 162 | break; 163 | 164 | 165 | default: 166 | DkDbgVal("Unknown IRP Major function", pStack->MajorFunction); 167 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 168 | break; 169 | } 170 | 171 | /* If the IRP was pended, do not call complete request */ 172 | if (ntStat != STATUS_PENDING) 173 | { 174 | DkCompleteRequest(pIrp, ntStat, (ULONG_PTR)bytesRead); 175 | } 176 | } 177 | 178 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 179 | 180 | return ntStat; 181 | } 182 | 183 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapHelperFunctions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_HELPER_FUNCTIONS_H 8 | #define USBPCAP_HELPER_FUNCTIONS_H 9 | 10 | #include "USBPcapMain.h" 11 | 12 | NTSTATUS USBPcapGetTargetDevicePdo(IN PDEVICE_OBJECT DeviceObject, 13 | OUT PDEVICE_OBJECT *pdo); 14 | 15 | NTSTATUS USBPcapGetNumberOfPorts(PDEVICE_OBJECT parent, 16 | PULONG numberOfPorts); 17 | 18 | #if DBG 19 | NTSTATUS USBPcapPrintUSBPChildrenInformation(PDEVICE_OBJECT hub); 20 | #else 21 | #define USBPcapPrintUSBPChildrenInformation(hub) {} 22 | #endif 23 | 24 | NTSTATUS USBPcapGetDeviceUSBInfo(PDEVICE_EXTENSION pDevExt); 25 | 26 | BOOLEAN USBPcapIsDeviceRootHub(PDEVICE_OBJECT device); 27 | 28 | PWSTR USBPcapGetHubInterfaces(PDEVICE_OBJECT hub); 29 | 30 | 31 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address); 32 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address); 33 | 34 | LARGE_INTEGER USBPcapGetCurrentTimestamp(VOID); 35 | 36 | #ifdef ALLOC_PRAGMA 37 | #pragma alloc_text (PAGE, USBPcapGetTargetDevicePdo) 38 | #pragma alloc_text (PAGE, USBPcapGetNumberOfPorts) 39 | #if DBG 40 | #pragma alloc_text (PAGE, USBPcapPrintUSBPChildrenInformation) 41 | #endif 42 | #pragma alloc_text (PAGE, USBPcapGetDeviceUSBInfo) 43 | #pragma alloc_text (PAGE, USBPcapIsDeviceRootHub) 44 | #pragma alloc_text (PAGE, USBPcapGetHubInterfaces) 45 | #endif 46 | 47 | #endif /* USBPCAP_HELPER_FUNCTIONS_H */ 48 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapMain.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | 9 | /* Control device ID, used when creating roothub control devices 10 | * 11 | * Although this is 32-bit value (ULONG) we use only lower 16 bits 12 | * The reason for that is lack of InterlockedIncrement16 when building 13 | * for x86 processors 14 | */ 15 | ULONG volatile g_controlId; 16 | 17 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pUsRegPath) 18 | { 19 | UCHAR ucCnt = 0; 20 | 21 | /* Building for Windows 8 or newer. */ 22 | #if _MSC_VER >= 1800 23 | ExInitializeDriverRuntime(DrvRtPoolNxOptIn); 24 | #endif 25 | 26 | DkDbgStr("3"); 27 | 28 | pDrvObj->DriverUnload = DkUnload; 29 | pDrvObj->DriverExtension->AddDevice = AddDevice; 30 | 31 | for (ucCnt = 0; ucCnt <= IRP_MJ_MAXIMUM_FUNCTION; ucCnt++) 32 | { 33 | pDrvObj->MajorFunction[ucCnt] = DkDefault; 34 | } 35 | 36 | pDrvObj->MajorFunction[IRP_MJ_CREATE] = 37 | pDrvObj->MajorFunction[IRP_MJ_CLEANUP] = 38 | pDrvObj->MajorFunction[IRP_MJ_CLOSE] = DkCreateClose; 39 | 40 | pDrvObj->MajorFunction[IRP_MJ_READ] = 41 | pDrvObj->MajorFunction[IRP_MJ_WRITE] = DkReadWrite; 42 | 43 | pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DkDevCtl; 44 | 45 | pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DkInDevCtl; 46 | 47 | pDrvObj->MajorFunction[IRP_MJ_PNP] = DkPnP; 48 | 49 | pDrvObj->MajorFunction[IRP_MJ_POWER] = DkPower; 50 | 51 | g_controlId = (ULONG)0; 52 | 53 | return STATUS_SUCCESS; 54 | } 55 | 56 | VOID DkUnload(PDRIVER_OBJECT pDrvObj) 57 | { 58 | DkDbgStr("2"); 59 | } 60 | 61 | VOID DkCompleteRequest(PIRP pIrp, NTSTATUS resStat, UINT_PTR uiInfo) 62 | { 63 | pIrp->IoStatus.Status = resStat; 64 | pIrp->IoStatus.Information = uiInfo; 65 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); 66 | } 67 | 68 | NTSTATUS DkDefault(PDEVICE_OBJECT pDevObj, PIRP pIrp) 69 | { 70 | NTSTATUS ntStat = STATUS_SUCCESS; 71 | PDEVICE_EXTENSION pDevExt = NULL; 72 | PDEVICE_OBJECT pNextDevObj = NULL; 73 | 74 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 75 | 76 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 77 | if (!NT_SUCCESS(ntStat)) 78 | { 79 | DkDbgVal("Error acquire lock!", ntStat); 80 | DkCompleteRequest(pIrp, ntStat, 0); 81 | return ntStat; 82 | } 83 | 84 | #if DBG 85 | { 86 | PIO_STACK_LOCATION pStack; 87 | pStack = IoGetCurrentIrpStackLocation(pIrp); 88 | DkDbgVal("DkDefault", pStack->MajorFunction); 89 | } 90 | #endif 91 | 92 | pNextDevObj = pDevExt->pNextDevObj; 93 | 94 | if (pNextDevObj == NULL) 95 | { 96 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 97 | DkCompleteRequest(pIrp, ntStat, 0); 98 | } 99 | else 100 | { 101 | IoSkipCurrentIrpStackLocation(pIrp); 102 | ntStat = IoCallDriver(pNextDevObj, pIrp); 103 | } 104 | 105 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 106 | 107 | return ntStat; 108 | } 109 | 110 | NTSTATUS DkForwardAndWait(PDEVICE_OBJECT pNextDevObj, PIRP pIrp) 111 | { 112 | KEVENT kEvt; 113 | NTSTATUS ntStat = STATUS_SUCCESS; 114 | 115 | KeInitializeEvent(&kEvt, NotificationEvent, FALSE); 116 | 117 | IoCopyCurrentIrpStackLocationToNext(pIrp); 118 | IoSetCompletionRoutine(pIrp, 119 | (PIO_COMPLETION_ROUTINE) DkGenCompletion, 120 | (PVOID) &kEvt, TRUE, TRUE, TRUE); 121 | 122 | ntStat = IoCallDriver(pNextDevObj, pIrp); 123 | 124 | if (ntStat == STATUS_PENDING) 125 | { 126 | KeWaitForSingleObject(&kEvt, Executive, KernelMode, FALSE, NULL); 127 | ntStat = pIrp->IoStatus.Status; 128 | } 129 | 130 | return ntStat; 131 | } 132 | 133 | NTSTATUS DkGenCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx) 134 | { 135 | PKEVENT pEvt = NULL; 136 | 137 | pEvt = (PKEVENT) pCtx; 138 | if (pEvt == NULL) 139 | return STATUS_UNSUCCESSFUL; 140 | 141 | KeSetEvent(pEvt, IO_NO_INCREMENT, FALSE); 142 | 143 | return STATUS_MORE_PROCESSING_REQUIRED; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapMain.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | /************************************************************************** 8 | * 9 | * Define all structures and functions needed by this driver 10 | * 11 | **************************************************************************/ 12 | 13 | #ifndef USBPCAP_MAIN_H 14 | #define USBPCAP_MAIN_H 15 | 16 | #ifndef _PREFAST_ 17 | #pragma warning(disable:4068) 18 | #endif 19 | 20 | //////////////////////////////////////////////////////////// 21 | // WDK headers defined here 22 | // 23 | #include "Ntddk.h" 24 | #include "Usbdi.h" 25 | #include "Usbdlib.h" 26 | #include "Usbioctl.h" 27 | #include "Wdm.h" 28 | 29 | #define DKPORT_DEVNAME_STR L"\\Device\\DkSysPort" // Device name string 30 | #define DKPORT_DEVLINK_STR L"\\DosDevices\\Global\\DkSysPort" // Link name string 31 | #define DKPORT_MTAG (ULONG)'dk3A' // To tag memory allocation if any 32 | 33 | #include "USBPcapQueue.h" 34 | #include "include\USBPcap.h" 35 | 36 | #define USBPCAP_DEFAULT_SNAP_LEN 65535 37 | 38 | typedef struct _USBPCAP_ROOTHUB_DATA 39 | { 40 | /* Circular-Buffer related variables */ 41 | KSPIN_LOCK bufferLock; 42 | PVOID buffer; 43 | UINT32 bufferSize; 44 | UINT32 readOffset; 45 | UINT32 writeOffset; 46 | 47 | /* Snapshot length */ 48 | UINT32 snaplen; 49 | 50 | /* Address filter. See include\USBPcap.h for more information. */ 51 | USBPCAP_ADDRESS_FILTER filter; 52 | 53 | /* Reference count. To be used only with InterlockedXXX calls. */ 54 | volatile LONG refCount; 55 | 56 | USHORT busId; /* bus number */ 57 | PDEVICE_OBJECT controlDevice; 58 | } USBPCAP_ROOTHUB_DATA, *PUSBPCAP_ROOTHUB_DATA; 59 | 60 | typedef struct _DEVICE_DATA 61 | { 62 | /* pParentFlt and pNextParentFlt are NULL for RootHub */ 63 | PDEVICE_OBJECT pParentFlt; /* Parent filter object */ 64 | PDEVICE_OBJECT pNextParentFlt; /* Lower object of Parent filter */ 65 | 66 | /* Previous children. Used when receive IRP_MN_QUERY_DEVICE_RELATIONS */ 67 | PDEVICE_OBJECT *previousChildren; 68 | 69 | /* TRUE if the parentPort, isHub and deviceAddress are correct */ 70 | BOOLEAN properData; 71 | 72 | /* Parent port number the device is attached to */ 73 | ULONG parentPort; 74 | BOOLEAN isHub; /* TRUE if device is hub */ 75 | 76 | USHORT deviceAddress; 77 | 78 | KSPIN_LOCK tablesSpinLock; 79 | PRTL_GENERIC_TABLE endpointTable; 80 | PRTL_GENERIC_TABLE URBIrpTable; 81 | 82 | PUSBPCAP_ROOTHUB_DATA pRootData; 83 | 84 | /* Active configuration descriptor */ 85 | PUSB_CONFIGURATION_DESCRIPTOR descriptor; 86 | } USBPCAP_DEVICE_DATA, *PUSBPCAP_DEVICE_DATA; 87 | 88 | #define USBPCAP_MAGIC_CONTROL 0xBAD51571 89 | #define USBPCAP_MAGIC_ROOTHUB 0xBAD51572 90 | #define USBPCAP_MAGIC_DEVICE 0xBAD51573 91 | 92 | //////////////////////////////////////////////////////////// 93 | // Device extension structure for this object 94 | // 95 | typedef struct DEVICE_EXTENSION_Tag { 96 | UINT32 deviceMagic; /* determines device type */ 97 | PDEVICE_OBJECT pThisDevObj; /* This device object pointer */ 98 | PDEVICE_OBJECT pNextDevObj; /* Lower object of this object */ 99 | PDRIVER_OBJECT pDrvObj; /* Driver object pointer */ 100 | IO_REMOVE_LOCK removeLock; /* Remove lock for this object */ 101 | PIO_REMOVE_LOCK parentRemoveLock; /* Pointer to parent remove lock */ 102 | 103 | union 104 | { 105 | /* For USBPCAP_MAGIC_CONTROL */ 106 | struct 107 | { 108 | USHORT id; 109 | PDEVICE_OBJECT pRootHubObject; /* Root Hub object */ 110 | 111 | /* Pointer to handle that can control capture and read the data. 112 | * Only one such handle is allowed at a time. 113 | * However, we allow other callers to obtain handle that can be 114 | * used to call IOCTL_USBPCAP_GET_HUB_SYMLINK. 115 | * 116 | * This pointer is NULL if there isn't any open handle with the READ 117 | * permission. 118 | * This can be accessed only via InterlockedCompareExchangePointer(). 119 | */ 120 | PFILE_OBJECT pCaptureObject; 121 | 122 | LIST_ENTRY lePendIrp; // Used by I/O Cancel-Safe 123 | IO_CSQ ioCsq; // I/O Cancel-Safe object 124 | KSPIN_LOCK csqSpinLock; // Spin lock object for I/O Cancel-Safe 125 | } control; 126 | 127 | /* For USBPCAP_MAGIC_ROOTHUB or USBPCAP_MAGIC_DEVICE */ 128 | struct 129 | { 130 | PUSBPCAP_DEVICE_DATA pDeviceData; /* Device data */ 131 | } usb; 132 | } context; 133 | } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 134 | 135 | 136 | //////////////////////////////////////////////////////////// 137 | // These are "must have" routines for this driver 138 | // 139 | DRIVER_INITIALIZE DriverEntry; 140 | DRIVER_UNLOAD DkUnload; 141 | DRIVER_ADD_DEVICE AddDevice; 142 | 143 | //////////////////////////////////////////////////////////// 144 | // Some "standard" dispatch routines, used by this driver 145 | // 146 | __drv_dispatchType(IRP_MJ_CREATE) 147 | __drv_dispatchType(IRP_MJ_CLEANUP) 148 | __drv_dispatchType(IRP_MJ_CLOSE) DRIVER_DISPATCH DkCreateClose; 149 | 150 | __drv_dispatchType(IRP_MJ_READ) 151 | __drv_dispatchType(IRP_MJ_WRITE) DRIVER_DISPATCH DkReadWrite; 152 | 153 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH DkDevCtl; 154 | 155 | __drv_dispatchType(IRP_MJ_INTERNAL_DEVICE_CONTROL) DRIVER_DISPATCH DkInDevCtl; 156 | 157 | __drv_dispatchType(IRP_MJ_PNP) DRIVER_DISPATCH DkPnP; 158 | 159 | __drv_dispatchType(IRP_MJ_POWER) DRIVER_DISPATCH DkPower; 160 | 161 | __drv_dispatchType_other DRIVER_DISPATCH DkDefault; 162 | 163 | 164 | /////////////////////////////////////////////////////////////////////////// 165 | // Completion routine for internal device control request for target object 166 | // 167 | IO_COMPLETION_ROUTINE DkTgtInDevCtlCompletion; 168 | NTSTATUS DkTgtInDevCtlCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx); 169 | 170 | 171 | /////////////////////////////////////////////////////////////////////////// 172 | // General purpose I/O request completion routine 173 | // 174 | VOID DkCompleteRequest(PIRP pIrp, NTSTATUS resStat, UINT_PTR uiInfo); 175 | 176 | 177 | /////////////////////////////////////////////////////////////////////////// 178 | // Macro to show some "debugging messages" to a debugging tool 179 | // 180 | #define DkDbgStr(a) KdPrint(("USBPcap, %s(): %s\n", __FUNCTION__, a)) 181 | #define DkDbgVal(a, b) KdPrint(("USBPcap, %s(): %s ("#b" = 0x%X)\n", __FUNCTION__, a, b)) 182 | 183 | 184 | /////////////////////////////////////////////////////////////////////////// 185 | // General purpose routine to forward to next or lower driver and then 186 | // wait forever until lower driver finished it's job 187 | // 188 | NTSTATUS DkForwardAndWait(PDEVICE_OBJECT pNextDevObj, PIRP pIrp); 189 | 190 | 191 | /////////////////////////////////////////////////////////// 192 | // Completion routine for general purpose 193 | // 194 | IO_COMPLETION_ROUTINE DkGenCompletion; 195 | NTSTATUS DkGenCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx); 196 | 197 | 198 | /////////////////////////////////////////////////////////////////////////// 199 | // "Sub dispatch routines" for Hub filter object 200 | // 201 | NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp); 202 | NTSTATUS DkHubFltPnpHandleQryDevRels(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp); 203 | 204 | 205 | /////////////////////////////////////////////////////////////////////////// 206 | // "Sub dispatch routines" for target device 207 | // 208 | NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp); 209 | NTSTATUS DkTgtInDevCtl(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp); 210 | 211 | 212 | /////////////////////////////////////////////////////////////////////////// 213 | // Detach and delete hub filter objects routine 214 | // 215 | VOID DkDetachAndDeleteHubFilt(PDEVICE_EXTENSION pDevExt); 216 | 217 | 218 | /////////////////////////////////////////////////////////////////////////// 219 | // Create and attach target device filter routine 220 | // 221 | NTSTATUS DkCreateAndAttachTgt(PDEVICE_EXTENSION pDevExt, PDEVICE_OBJECT pTgtDevObj); 222 | 223 | 224 | /////////////////////////////////////////////////////////////////////////// 225 | // Detach and delete target device fitler routine 226 | // 227 | VOID DkDetachAndDeleteTgt(PDEVICE_EXTENSION pDevExt); 228 | 229 | 230 | /////////////////////////////////////////////////////////////////////////// 231 | // Get USB Hub device name 232 | // 233 | NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes); 234 | 235 | #endif /* USBPCAP_MAIN_H */ 236 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapPnP.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "USBPcapHelperFunctions.h" 9 | #include "USBPcapRootHubControl.h" 10 | 11 | NTSTATUS DkPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) 12 | { 13 | NTSTATUS ntStat = STATUS_SUCCESS; 14 | PDEVICE_EXTENSION pDevExt = NULL; 15 | PIO_STACK_LOCATION pStack = NULL; 16 | 17 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 18 | 19 | pStack = IoGetCurrentIrpStackLocation(pIrp); 20 | 21 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) 22 | { 23 | return DkHubFltPnP(pDevExt, pStack, pIrp); 24 | } 25 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 26 | { 27 | return DkTgtPnP(pDevExt, pStack, pIrp); 28 | } 29 | else 30 | { 31 | // Do nothing 32 | } 33 | 34 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 35 | if (!NT_SUCCESS(ntStat)) 36 | { 37 | DkDbgVal("Error acquire lock!", ntStat); 38 | DkCompleteRequest(pIrp, ntStat, 0); 39 | return ntStat; 40 | } 41 | 42 | if (pDevExt->pNextDevObj == NULL) 43 | { 44 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 45 | DkCompleteRequest(pIrp, ntStat, 0); 46 | } 47 | else 48 | { 49 | IoSkipCurrentIrpStackLocation(pIrp); 50 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 51 | } 52 | 53 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 54 | 55 | return ntStat; 56 | } 57 | 58 | 59 | NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) 60 | { 61 | NTSTATUS ntStat = STATUS_SUCCESS; 62 | 63 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 64 | if (!NT_SUCCESS(ntStat)) 65 | { 66 | DkDbgVal("Error lock!", ntStat); 67 | DkCompleteRequest(pIrp, ntStat, 0); 68 | return ntStat; 69 | } 70 | 71 | switch (pStack->MinorFunction) 72 | { 73 | case IRP_MN_START_DEVICE: 74 | DkDbgStr("IRP_MN_START_DEVICE"); 75 | 76 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); 77 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); 78 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 79 | 80 | return ntStat; 81 | 82 | case IRP_MN_REMOVE_DEVICE: 83 | { 84 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; 85 | DkDbgStr("IRP_MN_REMOVE_DEVICE"); 86 | 87 | IoSkipCurrentIrpStackLocation(pIrp); 88 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 89 | 90 | if (pDeviceData != NULL && 91 | pDeviceData->pRootData != NULL && 92 | pDeviceData->pRootData->controlDevice != NULL) 93 | { 94 | USBPcapDeleteRootHubControlDevice(pDeviceData->pRootData->controlDevice); 95 | } 96 | 97 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); 98 | 99 | DkDetachAndDeleteHubFilt(pDevExt); 100 | 101 | return ntStat; 102 | } 103 | 104 | case IRP_MN_QUERY_DEVICE_RELATIONS: 105 | DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); 106 | ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); 107 | 108 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 109 | return ntStat; 110 | 111 | default: 112 | DkDbgVal("", pStack->MinorFunction); 113 | break; 114 | 115 | } 116 | 117 | if (pDevExt->pNextDevObj == NULL) 118 | { 119 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 120 | DkCompleteRequest(pIrp, ntStat, 0); 121 | } 122 | else 123 | { 124 | IoSkipCurrentIrpStackLocation(pIrp); 125 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 126 | } 127 | 128 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 129 | 130 | return ntStat; 131 | } 132 | 133 | NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) 134 | { 135 | NTSTATUS ntStat = STATUS_SUCCESS; 136 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; 137 | 138 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 139 | if (!NT_SUCCESS(ntStat)) 140 | { 141 | DkDbgVal("Error lock!", ntStat); 142 | DkCompleteRequest(pIrp, ntStat, 0); 143 | return ntStat; 144 | } 145 | 146 | switch (pStack->MinorFunction) 147 | { 148 | case IRP_MN_START_DEVICE: 149 | /* IRP_MN_START_DEVICE is sent at PASSIVE_LEVEL */ 150 | DkDbgStr("IRP_MN_START_DEVICE"); 151 | 152 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); 153 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); 154 | 155 | if (NT_SUCCESS(USBPcapGetDeviceUSBInfo(pDevExt))) 156 | { 157 | DkDbgVal("Started device", pDeviceData->deviceAddress); 158 | } 159 | else 160 | { 161 | DkDbgStr("Failed to get info of started device"); 162 | } 163 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 164 | return ntStat; 165 | 166 | case IRP_MN_QUERY_DEVICE_RELATIONS: 167 | /* Keep track of, and create child devices only for hubs. 168 | * Do not create child filters for composite devices. 169 | */ 170 | if (pDeviceData->isHub == TRUE) 171 | { 172 | DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); 173 | ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); 174 | 175 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 176 | return ntStat; 177 | } 178 | else 179 | { 180 | break; 181 | } 182 | 183 | case IRP_MN_REMOVE_DEVICE: 184 | DkDbgStr("IRP_MN_REMOVE_DEVICE"); 185 | 186 | IoSkipCurrentIrpStackLocation(pIrp); 187 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 188 | 189 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); 190 | 191 | DkDetachAndDeleteTgt(pDevExt); 192 | 193 | return ntStat; 194 | 195 | 196 | default: 197 | DkDbgVal("", pStack->MinorFunction); 198 | break; 199 | 200 | } 201 | 202 | if (pDevExt->pNextDevObj == NULL) 203 | { 204 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 205 | DkCompleteRequest(pIrp, ntStat, 0); 206 | } 207 | else 208 | { 209 | IoSkipCurrentIrpStackLocation(pIrp); 210 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 211 | } 212 | 213 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 214 | 215 | return ntStat; 216 | } 217 | 218 | NTSTATUS DkHubFltPnpHandleQryDevRels(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) 219 | { 220 | NTSTATUS ntStat = STATUS_SUCCESS; 221 | PDEVICE_RELATIONS pDevRel = NULL; 222 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; 223 | ULONG i; 224 | 225 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 226 | if (!NT_SUCCESS(ntStat)) 227 | { 228 | DkDbgVal("Error lock!", ntStat); 229 | DkCompleteRequest(pIrp, ntStat, 0); 230 | return ntStat; 231 | } 232 | 233 | /* PnP manager sends this at PASSIVE_LEVEL */ 234 | switch (pStack->Parameters.QueryDeviceRelations.Type) 235 | { 236 | case BusRelations: 237 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: BusRelations"); 238 | 239 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); 240 | 241 | // After we forward the request, the bus driver have created or deleted 242 | // a child device object. When bus driver created one (or more), this is the PDO 243 | // of our target device, we create and attach a filter object to it. 244 | // Note that we only attach the last detected USB device on it's Hub. 245 | if (NT_SUCCESS(ntStat)) 246 | { 247 | pDevRel = (PDEVICE_RELATIONS) pIrp->IoStatus.Information; 248 | if (pDevRel) 249 | { 250 | USBPcapPrintUSBPChildrenInformation(pDevExt->pNextDevObj); 251 | 252 | DkDbgVal("Child(s) number", pDevRel->Count); 253 | 254 | for (i = 0; i < pDevRel->Count; i++) 255 | { 256 | PDEVICE_OBJECT *child; 257 | BOOLEAN found = FALSE; 258 | 259 | child = pDeviceData->previousChildren; 260 | 261 | /* Search only if there are any children */ 262 | if (child != NULL) 263 | { 264 | while (*child != NULL) 265 | { 266 | if (*child == pDevRel->Objects[i]) 267 | { 268 | found = TRUE; 269 | break; 270 | } 271 | child++; 272 | } 273 | } 274 | 275 | if (found == FALSE) 276 | { 277 | /* New device attached */ 278 | DkCreateAndAttachTgt(pDevExt, 279 | pDevRel->Objects[i]); 280 | } 281 | } 282 | 283 | /* Free old children information */ 284 | if (pDeviceData->previousChildren != NULL) 285 | { 286 | ExFreePool(pDeviceData->previousChildren); 287 | pDeviceData->previousChildren = NULL; 288 | } 289 | 290 | if (pDevRel->Count > 0) 291 | { 292 | PDEVICE_OBJECT *children; 293 | 294 | children = 295 | ExAllocatePoolWithTag(NonPagedPool, 296 | sizeof(PDEVICE_OBJECT) * 297 | (pDevRel->Count + 1), 298 | DKPORT_MTAG); 299 | 300 | if (children != NULL) 301 | { 302 | for (i = 0; i < pDevRel->Count; i++) 303 | { 304 | children[i] = pDevRel->Objects[i]; 305 | } 306 | 307 | /* NULL-terminate the array */ 308 | children[pDevRel->Count] = NULL; 309 | 310 | pDeviceData->previousChildren = children; 311 | } 312 | else 313 | { 314 | /* Failed to allocate memory. Just leave it 315 | * as it. In next pass we won't check for 316 | * new devices (probably will miss some). 317 | * But it's probably the best we can do. 318 | */ 319 | DkDbgStr("Failed to allocate previousChildren"); 320 | } 321 | } 322 | } 323 | } 324 | 325 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); 326 | 327 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 328 | 329 | return ntStat; 330 | 331 | 332 | case EjectionRelations: 333 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: EjectionRelations"); 334 | break; 335 | case RemovalRelations: 336 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: RemovalRelations"); 337 | break; 338 | case TargetDeviceRelation: 339 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TargetDeviceRelation"); 340 | break; 341 | case PowerRelations: 342 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: PowerRelations"); 343 | break; 344 | case SingleBusRelations: 345 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: SingleBusRelations"); 346 | break; 347 | case TransportRelations: 348 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TransportRelations"); 349 | break; 350 | 351 | default: 352 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: Unknown query relation type"); 353 | break; 354 | } 355 | 356 | if (pDevExt->pNextDevObj == NULL) 357 | { 358 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 359 | DkCompleteRequest(pIrp, ntStat, 0); 360 | } 361 | else 362 | { 363 | IoSkipCurrentIrpStackLocation(pIrp); 364 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); 365 | } 366 | 367 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 368 | 369 | return ntStat; 370 | } 371 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapPower.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | 9 | NTSTATUS DkPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) 10 | { 11 | NTSTATUS ntStat = STATUS_SUCCESS; 12 | PDEVICE_EXTENSION pDevExt = NULL; 13 | PIO_STACK_LOCATION pStack = NULL; 14 | PDEVICE_OBJECT pNextDevObj = NULL; 15 | PCHAR pTmp = NULL; 16 | 17 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 18 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 19 | if (!NT_SUCCESS(ntStat)) 20 | { 21 | DkDbgVal("Error acquire lock!", ntStat); 22 | DkCompleteRequest(pIrp, ntStat, 0); 23 | return ntStat; 24 | } 25 | 26 | pStack = IoGetCurrentIrpStackLocation(pIrp); 27 | 28 | pNextDevObj = pDevExt->pNextDevObj; 29 | 30 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) 31 | { 32 | pTmp = "Root Hub Filter"; 33 | } 34 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE) 35 | { 36 | pTmp = "Device"; 37 | } 38 | else 39 | { 40 | pTmp = "Global"; 41 | } 42 | 43 | switch (pStack->MinorFunction) 44 | { 45 | case IRP_MN_POWER_SEQUENCE: 46 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_POWER_SEQUENCE\n", __FUNCTION__, pTmp)); 47 | break; 48 | 49 | case IRP_MN_QUERY_POWER: 50 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_QUERY_POWER\n", __FUNCTION__, pTmp)); 51 | break; 52 | 53 | case IRP_MN_SET_POWER: 54 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_SET_POWER\n", __FUNCTION__, pTmp)); 55 | break; 56 | 57 | case IRP_MN_WAIT_WAKE: 58 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_WAIT_WAKE\n", __FUNCTION__, pTmp)); 59 | break; 60 | 61 | default: 62 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_XXX (0x%X)\n", __FUNCTION__, pTmp, pStack->MinorFunction)); 63 | break; 64 | } 65 | 66 | if (pDevExt->pNextDevObj == NULL) 67 | { 68 | ntStat = STATUS_INVALID_DEVICE_REQUEST; 69 | DkCompleteRequest(pIrp, ntStat, 0); 70 | return ntStat; 71 | } 72 | 73 | #if (NTDDI_VERSION < NTDDI_VISTA) 74 | PoStartNextPowerIrp(pIrp); 75 | #endif 76 | 77 | IoSkipCurrentIrpStackLocation(pIrp); 78 | 79 | #if (NTDDI_VERSION < NTDDI_VISTA) 80 | ntStat = PoCallDriver(pNextDevObj, pIrp); 81 | #else 82 | ntStat = IoCallDriver(pNextDevObj, pIrp); 83 | #endif 84 | 85 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); 86 | 87 | return ntStat; 88 | } 89 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapQueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "USBPcapQueue.h" 9 | 10 | VOID DkCsqInsertIrp(__in PIO_CSQ pCsq, __in PIRP pIrp) 11 | { 12 | PDEVICE_EXTENSION pDevExt = NULL; 13 | 14 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION, 15 | context.control.ioCsq); 16 | 17 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 18 | 19 | InsertTailList(&pDevExt->context.control.lePendIrp, 20 | &pIrp->Tail.Overlay.ListEntry); 21 | } 22 | 23 | VOID DkCsqRemoveIrp(__in PIO_CSQ pCsq, __in PIRP pIrp) 24 | { 25 | BOOLEAN bRes = FALSE; 26 | 27 | UNREFERENCED_PARAMETER(pCsq); 28 | 29 | bRes = RemoveEntryList(&pIrp->Tail.Overlay.ListEntry); 30 | } 31 | 32 | PIRP DkCsqPeekNextIrp(__in PIO_CSQ pCsq, __in PIRP pIrp, __in PVOID pCtx) 33 | { 34 | PDEVICE_EXTENSION pDevExt = NULL; 35 | PIRP pNextIrp = NULL; 36 | PLIST_ENTRY pNextList = NULL, pHeadList = NULL; 37 | PIO_STACK_LOCATION pStack = NULL; 38 | 39 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION, 40 | context.control.ioCsq); 41 | 42 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 43 | 44 | pHeadList = &pDevExt->context.control.lePendIrp; 45 | 46 | if (pIrp == NULL) 47 | { 48 | pNextList = pHeadList->Flink; 49 | } 50 | else 51 | { 52 | pNextList = pIrp->Tail.Overlay.ListEntry.Flink; 53 | } 54 | 55 | while (pNextList != pHeadList) 56 | { 57 | pNextIrp = CONTAINING_RECORD(pNextList, IRP, Tail.Overlay.ListEntry); 58 | pStack = IoGetCurrentIrpStackLocation(pNextIrp); 59 | if (pCtx) 60 | { 61 | if (pStack->FileObject == (PFILE_OBJECT)pCtx) 62 | { 63 | break; 64 | } 65 | } 66 | else 67 | { 68 | break; 69 | } 70 | pNextIrp = NULL; 71 | pNextList = pNextList->Flink; 72 | } 73 | 74 | return pNextIrp; 75 | } 76 | 77 | __drv_raisesIRQL(DISPATCH_LEVEL) 78 | __drv_maxIRQL(DISPATCH_LEVEL) 79 | VOID DkCsqAcquireLock(__in PIO_CSQ pCsq, __out __drv_out_deref(__drv_savesIRQL) PKIRQL pKIrql) 80 | { 81 | PDEVICE_EXTENSION pDevExt = NULL; 82 | 83 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION, 84 | context.control.ioCsq); 85 | 86 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 87 | 88 | KeAcquireSpinLock(&pDevExt->context.control.csqSpinLock, pKIrql); 89 | } 90 | 91 | __drv_requiresIRQL(DISPATCH_LEVEL) 92 | VOID DkCsqReleaseLock(__in PIO_CSQ pCsq, __in __drv_in(__drv_restoresIRQL) KIRQL kIrql) 93 | { 94 | PDEVICE_EXTENSION pDevExt = NULL; 95 | 96 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION, 97 | context.control.ioCsq); 98 | 99 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 100 | 101 | KeReleaseSpinLock(&pDevExt->context.control.csqSpinLock, kIrql); 102 | } 103 | 104 | VOID DkCsqCompleteCanceledIrp(__in PIO_CSQ pCsq, __in PIRP pIrp) 105 | { 106 | UNREFERENCED_PARAMETER(pCsq); 107 | 108 | pIrp->IoStatus.Status = STATUS_CANCELLED; 109 | pIrp->IoStatus.Information = 0; 110 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); 111 | } 112 | 113 | VOID DkCsqCleanUpQueue(PDEVICE_OBJECT pDevObj, PIRP pIrp) 114 | { 115 | PIO_STACK_LOCATION pStack = NULL; 116 | PDEVICE_EXTENSION pDevExt = NULL; 117 | PIRP pPendIrp = NULL; 118 | 119 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; 120 | 121 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 122 | 123 | pStack = IoGetCurrentIrpStackLocation(pIrp); 124 | 125 | while (TRUE) 126 | { 127 | pPendIrp = IoCsqRemoveNextIrp(&pDevExt->context.control.ioCsq, 128 | (PVOID)pStack->FileObject); 129 | if (pPendIrp == NULL) 130 | { 131 | break; 132 | } 133 | else 134 | { 135 | DkCsqCompleteCanceledIrp(&pDevExt->context.control.ioCsq, 136 | pPendIrp); 137 | } 138 | } 139 | } 140 | 141 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapQueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_QUEUE_H 8 | #define USBPCAP_QUEUE_H 9 | 10 | #include "Wdm.h" 11 | #include "include\USBPcap.h" 12 | 13 | __drv_raisesIRQL(DISPATCH_LEVEL) 14 | __drv_maxIRQL(DISPATCH_LEVEL) 15 | VOID DkCsqAcquireLock(__in PIO_CSQ pCsq, __out __drv_out_deref(__drv_savesIRQL) PKIRQL pKIrql); 16 | 17 | __drv_requiresIRQL(DISPATCH_LEVEL) 18 | VOID DkCsqReleaseLock(__in PIO_CSQ pCsq, __in __drv_in(__drv_restoresIRQL) KIRQL kIrql); 19 | 20 | IO_CSQ_INSERT_IRP DkCsqInsertIrp; 21 | IO_CSQ_REMOVE_IRP DkCsqRemoveIrp; 22 | IO_CSQ_PEEK_NEXT_IRP DkCsqPeekNextIrp; 23 | IO_CSQ_COMPLETE_CANCELED_IRP DkCsqCompleteCanceledIrp; 24 | 25 | VOID DkCsqCleanUpQueue(PDEVICE_OBJECT pDevObj, PIRP pIrp); 26 | 27 | #endif /* USBPCAP_QUEUE_H */ 28 | 29 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapRootHubControl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include 9 | #include "USBPcapRootHubControl.h" 10 | #include "Ntstrsafe.h" 11 | 12 | extern ULONG volatile g_controlId; 13 | 14 | #define NTNAME_PREFIX L"\\Device\\USBPcap" 15 | #define SYMBOLIC_PREFIX L"\\DosDevices\\USBPcap" 16 | #define MAX_CONTROL_ID L"65535" 17 | 18 | #define MAX_NTNAME_LEN (sizeof(NTNAME_PREFIX)+sizeof(MAX_CONTROL_ID)) 19 | #define MAX_SYMBOLIC_LEN (sizeof(SYMBOLIC_PREFIX)+sizeof(MAX_CONTROL_ID)) 20 | 21 | DECLARE_CONST_UNICODE_STRING( 22 | SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY, 23 | L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GX;;;WD)(A;;GX;;;RC)" 24 | ); 25 | 26 | __drv_requiresIRQL(PASSIVE_LEVEL) 27 | NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt, 28 | OUT PDEVICE_OBJECT *control, 29 | OUT USHORT *busId) 30 | { 31 | UNICODE_STRING ntDeviceName; 32 | UNICODE_STRING symbolicLinkName; 33 | PDEVICE_OBJECT controlDevice = NULL; 34 | PDEVICE_EXTENSION controlExt = NULL; 35 | NTSTATUS status; 36 | USHORT id; 37 | PWCHAR ntNameBuffer[MAX_NTNAME_LEN]; 38 | PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; 39 | 40 | ASSERT(hubExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB); 41 | 42 | /* Acquire the control device ID */ 43 | id = (USHORT) InterlockedIncrement(&g_controlId); 44 | 45 | ntDeviceName.Length = 0; 46 | ntDeviceName.MaximumLength = MAX_NTNAME_LEN; 47 | ntDeviceName.Buffer = (PWSTR)ntNameBuffer; 48 | 49 | symbolicLinkName.Length = 0; 50 | symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; 51 | symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; 52 | 53 | status = RtlUnicodeStringPrintf(&ntDeviceName, 54 | NTNAME_PREFIX L"%hu", id); 55 | if (!NT_SUCCESS(status)) 56 | { 57 | return status; 58 | } 59 | 60 | status = RtlUnicodeStringPrintf(&symbolicLinkName, 61 | SYMBOLIC_PREFIX L"%hu", id); 62 | if (!NT_SUCCESS(status)) 63 | { 64 | return status; 65 | } 66 | 67 | KdPrint(("Creating device %wZ (%wZ)\n", 68 | &ntDeviceName, &symbolicLinkName)); 69 | 70 | status = IoCreateDeviceSecure(hubExt->pDrvObj, 71 | sizeof(DEVICE_EXTENSION), 72 | &ntDeviceName, 73 | FILE_DEVICE_UNKNOWN, 74 | FILE_DEVICE_SECURE_OPEN, 75 | FALSE, /* Non-Exclusive device */ 76 | &SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY, 77 | NULL, 78 | &controlDevice); 79 | 80 | if (NT_SUCCESS(status)) 81 | { 82 | controlDevice->Flags |= DO_DIRECT_IO; 83 | 84 | status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName); 85 | 86 | if (!NT_SUCCESS(status)) 87 | { 88 | IoDeleteDevice(controlDevice); 89 | KdPrint(("IoCreateSymbolicLink failed %x\n", status)); 90 | return status; 91 | } 92 | 93 | controlExt = (PDEVICE_EXTENSION)controlDevice->DeviceExtension; 94 | controlExt->deviceMagic = USBPCAP_MAGIC_CONTROL; 95 | controlExt->pThisDevObj = controlDevice; 96 | controlExt->pNextDevObj = NULL; 97 | controlExt->pDrvObj = hubExt->pDrvObj; 98 | 99 | IoInitializeRemoveLock(&controlExt->removeLock, 0, 0, 0); 100 | controlExt->parentRemoveLock = &hubExt->removeLock; 101 | 102 | /* Initialize USBPcap control context */ 103 | controlExt->context.control.id = id; 104 | controlExt->context.control.pRootHubObject = hubExt->pThisDevObj; 105 | controlExt->context.control.pCaptureObject = NULL; 106 | 107 | 108 | KeInitializeSpinLock(&controlExt->context.control.csqSpinLock); 109 | InitializeListHead(&controlExt->context.control.lePendIrp); 110 | status = IoCsqInitialize(&controlExt->context.control.ioCsq, 111 | DkCsqInsertIrp, DkCsqRemoveIrp, 112 | DkCsqPeekNextIrp, DkCsqAcquireLock, 113 | DkCsqReleaseLock, DkCsqCompleteCanceledIrp); 114 | if (!NT_SUCCESS(status)) 115 | { 116 | DkDbgVal("Error initialize Cancel-safe queue!", status); 117 | goto End; 118 | } 119 | 120 | controlDevice->Flags &= ~DO_DEVICE_INITIALIZING; 121 | } 122 | else 123 | { 124 | KdPrint(("IoCreateDevice failed %x\n", status)); 125 | } 126 | 127 | End: 128 | if ((!NT_SUCCESS(status)) || (controlExt == NULL)) 129 | { 130 | if (controlDevice != NULL) 131 | { 132 | IoDeleteSymbolicLink(&symbolicLinkName); 133 | IoDeleteDevice(controlDevice); 134 | } 135 | } 136 | else 137 | { 138 | IoAcquireRemoveLock(controlExt->parentRemoveLock, NULL); 139 | *control = controlDevice; 140 | *busId = id; 141 | } 142 | 143 | return status; 144 | } 145 | 146 | 147 | VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice) 148 | { 149 | UNICODE_STRING symbolicLinkName; 150 | PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; 151 | USHORT id; 152 | PDEVICE_EXTENSION pDevExt; 153 | NTSTATUS status; 154 | 155 | pDevExt = ((PDEVICE_EXTENSION)controlDevice->DeviceExtension); 156 | 157 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); 158 | 159 | id = pDevExt->context.control.id; 160 | 161 | symbolicLinkName.Length = 0; 162 | symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; 163 | symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; 164 | 165 | status = RtlUnicodeStringPrintf(&symbolicLinkName, 166 | SYMBOLIC_PREFIX L"%hu", id); 167 | 168 | IoAcquireRemoveLock(&pDevExt->removeLock, NULL); 169 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, NULL); 170 | 171 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL); 172 | 173 | ASSERT(NT_SUCCESS(status)); 174 | if (NT_SUCCESS(status)) 175 | { 176 | IoDeleteSymbolicLink(&symbolicLinkName); 177 | IoDeleteDevice(controlDevice); 178 | } 179 | else 180 | { 181 | /* Very bad */ 182 | KdPrint(("Failed to init symbolic link name\n")); 183 | 184 | pDevExt->context.control.pRootHubObject = NULL; 185 | } 186 | } 187 | 188 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapRootHubControl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_ROOTHUB_CONTROL_H 8 | #define USBPCAP_ROOTHUB_CONTROL_H 9 | 10 | #include "USBPcapMain.h" 11 | 12 | NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt, 13 | OUT PDEVICE_OBJECT *control, 14 | OUT USHORT *busId); 15 | 16 | VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice); 17 | 18 | #endif /* USBPCAP_ROOTHUB_CONTROL_H */ 19 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapTables.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #include "USBPcapMain.h" 8 | #include "USBPcapTables.h" 9 | 10 | #define USBPCAP_TABLE_TAG ' BAT' 11 | 12 | typedef struct _USBPCAP_INTERNAL_ENDPOINT_INFO 13 | { 14 | RTL_SPLAY_LINKS links; 15 | LIST_ENTRY entry; 16 | USBPCAP_ENDPOINT_INFO info; 17 | } USBPCAP_INTERNAL_ENDPOINT_INFO, *PUSBPCAP_INTERNAL_ENDPOINT_INFO; 18 | 19 | VOID USBPcapRemoveEndpointInfo(IN PRTL_GENERIC_TABLE table, 20 | IN USBD_PIPE_HANDLE handle) 21 | { 22 | USBPCAP_INTERNAL_ENDPOINT_INFO info; 23 | BOOLEAN deleted; 24 | 25 | info.info.handle = handle; 26 | 27 | deleted = RtlDeleteElementGenericTable(table, &info); 28 | 29 | if (deleted == TRUE) 30 | { 31 | DkDbgVal("Successfully removed", handle); 32 | } 33 | else 34 | { 35 | DkDbgVal("Failed to remove", handle); 36 | } 37 | } 38 | 39 | VOID USBPcapAddEndpointInfo(IN PRTL_GENERIC_TABLE table, 40 | IN PUSBD_PIPE_INFORMATION pipeInfo, 41 | IN USHORT deviceAddress) 42 | { 43 | USBPCAP_INTERNAL_ENDPOINT_INFO info; 44 | BOOLEAN new; 45 | PUSBPCAP_INTERNAL_ENDPOINT_INFO pInfo; 46 | 47 | info.info.handle = pipeInfo->PipeHandle; 48 | info.info.type = pipeInfo->PipeType; 49 | info.info.endpointAddress = pipeInfo->EndpointAddress; 50 | info.info.deviceAddress = deviceAddress; 51 | 52 | pInfo = RtlInsertElementGenericTable(table, 53 | (PVOID)&info, 54 | sizeof(USBPCAP_INTERNAL_ENDPOINT_INFO), 55 | &new); 56 | 57 | if ((new == FALSE) && (pInfo != NULL)) 58 | { 59 | DkDbgStr("Element already exists in table, updating entry"); 60 | pInfo->info.type = pipeInfo->PipeType; 61 | pInfo->info.endpointAddress = pipeInfo->EndpointAddress; 62 | pInfo->info.deviceAddress = deviceAddress; 63 | } 64 | } 65 | 66 | /* 67 | * Retrieves the USBPCAP_ENDPOINT_INFO information from endpoint table. 68 | * 69 | * Returns NULL when no such endpoint information was found 70 | */ 71 | PUSBPCAP_ENDPOINT_INFO USBPcapGetEndpointInfo(IN PRTL_GENERIC_TABLE table, 72 | IN USBD_PIPE_HANDLE handle) 73 | { 74 | PUSBPCAP_INTERNAL_ENDPOINT_INFO pInfo; 75 | USBPCAP_INTERNAL_ENDPOINT_INFO info; 76 | 77 | info.info.handle = handle; 78 | 79 | pInfo = RtlLookupElementGenericTable(table, &info); 80 | 81 | if (pInfo == NULL) 82 | { 83 | return NULL; 84 | } 85 | 86 | return &pInfo->info; 87 | } 88 | 89 | RTL_GENERIC_FREE_ROUTINE USBPcapFreeRoutine; 90 | static VOID 91 | USBPcapFreeRoutine(IN PRTL_GENERIC_TABLE table, 92 | IN PVOID buffer) 93 | { 94 | ExFreePool(buffer); 95 | } 96 | 97 | RTL_GENERIC_ALLOCATE_ROUTINE USBPcapAllocateRoutine; 98 | static PVOID 99 | USBPcapAllocateRoutine(IN PRTL_GENERIC_TABLE table, 100 | IN CLONG size) 101 | { 102 | return ExAllocatePoolWithTag(NonPagedPool, 103 | size, 104 | USBPCAP_TABLE_TAG); 105 | } 106 | 107 | RTL_GENERIC_COMPARE_ROUTINE USBPcapCompareEndpointInfo; 108 | static RTL_GENERIC_COMPARE_RESULTS 109 | USBPcapCompareEndpointInfo(IN PRTL_GENERIC_TABLE table, 110 | IN PVOID first, 111 | IN PVOID second) 112 | { 113 | PUSBPCAP_INTERNAL_ENDPOINT_INFO left = first; 114 | PUSBPCAP_INTERNAL_ENDPOINT_INFO right = second; 115 | 116 | if (left->info.handle < right->info.handle) 117 | { 118 | return GenericLessThan; 119 | } 120 | else if (left->info.handle == right->info.handle) 121 | { 122 | return GenericEqual; 123 | } 124 | else 125 | { 126 | return GenericGreaterThan; 127 | } 128 | } 129 | 130 | VOID USBPcapFreeEndpointTable(IN PRTL_GENERIC_TABLE table) 131 | { 132 | PVOID element; 133 | 134 | DkDbgStr("Free endpoint data"); 135 | 136 | /* Delete all the elements from table */ 137 | while (NULL != (element = RtlGetElementGenericTable(table, 0))) 138 | { 139 | RtlDeleteElementGenericTable(table, element); 140 | } 141 | 142 | /* Delete table structure */ 143 | ExFreePool(table); 144 | } 145 | 146 | /* 147 | * Initializes endpoint table. 148 | * Returns NULL if there are no sufficient resources availble. 149 | * 150 | * Returned table must be freed using USBPcapFreeEndpointTable() 151 | */ 152 | PRTL_GENERIC_TABLE USBPcapInitializeEndpointTable(IN PVOID context) 153 | { 154 | PRTL_GENERIC_TABLE table; 155 | 156 | DkDbgStr("Initialize endpoint table"); 157 | 158 | table = (PRTL_GENERIC_TABLE) 159 | ExAllocatePoolWithTag(NonPagedPool, 160 | sizeof(RTL_GENERIC_TABLE), 161 | USBPCAP_TABLE_TAG); 162 | 163 | if (table == NULL) 164 | { 165 | DkDbgStr("Unable to allocate endpoint table"); 166 | return table; 167 | } 168 | 169 | RtlInitializeGenericTable(table, 170 | USBPcapCompareEndpointInfo, 171 | USBPcapAllocateRoutine, 172 | USBPcapFreeRoutine, 173 | context); 174 | 175 | return table; 176 | } 177 | 178 | BOOLEAN USBPcapRetrieveEndpointInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData, 179 | IN USBD_PIPE_HANDLE handle, 180 | PUSBPCAP_ENDPOINT_INFO pInfo) 181 | { 182 | KIRQL irql; 183 | PUSBPCAP_ENDPOINT_INFO info; 184 | BOOLEAN found = FALSE; 185 | 186 | KeAcquireSpinLock(&pDeviceData->tablesSpinLock, &irql); 187 | info = USBPcapGetEndpointInfo(pDeviceData->endpointTable, handle); 188 | if (info != NULL) 189 | { 190 | found = TRUE; 191 | memcpy(pInfo, info, sizeof(USBPCAP_ENDPOINT_INFO)); 192 | } 193 | KeReleaseSpinLock(&pDeviceData->tablesSpinLock, irql); 194 | 195 | if (found == TRUE) 196 | { 197 | DkDbgVal("Found endpoint info", handle); 198 | DkDbgVal("", pInfo->type); 199 | DkDbgVal("", pInfo->endpointAddress); 200 | DkDbgVal("", pInfo->deviceAddress); 201 | } 202 | else 203 | { 204 | DkDbgVal("Unable to find endpoint info", handle); 205 | } 206 | 207 | return found; 208 | } 209 | 210 | 211 | typedef struct _USBPCAP_INTERNAL_URB_IRP_INFO 212 | { 213 | RTL_SPLAY_LINKS links; 214 | LIST_ENTRY entry; 215 | USBPCAP_URB_IRP_INFO info; 216 | } USBPCAP_INTERNAL_URB_IRP_INFO, *PUSBPCAP_INTERNAL_URB_IRP_INFO; 217 | 218 | VOID USBPcapRemoveURBIRPInfo(IN PRTL_GENERIC_TABLE table, 219 | IN PIRP irp) 220 | { 221 | USBPCAP_INTERNAL_URB_IRP_INFO info; 222 | BOOLEAN deleted; 223 | 224 | info.info.irp = irp; 225 | 226 | deleted = RtlDeleteElementGenericTable(table, &info); 227 | 228 | if (deleted == TRUE) 229 | { 230 | DkDbgVal("Successfully removed irp from table", irp); 231 | } 232 | } 233 | 234 | VOID USBPcapAddURBIRPInfo(IN PRTL_GENERIC_TABLE table, 235 | IN PUSBPCAP_URB_IRP_INFO irpinfo) 236 | { 237 | USBPCAP_INTERNAL_URB_IRP_INFO info; 238 | BOOLEAN new; 239 | 240 | info.info = *irpinfo; 241 | 242 | RtlInsertElementGenericTable(table, 243 | (PVOID)&info, 244 | sizeof(USBPCAP_INTERNAL_URB_IRP_INFO), 245 | &new); 246 | 247 | if (new == FALSE) 248 | { 249 | DkDbgVal("Element already exists in table", irpinfo->irp); 250 | } 251 | } 252 | 253 | static PUSBPCAP_URB_IRP_INFO 254 | USBPcapGetURBIRPInfo(IN PRTL_GENERIC_TABLE table, 255 | IN PIRP irp) 256 | { 257 | PUSBPCAP_INTERNAL_URB_IRP_INFO pInfo; 258 | USBPCAP_INTERNAL_URB_IRP_INFO info; 259 | 260 | info.info.irp = irp; 261 | 262 | pInfo = RtlLookupElementGenericTable(table, &info); 263 | 264 | if (pInfo == NULL) 265 | { 266 | return NULL; 267 | } 268 | 269 | return &pInfo->info; 270 | } 271 | 272 | VOID USBPcapFreeURBIRPInfoTable(IN PRTL_GENERIC_TABLE table) 273 | { 274 | PVOID element; 275 | 276 | DkDbgStr("Free URB irp data"); 277 | 278 | /* Delete all the elements from table */ 279 | while (NULL != (element = RtlGetElementGenericTable(table, 0))) 280 | { 281 | RtlDeleteElementGenericTable(table, element); 282 | } 283 | 284 | /* Delete table structure */ 285 | ExFreePool(table); 286 | } 287 | 288 | RTL_GENERIC_COMPARE_ROUTINE USBPcapCompareURBIRPInfo; 289 | static RTL_GENERIC_COMPARE_RESULTS 290 | USBPcapCompareURBIRPInfo(IN PRTL_GENERIC_TABLE table, 291 | IN PVOID first, 292 | IN PVOID second) 293 | { 294 | PUSBPCAP_INTERNAL_URB_IRP_INFO left = first; 295 | PUSBPCAP_INTERNAL_URB_IRP_INFO right = second; 296 | 297 | if (left->info.irp < right->info.irp) 298 | { 299 | return GenericLessThan; 300 | } 301 | else if (left->info.irp == right->info.irp) 302 | { 303 | return GenericEqual; 304 | } 305 | else 306 | { 307 | return GenericGreaterThan; 308 | } 309 | } 310 | 311 | PRTL_GENERIC_TABLE USBPcapInitializeURBIRPInfoTable(IN PVOID context) 312 | { 313 | PRTL_GENERIC_TABLE table; 314 | 315 | DkDbgStr("Initialize URB irp table"); 316 | 317 | table = (PRTL_GENERIC_TABLE) 318 | ExAllocatePoolWithTag(NonPagedPool, 319 | sizeof(RTL_GENERIC_TABLE), 320 | USBPCAP_TABLE_TAG); 321 | 322 | if (table == NULL) 323 | { 324 | DkDbgStr("Unable to allocate URB irp table"); 325 | return table; 326 | } 327 | 328 | RtlInitializeGenericTable(table, 329 | USBPcapCompareURBIRPInfo, 330 | USBPcapAllocateRoutine, 331 | USBPcapFreeRoutine, 332 | context); 333 | 334 | return table; 335 | } 336 | 337 | /* Obtains the URB IRP info from the URB IRP info table 338 | * 339 | * If the value was present in the table, it will be removed. 340 | * 341 | * Returns TRUE if irp was found in table, FALSE otherwise. 342 | */ 343 | BOOLEAN USBPcapObtainURBIRPInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData, 344 | IN PIRP irp, 345 | PUSBPCAP_URB_IRP_INFO pInfo) 346 | { 347 | KIRQL irql; 348 | PUSBPCAP_URB_IRP_INFO info; 349 | BOOLEAN found = FALSE; 350 | 351 | KeAcquireSpinLock(&pDeviceData->tablesSpinLock, &irql); 352 | info = USBPcapGetURBIRPInfo(pDeviceData->URBIrpTable, irp); 353 | if (info != NULL) 354 | { 355 | found = TRUE; 356 | memcpy(pInfo, info, sizeof(USBPCAP_URB_IRP_INFO)); 357 | USBPcapRemoveURBIRPInfo(pDeviceData->URBIrpTable, irp); 358 | } 359 | KeReleaseSpinLock(&pDeviceData->tablesSpinLock, irql); 360 | 361 | if (found == TRUE) 362 | { 363 | DkDbgVal("Found URB irp info", irp); 364 | DkDbgVal("", pInfo->function); 365 | } 366 | 367 | return found; 368 | } 369 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapTables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_TABLES_H 8 | #define USBPCAP_TABLES_H 9 | 10 | #include "USBPcapMain.h" 11 | 12 | typedef struct _USBPCAP_ENDPOINT_INFO 13 | { 14 | /* handle is used as a key */ 15 | USBD_PIPE_HANDLE handle; 16 | USBD_PIPE_TYPE type; 17 | UCHAR endpointAddress; 18 | USHORT deviceAddress; 19 | } USBPCAP_ENDPOINT_INFO, *PUSBPCAP_ENDPOINT_INFO; 20 | 21 | VOID USBPcapRemoveEndpointInfo(IN PRTL_GENERIC_TABLE table, 22 | IN USBD_PIPE_HANDLE handle); 23 | VOID USBPcapAddEndpointInfo(IN PRTL_GENERIC_TABLE table, 24 | IN PUSBD_PIPE_INFORMATION pipeInfo, 25 | IN USHORT deviceAddress); 26 | 27 | PUSBPCAP_ENDPOINT_INFO USBPcapGetEndpointInfo(IN PRTL_GENERIC_TABLE table, 28 | IN USBD_PIPE_HANDLE handle); 29 | 30 | VOID USBPcapFreeEndpointTable(IN PRTL_GENERIC_TABLE table); 31 | PRTL_GENERIC_TABLE USBPcapInitializeEndpointTable(IN PVOID context); 32 | 33 | 34 | BOOLEAN USBPcapRetrieveEndpointInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData, 35 | IN USBD_PIPE_HANDLE handle, 36 | PUSBPCAP_ENDPOINT_INFO pInfo); 37 | 38 | typedef struct _USBPCAP_URB_IRP_INFO 39 | { 40 | /* IRP pointer is used as a key */ 41 | PIRP irp; 42 | /* Data collected when the URB was travelling from FDO to PDO */ 43 | LARGE_INTEGER timestamp; 44 | USBD_STATUS status; 45 | USHORT function; 46 | UCHAR info; /* I/O Request info */ 47 | USHORT bus; /* bus (RootHub) number */ 48 | USHORT device; /* device address */ 49 | } USBPCAP_URB_IRP_INFO, *PUSBPCAP_URB_IRP_INFO; 50 | 51 | VOID USBPcapRemoveURBIRPInfo(IN PRTL_GENERIC_TABLE table, 52 | IN PIRP irp); 53 | VOID USBPcapAddURBIRPInfo(IN PRTL_GENERIC_TABLE table, 54 | IN PUSBPCAP_URB_IRP_INFO irpinfo); 55 | 56 | VOID USBPcapFreeURBIRPInfoTable(IN PRTL_GENERIC_TABLE table); 57 | PRTL_GENERIC_TABLE USBPcapInitializeURBIRPInfoTable(IN PVOID context); 58 | 59 | BOOLEAN USBPcapObtainURBIRPInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData, 60 | IN PIRP irp, 61 | PUSBPCAP_URB_IRP_INFO pInfo); 62 | 63 | #endif /* USBPCAP_TABLES_H */ 64 | -------------------------------------------------------------------------------- /USBPcapDriver/USBPcapURB.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: GPL-2.0 5 | */ 6 | 7 | #ifndef USBPCAP_URB_H 8 | #define USBPCAP_URB_H 9 | 10 | #include "USBPcapMain.h" 11 | 12 | VOID USBPcapAnalyzeURB(PIRP pIrp, PURB pUrb, BOOLEAN post, 13 | PUSBPCAP_DEVICE_DATA pDeviceData); 14 | 15 | #endif /* USBPCAP_URB_H */ 16 | -------------------------------------------------------------------------------- /USBPcapDriver/include/USBPcap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 Tomasz Moń 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #ifndef USBPCAP_H 8 | #define USBPCAP_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | 16 | typedef struct 17 | { 18 | UINT32 size; 19 | } USBPCAP_IOCTL_SIZE, *PUSBPCAP_IOCTL_SIZE; 20 | 21 | #pragma pack(push) 22 | #pragma pack(1) 23 | /* USBPCAP_ADDRESS_FILTER is parameter structure to IOCTL_USBPCAP_START_FILTERING. */ 24 | typedef struct _USBPCAP_ADDRESS_FILTER 25 | { 26 | /* Individual device filter bit array. USB standard assigns device 27 | * numbers 1 to 127 (0 is reserved for initial configuration). 28 | * 29 | * If address 0 bit is set, then we will automatically capture from 30 | * newly connected devices. 31 | * 32 | * addresses[0] - 0 - 31 33 | * addresses[1] - 32 - 63 34 | * addresses[2] - 64 - 95 35 | * addresses[3] - 96 - 127 36 | */ 37 | UINT32 addresses[4]; 38 | 39 | /* Filter all devices */ 40 | BOOLEAN filterAll; 41 | } USBPCAP_ADDRESS_FILTER, *PUSBPCAP_ADDRESS_FILTER; 42 | #pragma pack(pop) 43 | 44 | #define IOCTL_USBPCAP_SETUP_BUFFER \ 45 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) 46 | 47 | #define IOCTL_USBPCAP_START_FILTERING \ 48 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 49 | 50 | #define IOCTL_USBPCAP_STOP_FILTERING \ 51 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 52 | 53 | #define IOCTL_USBPCAP_GET_HUB_SYMLINK \ 54 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) 55 | 56 | #define IOCTL_USBPCAP_SET_SNAPLEN_SIZE \ 57 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_READ_ACCESS) 58 | 59 | /* USB packets, beginning with a USBPcap header */ 60 | #define DLT_USBPCAP 249 61 | 62 | #pragma pack(push, 1) 63 | typedef struct pcap_hdr_s { 64 | UINT32 magic_number; /* magic number */ 65 | UINT16 version_major; /* major version number */ 66 | UINT16 version_minor; /* minor version number */ 67 | INT32 thiszone; /* GMT to local correction */ 68 | UINT32 sigfigs; /* accuracy of timestamps */ 69 | UINT32 snaplen; /* max length of captured packets, in octets */ 70 | UINT32 network; /* data link type */ 71 | } pcap_hdr_t; 72 | #pragma pack(pop) 73 | 74 | #pragma pack(push, 1) 75 | typedef struct pcaprec_hdr_s { 76 | UINT32 ts_sec; /* timestamp seconds */ 77 | UINT32 ts_usec; /* timestamp microseconds */ 78 | UINT32 incl_len; /* number of octets of packet saved in file */ 79 | UINT32 orig_len; /* actual length of packet */ 80 | } pcaprec_hdr_t; 81 | #pragma pack(pop) 82 | 83 | /* All multi-byte fields are stored in .pcap file in little endian */ 84 | 85 | #define USBPCAP_TRANSFER_ISOCHRONOUS 0 86 | #define USBPCAP_TRANSFER_INTERRUPT 1 87 | #define USBPCAP_TRANSFER_CONTROL 2 88 | #define USBPCAP_TRANSFER_BULK 3 89 | #define USBPCAP_TRANSFER_IRP_INFO 0xFE 90 | #define USBPCAP_TRANSFER_UNKNOWN 0xFF 91 | 92 | /* info byte fields: 93 | * bit 0 (LSB) - when 1: PDO -> FDO 94 | * bits 1-7: Reserved 95 | */ 96 | #define USBPCAP_INFO_PDO_TO_FDO (1 << 0) 97 | 98 | #pragma pack(push, 1) 99 | typedef struct 100 | { 101 | USHORT headerLen; /* This header length */ 102 | UINT64 irpId; /* I/O Request packet ID */ 103 | USBD_STATUS status; /* USB status code (on return from host controller) */ 104 | USHORT function; /* URB Function */ 105 | UCHAR info; /* I/O Request info */ 106 | 107 | USHORT bus; /* bus (RootHub) number */ 108 | USHORT device; /* device address */ 109 | UCHAR endpoint; /* endpoint number and transfer direction */ 110 | UCHAR transfer; /* transfer type */ 111 | 112 | UINT32 dataLength;/* Data length */ 113 | } USBPCAP_BUFFER_PACKET_HEADER, *PUSBPCAP_BUFFER_PACKET_HEADER; 114 | #pragma pack(pop) 115 | 116 | /* USBPcap versions before 1.5.0.0 recorded control transactions as two 117 | * or three pcap packets: 118 | * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data 119 | * * Optional USBPCAP_CONTROL_STAGE_DATA with either DATA OUT or IN 120 | * * USBPCAP_CONTROL_STAGE_STATUS without data on IRP completion 121 | * 122 | * Such capture was considered unnecessary complex. Due to that, since 123 | * USBPcap 1.5.0.0, the control transactions are recorded as two packets: 124 | * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data and 125 | * optional DATA OUT 126 | * * USBPCAP_CONTROL_STAGE_COMPLETE without payload or with the DATA IN 127 | * 128 | * The merit behind this change was that Wireshark dissector, since the 129 | * very first time when Wireshark understood USBPcap format, was really 130 | * expecting the USBPCAP_CONTROL_STAGE_SETUP to contain SETUP + DATA OUT. 131 | * Even when they Wireshark doesn't recognize USBPCAP_CONTROL_STAGE_COMPLETE 132 | * it will still process the payload correctly. 133 | */ 134 | #define USBPCAP_CONTROL_STAGE_SETUP 0 135 | #define USBPCAP_CONTROL_STAGE_DATA 1 136 | #define USBPCAP_CONTROL_STAGE_STATUS 2 137 | #define USBPCAP_CONTROL_STAGE_COMPLETE 3 138 | 139 | #pragma pack(push, 1) 140 | typedef struct 141 | { 142 | USBPCAP_BUFFER_PACKET_HEADER header; 143 | UCHAR stage; 144 | } USBPCAP_BUFFER_CONTROL_HEADER, *PUSBPCAP_BUFFER_CONTROL_HEADER; 145 | #pragma pack(pop) 146 | 147 | /* Note about isochronous packets: 148 | * packet[x].length, packet[x].status and errorCount are only relevant 149 | * when USBPCAP_INFO_PDO_TO_FDO is set 150 | * 151 | * packet[x].length is not used for isochronous OUT transfers. 152 | * 153 | * Buffer data is attached to: 154 | * * for isochronous OUT transactions (write to device) 155 | * Requests (USBPCAP_INFO_PDO_TO_FDO is not set) 156 | * * for isochronous IN transactions (read from device) 157 | * Responses (USBPCAP_INFO_PDO_TO_FDO is set) 158 | */ 159 | #pragma pack(push, 1) 160 | typedef struct 161 | { 162 | ULONG offset; 163 | ULONG length; 164 | USBD_STATUS status; 165 | } USBPCAP_BUFFER_ISO_PACKET, *PUSBPCAP_BUFFER_ISO_PACKET; 166 | #pragma pack(pop) 167 | 168 | #pragma pack(push, 1) 169 | typedef struct 170 | { 171 | USBPCAP_BUFFER_PACKET_HEADER header; 172 | ULONG startFrame; 173 | ULONG numberOfPackets; 174 | ULONG errorCount; 175 | USBPCAP_BUFFER_ISO_PACKET packet[1]; 176 | } USBPCAP_BUFFER_ISOCH_HEADER, *PUSBPCAP_BUFFER_ISOCH_HEADER; 177 | #pragma pack(pop) 178 | 179 | #ifdef __cplusplus 180 | } 181 | #endif 182 | 183 | #endif /* USBPCAP_H */ 184 | -------------------------------------------------------------------------------- /USBPcapDriver/makefile.inc: -------------------------------------------------------------------------------- 1 | _LNG=$(LANGUAGE) 2 | _INX=. 3 | STAMP=stampinf -f $@ -a $(_BUILDARCH) -v $(USBPCAP_VERSION) 4 | 5 | $(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx 6 | copy $(_INX)\$(@B).inx $@ 7 | $(STAMP) 8 | -------------------------------------------------------------------------------- /appveyor_build.bat: -------------------------------------------------------------------------------- 1 | call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64 2 | 3 | set USBPcap_catalog=USBPcapamd64.cat 4 | set USBPcap_OS=8_X64 5 | set USBPcap_builddir=x64\Win8Release\dirs-Package 6 | 7 | cd %~dp0 8 | CALL config.bat 9 | 10 | ::Delete the release directory if it already exists 11 | if exist %USBPcap_builddir% RMDIR /S /Q %USBPcap_builddir% 12 | 13 | Nmake2MsBuild dirs 14 | MSBuild dirs.sln /p:Configuration="Win8 Release" 15 | 16 | if errorlevel 1 goto error 17 | 18 | ::Consider the build a success even if test signing fails 19 | ::Actual signing that matter is release one which for obvious reasons 20 | ::is done using non-public keys 21 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %USBPcap_builddir%\USBPcap.sys 22 | Inf2cat.exe /driver:%USBPcap_builddir%\ /os:%USBPcap_OS% 23 | 24 | copy %USBPcap_builddir%\USBPcap.sys %2 25 | copy %USBPcap_builddir%\USBPcap.inf %2 26 | copy %USBPcap_builddir%\%USBPcap_catalog% %2 27 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %2\%USBPcap_catalog% 28 | 29 | exit /B 0 30 | 31 | :error 32 | echo ===== BUILD FAILED! ===== 33 | exit /B 1 34 | -------------------------------------------------------------------------------- /build_release.bat: -------------------------------------------------------------------------------- 1 | cd %~dp0 2 | 3 | ::Remove the Release directory if it exists 4 | if exist Release RMDIR /S /Q Release 5 | 6 | ::build for Windows 7 7 | mkdir Release\Windows7\x86 8 | mkdir Release\Windows7\x64 9 | 10 | call cmd.exe /c driver_build.bat x86 WIN7 Release\Windows7\x86 11 | call cmd.exe /c driver_build.bat x64 WIN7 Release\Windows7\x64 12 | 13 | ::Copy the USBPcapCMD.exe 14 | copy USBPcapCMD\objfre_win7_x86\i386\USBPcapCMD.exe Release\USBPcapCMD_x86.exe 15 | copy USBPcapCMD\objfre_win7_amd64\amd64\USBPcapCMD.exe Release\USBPcapCMD_x64.exe 16 | 17 | ::Build for Windows 8 18 | mkdir Release\Windows8\x86 19 | mkdir Release\Windows8\x64 20 | 21 | call cmd.exe /c driver_build_win8.bat x86 Release\Windows8\x86 22 | call cmd.exe /c driver_build_win8.bat x86_amd64 Release\Windows8\x64 23 | 24 | ::Create Attestation signing cabinet files 25 | call cmd.exe /c driver_attestation_signing.bat 26 | @echo off 27 | echo Attestation signing packages should be available in disk1 directory 28 | echo Sign these files with EV Code Signing certificate and upload them 29 | echo to Hardware Dev Center Dashboard 30 | echo After you are ready, unzip signed files to Release directory 31 | @echo on 32 | pause 33 | 34 | ::Build finished 35 | 36 | @echo off 37 | echo Build finished. Please check if Release directory contains all required 38 | echo files. Now you can build the installer using nsis\USBPcap.nsi 39 | @echo on 40 | 41 | pause 42 | -------------------------------------------------------------------------------- /certificates/Certum Trusted Network CA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFTTCCAzWgAwIBAgIKYTvHkQAAAAAANDANBgkqhkiG9w0BAQUFADB/MQswCQYD 3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe 4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv 5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUyMDE1MzRaFw0yMTA0 6 | MTUyMDI1MzRaMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hu 7 | b2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo 8 | b3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwggEiMA0G 9 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj+32jcrrC8MkUh/VrAU7hbkAHum0n 10 | XX/3Wy2zWsdRX6ukMqZhh7ZuD4bSMAKX+NdpV6EYOV1qZHnGAVmsPDFKOHzSBNJL 11 | KOggXzsHosxNc9vzrk/HVtVap5aJ+vOraNQjhlknzwknvKxucoMcMHLf4KLp0uF0 12 | dRm9Kp57FVQEG9dDOa1VKMXiGrv0wOSuOEkzzHaFnzlF0qSe8hKMUfh85C1/9axf 13 | 6xafsS3RusyRQndMJcmQOG/b8Mz7jh6XWT7VYE7mBSjtSXkTS7pI2y/5ctM5yv4f 14 | 2DRy9bRAzzEBw+zeES0XXR+4UNFeGadp3gczKMpQlfmnVMtUhlBFqflJAgMBAAGj 15 | gcswgcgwEQYDVR0gBAowCDAGBgRVHSAAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 16 | BBYEFAh2zcsH/yT2xc3tu5C84oQ3RnX3MAsGA1UdDwQEAwIBhjAfBgNVHSMEGDAW 17 | gBRi+wohW39DbhHaCVRQa/XSlnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8v 18 | Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2Rl 19 | VmVyaWZSb290LmNybDANBgkqhkiG9w0BAQUFAAOCAgEAQZ8SFg7t7iSR/l1fEKCX 20 | qHSeDczzEVFjEipbuV3Hr6xaolwAAstyjg2SJbZSJlO+PHeiwoyAidhBGFcauNBQ 21 | V8Mo5/rQRIBOfokzKG86R+9eIx7yev46KhnerWsaKEd4bpu/63NnWJonGdjrXD0I 22 | WGBinVkUz552s8/ZYq97cqyA+eAVq5x6XEsccIPbcJQRe9IqTHc03DbMzUbUCxmM 23 | CfZhCt5IHJs//wtD1/EBgGGr2nDPp4RErLMcziYw9cpfaWc1g26jiIwPuJOb1lsG 24 | FeZLfblQqwngeyvrTBpruhzKeRvFn4G95EPwLeGV1aFmB2zm5UVuBgvb9bxDlbiK 25 | pQVV5ZZorB0x2zgEvBw9thl10bWAKoIeOFxGdiVsTYt0g1RDded7s5W/7hNgng7N 26 | +8r3OipSoKYlSXoXGTrolB8sggQDXqlRPO9Sb3tDztorgbR/2hosYmXR7Cg3gjAU 27 | MZ0Vvf+syIslbkG9HyN0G+P8+Uvi60bmgVFTDslKhHiN7Ki4D41Mf+D2sNLFOLJP 28 | gsQQ/oe4jsa2sPh8Eqe0g038HotqW/nVZHk+0eN+GvbIHlnbTcpgXFd+olh37PoF 29 | JgAyp/b/E06Y2G9bQ0yzNuQlvNk7nzjgDum+gebJHw8CL406Eoiojhux53aRPhje 30 | NhIo/vdmVXxb1GRIdFLDIYk= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /certificates/Readme.txt: -------------------------------------------------------------------------------- 1 | Following certificates were created with following commands: 2 | MakeCert -r -pe -ss PrivateCertStore -n "CN=USBPcapTest" -sv USBPcapTestCert.pvk USBPcapTestCert.cer 3 | pvk2pfx -pvk USBPcapTestCert.pvk -spc USBPcapTestCert.cer -pfx USBPcapTestCert.pfx 4 | 5 | Password: USBPcap 6 | 7 | 8 | WARNING: Prior to installing the test-signed driver you need to run: 9 | CertMgr /add USBPcapTestCert.cer /s /r localMachine root 10 | CertMgr /add USBPcapTestCert.cer /s /r localMachine trustedpublisher 11 | Bcdedit.exe -set TESTSIGNING ON 12 | -------------------------------------------------------------------------------- /certificates/USBPcapTestCert.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.cer -------------------------------------------------------------------------------- /certificates/USBPcapTestCert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.pfx -------------------------------------------------------------------------------- /certificates/USBPcapTestCert.pvk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.pvk -------------------------------------------------------------------------------- /certificates/VeriSign Class 3 Public Primary Certification Authority - G5.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFmjCCA4KgAwIBAgIKYRmT5AAAAAAAHDANBgkqhkiG9w0BAQUFADB/MQswCQYD 3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe 4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv 5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTAyMjIxOTI1MTdaFw0yMTAy 6 | MjIxOTM1MTdaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIElu 7 | Yy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShj 8 | KSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkx 9 | RTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm 10 | aWNhdGlvbiBBdXRob3JpdHkgLSBHNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC 11 | AQoCggEBAK8kCAgpejWeYAyq50s7Ttx8vDxFHLsr4P4pAvlXCKNkhRUn9fGtyDGJ 12 | XSLoKqqmQrOP+LlVt7G3S7P+j34HV+zvQ9tmYhVhz2ANpNje+ODDYgg9VBPrScpZ 13 | VIUm5SuPG5/r9aGRwjNJ2ENjalJL0o/ocFFN0Ylpe8dw9rPcEnTbe11LVtOWvxV3 14 | obD0oiXyrxySZxjl9AYE75C55ADk3Tq1Gf8CuvQ87uCL6zeL7PTXrPL28D2v3XWR 15 | MxkdHEDLdCQZIZPZFP6sKlLHj9UESeSNY0eIPGmDy/5HvSt+T8WVrg6d1NFDwGdz 16 | 4xQIfuU/n3O4MwrPXT80h5aK7lPoJRUCAwEAAaOByzCByDARBgNVHSAECjAIMAYG 17 | BFUdIAAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwHQYDVR0OBBYEFH/T 18 | ZafC3ey78DAJ80M5+gKvMzEzMB8GA1UdIwQYMBaAFGL7CiFbf0NuEdoJVFBr9dKW 19 | cfGeMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w 20 | a2kvY3JsL3Byb2R1Y3RzL01pY3Jvc29mdENvZGVWZXJpZlJvb3QuY3JsMA0GCSqG 21 | SIb3DQEBBQUAA4ICAQCBKoIWjDRnK+UD6zR7jKKjUIr0VYbxHoyOrn3uAxnOcpUY 22 | SK1iEf0g/T9HBgFa4uBvjBUsTjxqUGwLNqPPeg2cQrxc+BnVYONp5uIjQWeMaIN2 23 | K4+Toyq1f75Z+6nJsiaPyqLzghuYPpGVJ5eGYe5bXQdrzYao4mWAqOIV4rK+IwVq 24 | ugzzR5NNrKSMB3k5wGESOgUNiaPsn1eJhPvsynxHZhSR2LYPGV3muEqsvEfIcUOW 25 | 5jIgpdx3hv0844tx23ubA/y3HTJk6xZSoEOj+i6tWZJOfMfyM0JIOFE6fDjHGyQi 26 | KEAeGkYfF9sY9/AnNWy4Y9nNuWRdK6Ve78YptPLH+CHMBLpX/QG2q8Zn+efTmX/0 27 | 9SL6cvX9/zocQjqh+YAYpe6NHNRmnkUB/qru//sXjzD38c0pxZ3stdVJAD2FuMu7 28 | kzonaknAMK5myfcjKDJ2+aSDVshIzlqWqqDMDMR/tI6Xr23jVCfDn4bA1uRzCJcF 29 | 29BUYl4DSMLVn3+nZozQnbBP1NOYX0t6yX+yKVLQEoDHD1S2HmfNxqBsEQOE00h1 30 | 5yr+sDtuCjqma3aZBaPxd2hhMxRHBvxTf1K9khRcSiRqZ4yvjZCq0PZ5IRuTJnzD 31 | zh69iDiSrkXGGWpJULMF+K5ZN4pqJQOUsVmBUOi6g4C3IzX0drlnHVkYrSCNlA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /config.bat: -------------------------------------------------------------------------------- 1 | ::Change code page to UTF-8 when building official release and your cerificate 2 | ::has non-ASCII characters in name 3 | ::Do not change it by default as this seems to cause problems with AppVeyor 4 | ::chcp 65001 5 | 6 | ::Use SignTool from Windows Driver Kit 7 | set _USBPCAP_SIGNTOOL="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" 8 | 9 | ::Development build - on x64 you have to use TESTSIGNING to load driver 10 | set _USBPCAP_SIGN_OPTS_SHA256=sign /as /v /fd sha256 /f %~dp0certificates\USBPcapTestCert.pfx /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td sha256 11 | ::Release build. Keep in mind you would have to replace the certificate 12 | ::name with your personal/company certificate. 13 | ::Also, you might want to use different cross-certificate depending on the 14 | ::certificate authority that you got the certificate from 15 | :: 16 | ::For more information check out the Kernel-Mode Code Signing Walkthrough 17 | ::http://msdn.microsoft.com/en-us/library/windows/hardware/gg487328.aspx 18 | ::set _USBPCAP_SIGN_OPTS_SHA256=sign /as /v /fd sha256 /ac "%~dp0certificates\Certum Trusted Network CA.crt" /n "Tomasz" /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td sha256 19 | 20 | ::_USBPCAP_VERSION specifies version of the installer. 21 | ::To update driver version edit USBPcapDriver\USBPcap.rc and 22 | ::USBPcapDriver\SOURCES 23 | set _USBPCAP_VERSION="1.5.4.0" 24 | -------------------------------------------------------------------------------- /dirs: -------------------------------------------------------------------------------- 1 | dirs = USBPcapCMD USBPcapDriver 2 | -------------------------------------------------------------------------------- /driver_attestation_signing.bat: -------------------------------------------------------------------------------- 1 | cd %~dp0 2 | CALL config.bat 3 | 4 | CALL :dequote _USBPCAP_VERSION 5 | 6 | ::Prepare driver package for Windows 10 Attestation signing 7 | ::According to documentation Attestation signed driver works 8 | ::only on Windows 10, hence we cannot use exactly the same 9 | ::driver file for Windows 8 and Windows 10 10 | ::However, we use the same source, only the signing differ 11 | CALL :CreateCab x86 12 | CALL :CreateCab x64 13 | Goto :eof 14 | 15 | :DeQuote 16 | for /f "delims=" %%A in ('echo %%%1%%') do set %1=%%~A 17 | Goto :eof 18 | 19 | :CreateCab 20 | ( 21 | echo .OPTION EXPLICIT ; Generate errors 22 | echo .Set CabinetFileCountThreshold=0 23 | echo .Set FolderFileCountThreshold=0 24 | echo .Set FolderSizeThreshold=0 25 | echo .Set MaxCabinetSize=0 26 | echo .Set MaxDiskFileCount=0 27 | echo .Set MaxDiskSize=0 28 | echo .Set CompressionType=MSZIP 29 | echo .Set Cabinet=on 30 | echo .Set Compress=on 31 | echo .Set CabinetNameTemplate=USBPcap-%_USBPCAP_VERSION%-%1.cab 32 | echo .Set DestinationDir=Windows10%1 33 | echo %~dp0Release\Windows8\%1\USBPcap.inf 34 | echo %~dp0Release\Windows8\%1\USBPcap.sys 35 | echo %~dp0Release\Windows8\%1\USBPcap.pdb 36 | ) > Windows10-%1.ddf 37 | MakeCab /f Windows10-%1.ddf 38 | Goto :eof 39 | -------------------------------------------------------------------------------- /driver_build.bat: -------------------------------------------------------------------------------- 1 | ::Parameters: 2 | :: %1 - x86 or x64 3 | :: %2 - WIN7 4 | :: %3 - target directory 5 | 6 | call C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ fre %1 %2 7 | 8 | cd %~dp0 9 | CALL config.bat 10 | 11 | if "%_BUILDARCH%"=="x86" ( 12 | set USBPcap_arch=i386 13 | set USBPcap_catalog=USBPcapx86.cat 14 | if "%DDK_TARGET_OS%"=="WinLH" ( 15 | set USBPcap_OS=Vista_X86 16 | ) else if "%DDK_TARGET_OS%"=="WinXP" ( 17 | set USBPcap_OS=XP_X86 18 | ) else if "%DDK_TARGET_OS%"=="Win7" ( 19 | set USBPcap_OS=7_X86 20 | ) 21 | ) else ( 22 | set USBPcap_arch=amd64 23 | set USBPcap_catalog=USBPcapamd64.cat 24 | if "%DDK_TARGET_OS%"=="WinLH" ( 25 | set USBPcap_OS=Vista_X64 26 | ) else if "%DDK_TARGET_OS%"=="WinNET" ( 27 | set USBPcap_OS=XP_X64 28 | ) else if "%DDK_TARGET_OS%"=="Win7" ( 29 | set USBPcap_OS=7_X64 30 | ) 31 | ) 32 | 33 | cd %~dp0 34 | CALL config.bat 35 | 36 | build -ceZg 37 | if exist build%BUILD_ALT_DIR%.err goto error 38 | 39 | ::Sign the USBPcapCMD.exe, it is not critical so do not fail on error 40 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapCMD\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcapCMD.exe 41 | 42 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys 43 | if errorlevel 1 goto error 44 | 45 | Inf2cat.exe /driver:USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\ /os:%USBPcap_OS% 46 | 47 | goto end 48 | 49 | :error 50 | echo ===== BUILD FAILED! ===== 51 | pause 52 | exit /B 1 53 | 54 | :end 55 | 56 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys %3 57 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.pdb %3 58 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.inf %3 59 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\%USBPcap_catalog% %3 60 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %3\%USBPcap_catalog% 61 | if errorlevel 1 goto error 62 | 63 | exit /B 0 64 | -------------------------------------------------------------------------------- /driver_build_win7_64bit.bat: -------------------------------------------------------------------------------- 1 | call C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ fre x64 WIN7 2 | 3 | if "%_BUILDARCH%"=="x86" ( 4 | set USBPcap_arch=i386 5 | if "%DDK_TARGET_OS%"=="WinLH" ( 6 | set USBPcap_OS=Vista_X86 7 | ) else if "%DDK_TARGET_OS%"=="WinXP" ( 8 | set USBPcap_OS=XP_X86 9 | ) else if "%DDK_TARGET_OS%"=="Win7" ( 10 | set USBPcap_OS=7_X86 11 | ) 12 | ) else ( 13 | set USBPcap_arch=amd64 14 | if "%DDK_TARGET_OS%"=="WinLH" ( 15 | set USBPcap_OS=Vista_X64 16 | ) else if "%DDK_TARGET_OS%"=="WinXP" ( 17 | set USBPcap_OS=XP_X64 18 | ) else if "%DDK_TARGET_OS%"=="Win7" ( 19 | set USBPcap_OS=7_X64 20 | ) 21 | ) 22 | 23 | cd %~dp0 24 | CALL config.bat 25 | 26 | build -ceZg 27 | if exist build%BUILD_ALT_DIR%.err goto error 28 | 29 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys 30 | if errorlevel 1 goto error 31 | 32 | Inf2cat.exe /driver:USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\ /os:%USBPcap_OS% 33 | 34 | goto end 35 | 36 | :error 37 | echo ===== BUILD FAILED! ===== 38 | cd %~dp0 39 | pause 40 | exit /B 1 41 | 42 | :end 43 | cd %~dp0 44 | pause 45 | exit /B 0 46 | -------------------------------------------------------------------------------- /driver_build_win8.bat: -------------------------------------------------------------------------------- 1 | ::Parameters: 2 | :: %1 - x86 or x86_amd64 3 | 4 | call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" %1 5 | 6 | if "%1"=="x86" ( 7 | set USBPcap_catalog=USBPcapx86.cat 8 | set USBPcap_OS=8_X86 9 | set USBPcap_builddir=USBPcapDriver\Win8Release\x86 10 | ) else ( 11 | set USBPcap_catalog=USBPcapamd64.cat 12 | set USBPcap_OS=8_X64 13 | set USBPcap_builddir=USBPcapDriver\Win8Release\x64 14 | ) 15 | 16 | cd %~dp0 17 | CALL config.bat 18 | 19 | ::Delete the release directory if it already exists 20 | if exist %USBPcap_builddir% RMDIR /S /Q %USBPcap_builddir% 21 | 22 | Nmake2MsBuild dirs 23 | MSBuild dirs.sln /p:Configuration="Win8 Release" 24 | 25 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %USBPcap_builddir%\USBPcap.sys 26 | if errorlevel 1 goto error 27 | 28 | Inf2cat.exe /driver:%USBPcap_builddir%\ /os:%USBPcap_OS% 29 | 30 | goto end 31 | 32 | :error 33 | echo ===== BUILD FAILED! ===== 34 | pause 35 | exit /B 1 36 | 37 | :end 38 | copy %USBPcap_builddir%\USBPcap.sys %2 39 | copy %USBPcap_builddir%\USBPcap.pdb %2 40 | copy %USBPcap_builddir%\USBPcap.inf %2 41 | copy %USBPcap_builddir%\%USBPcap_catalog% %2 42 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %2\%USBPcap_catalog% 43 | if errorlevel 1 goto error 44 | 45 | exit /B 0 46 | -------------------------------------------------------------------------------- /nsis/SysRestore.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/nsis/SysRestore.dll -------------------------------------------------------------------------------- /nsis/USBPcap.nsi: -------------------------------------------------------------------------------- 1 | !include "LogicLib.nsh" 2 | !include "x64.nsh" 3 | !include "WinVer.nsh" 4 | !include "FileFunc.nsh" 5 | !include "WordFunc.nsh" 6 | 7 | !addplugindir . 8 | 9 | !macro __MOZ__WinVer_DefineOSTests WinVer 10 | !insertmacro __WinVer_DefineOSTest AtLeast ${WinVer} "" 11 | !insertmacro __WinVer_DefineOSTest AtMost ${WinVer} "" 12 | !insertmacro __WinVer_DefineOSTest Is ${WinVer} "" 13 | !macroend 14 | 15 | !ifndef WINVER_8 16 | !define WINVER_8 0x06020000 ;6.02.???? 17 | !insertmacro __MOZ__WinVer_DefineOSTests 8 18 | !endif 19 | 20 | !define VERSION $%_USBPCAP_VERSION% 21 | 22 | Name "USBPcap ${VERSION}" 23 | 24 | RequestExecutionLevel admin 25 | 26 | !ifdef INNER 27 | !echo "Inner invocation" ; just to see what's going on 28 | OutFile "$%TEMP%\tempinstaller.exe" ; not really important where this is 29 | SetCompress off ; for speed 30 | !else 31 | !echo "Outer invocation" 32 | 33 | ; Call makensis again, defining INNER. This writes an installer for us 34 | ; which, when it is invoked, will just write the uninstaller to some 35 | ; location, and then exit. 36 | ; Be sure to substitute the name of this script here. 37 | 38 | !system "$\"${NSISDIR}\makensis$\" /DINNER USBPcap.nsi" = 0 39 | 40 | ; So now run that installer we just created as %TEMP%\tempinstaller.exe. 41 | ; Since it calls quit the return value isn't zero. 42 | 43 | !system "$%TEMP%\tempinstaller.exe" = 2 44 | 45 | ; That will have written an uninstaller binary for us. Now we sign it 46 | ; with your favourite code signing tool. 47 | !system '$%_USBPCAP_SIGNTOOL% $%_USBPCAP_SIGN_OPTS_SHA256% $%TEMP%\Uninstall.exe' = 0 48 | 49 | ; Good. Now we can carry on writing the real installer. 50 | 51 | outFile "USBPcapSetup-${VERSION}.exe" 52 | SetCompressor /SOLID lzma 53 | 54 | VIAddVersionKey "ProductName" "USBPcap" 55 | VIAddVersionKey "ProductVersion" "${VERSION}" 56 | VIAddVersionKey "LegalCopyright" "(c) 2013-2020 Tomasz Mon" 57 | VIAddVersionKey "FileDescription" "USBPcap installer" 58 | VIAddVersionKey "FileVersion" "${VERSION}" 59 | VIProductVersion "${VERSION}" 60 | !endif 61 | 62 | PageEx license 63 | LicenseText "USBPcap Driver license" 64 | LicenseData gpl-2.0.txt 65 | LicenseForceSelection checkbox 66 | PageExEnd 67 | 68 | PageEx license 69 | LicenseText "USBPcapCMD license" 70 | LicenseData bsd-2clause.txt 71 | LicenseForceSelection checkbox 72 | PageExEnd 73 | 74 | Page components 75 | Page directory 76 | Page instfiles 77 | UninstPage uninstConfirm 78 | UninstPage instfiles 79 | 80 | Function EnsureSHA2IsSupported 81 | push $0 82 | push $1 83 | push $2 84 | 85 | StrCpy $2 0 86 | 87 | System::Call "kernel32::LoadLibrary(t 'wintrust.dll') p .r1" 88 | ${If} $1 != 0 89 | System::Call "kernel32::GetProcAddress(p r1, t 'CryptCATAdminAcquireContext2') p .r2" 90 | System::Call "kernel32::FreeLibrary(p r1)" 91 | ${EndIf} 92 | 93 | ${If} $2 == 0 94 | MessageBox MB_OK|MB_ICONEXCLAMATION "Windows 7 without updates does not support SHA-2.$\nInstall KB3033929 or KB4474419 before installing USBPcap." 95 | Quit 96 | ${EndIf} 97 | 98 | pop $2 99 | pop $1 100 | pop $0 101 | FunctionEnd 102 | 103 | Function .onInit 104 | !ifdef INNER 105 | ; If INNER is defined, then we aren't supposed to do anything except write 106 | ; out the installer. This is better than processing a command line option 107 | ; as it means this entire code path is not present in the final (real) 108 | ; installer. 109 | 110 | WriteUninstaller "$%TEMP%\Uninstall.exe" 111 | Quit ; just bail out quickly when running the "inner" installer 112 | !endif 113 | 114 | ; It is no longer possible to get SHA-1 Kernel Mode Code Signing certificate 115 | ; Windows 8 and later contain SHA-2 support built-in. 116 | ; Windows 7 supports SHA-2 when KB3033929 or KB4474419 is installed. 117 | ; Older Windows versions do not support SHA-2. 118 | ${IfNot} ${AtLeastWin7} 119 | MessageBox MB_OK "Unsupported Windows version. Only Windows 7, 8 and 10 are supported.$\nThe last USBPcap release supporting Windows XP and Vista was 1.5.3.0." 120 | Quit 121 | ${EndIf} 122 | 123 | ${IfNot} ${AtLeastWin8} 124 | Call EnsureSHA2IsSupported 125 | ${EndIf} 126 | 127 | ${If} ${RunningX64} 128 | ${DisableX64FSRedirection} 129 | SetRegView 64 130 | ${EndIf} 131 | ReadRegStr $R0 HKLM \ 132 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 133 | "UninstallString" 134 | ${If} ${RunningX64} 135 | ${EnableX64FSRedirection} 136 | ${EndIf} 137 | StrCmp $R0 "" not_installed 138 | 139 | MessageBox MB_OK|MB_ICONEXCLAMATION \ 140 | "USBPcap is already installed. Please uninstall it first.$\r$\nMake sure to reboot after uninstall." 141 | Abort 142 | 143 | not_installed: 144 | ; Check if USBPcap driver service is pending removal 145 | ClearErrors 146 | ReadRegDWORD $0 HKLM "SYSTEM\CurrentControlSet\services\USBPcap" "DeleteFlag" 147 | IfErrors no_removal_pending 148 | ; DeleteFlag exists. On Windows 7 it seems that it will result in USBPcap 149 | ; service getting removed after reboot no matter what DeleteFlag value is 150 | MessageBox MB_OK|MB_ICONEXCLAMATION \ 151 | "USBPcap driver service is pending removal.$\r$\nReboot is required before installation." 152 | Abort 153 | 154 | no_removal_pending: 155 | ${If} ${RunningX64} 156 | StrCpy $INSTDIR "$PROGRAMFILES64\USBPcap" 157 | ${Else} 158 | StrCpy $INSTDIR "$PROGRAMFILES\USBPcap" 159 | ${EndIf} 160 | 161 | ; Windows To Go is not supported 162 | ClearErrors 163 | ReadRegDWORD $0 HKLM "SYSTEM\CurrentControlSet\Control" "PortableOperatingSystem" 164 | ${If} $0 <> 0 165 | MessageBox MB_OK "USBPcap cannot be installed on Windows To Go." 166 | Quit 167 | ${EndIf} 168 | 169 | Pop $R0 170 | FunctionEnd 171 | 172 | InstType "Full" 173 | InstType "Minimal" 174 | 175 | Section "USBPcap Driver" SEC_USBPCAPDRIVER 176 | SectionIn RO 177 | SetOutPath "$INSTDIR" 178 | 179 | Var /GLOBAL restore_point_success 180 | !define RESTORE_POINT_NAME_INSTALL "USBPcap ${VERSION} installation" 181 | 182 | DetailPrint "Start setting system restore point: ${RESTORE_POINT_NAME_INSTALL}" 183 | SysRestore::StartRestorePoint /NOUNLOAD "${RESTORE_POINT_NAME_INSTALL}" 184 | Pop $0 185 | ${If} $0 != 0 186 | DetailPrint "Error occurred when starting setting system restore point, return value=|$0|" 187 | ${Else} 188 | StrCpy $restore_point_success "yes" 189 | ${Endif} 190 | 191 | ${If} ${RunningX64} 192 | ${DisableX64FSRedirection} 193 | SetRegView 64 194 | ${EndIf} 195 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 196 | "DisplayName" "USBPcap ${VERSION}" 197 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 198 | "DisplayVersion" "${VERSION}" 199 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 200 | "UninstallString" "$\"$INSTDIR\Uninstall.exe$\"" 201 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 202 | "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S" 203 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 204 | "URLInfoAbout" "http://desowin.org/usbpcap" 205 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 206 | "Publisher" "Tomasz Mon" 207 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 208 | "NoModify" 1 209 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \ 210 | "NoRepair" 1 211 | 212 | ${If} ${RunningX64} 213 | ${If} ${AtLeastWin10} 214 | File "..\Release\Windows10\x64\USBPcap.inf" 215 | File "..\Release\Windows10\x64\USBPcap.sys" 216 | File "..\Release\Windows10\x64\USBPcapamd64.cat" 217 | ${ElseIf} ${AtLeastWin8} 218 | File "..\Release\Windows8\x64\USBPcap.inf" 219 | File "..\Release\Windows8\x64\USBPcap.sys" 220 | File "..\Release\Windows8\x64\USBPcapamd64.cat" 221 | ${Else} 222 | ; Assume 64-bit Windows 7 223 | File "..\Release\Windows7\x64\USBPcap.inf" 224 | File "..\Release\Windows7\x64\USBPcap.sys" 225 | File "..\Release\Windows7\x64\USBPcapamd64.cat" 226 | ${EndIf} 227 | ${Else} 228 | ${If} ${AtLeastWin10} 229 | File "..\Release\Windows10\x86\USBPcap.inf" 230 | File "..\Release\Windows10\x86\USBPcap.sys" 231 | File "..\Release\Windows10\x86\USBPcapx86.cat" 232 | ${ElseIf} ${AtLeastWin8} 233 | File "..\Release\Windows8\x86\USBPcap.inf" 234 | File "..\Release\Windows8\x86\USBPcap.sys" 235 | File "..\Release\Windows8\x86\USBPcapx86.cat" 236 | ${Else} 237 | ; Assume 32-bit Windows 7 238 | File "..\Release\Windows7\x86\USBPcap.inf" 239 | File "..\Release\Windows7\x86\USBPcap.sys" 240 | File "..\Release\Windows7\x86\USBPcapx86.cat" 241 | ${EndIf} 242 | ${EndIf} 243 | 244 | ExecWait '$SYSDIR\RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 .\USBPcap.inf' 245 | 246 | ${If} ${RunningX64} 247 | ${EnableX64FSRedirection} 248 | ${EndIf} 249 | 250 | !ifndef INNER 251 | ; this packages the signed uninstaller 252 | File $%TEMP%\Uninstall.exe 253 | !endif 254 | SectionEnd 255 | 256 | Section "USBPcapCMD" SEC_USBPCAPCMD 257 | SectionIn 1 RO 258 | SetOutPath "$INSTDIR" 259 | 260 | ${If} ${RunningX64} 261 | File /oname=USBPcapCMD.exe "..\Release\USBPcapCMD_x64.exe" 262 | ${Else} 263 | File /oname=USBPcapCMD.exe "..\Release\USBPcapCMD_x86.exe" 264 | ${EndIf} 265 | 266 | ${If} $restore_point_success == "yes" 267 | DetailPrint "Finish setting system restore point: ${RESTORE_POINT_NAME_INSTALL}" 268 | SysRestore::FinishRestorePoint /NOUNLOAD 269 | Pop $0 270 | ${If} $0 != 0 271 | DetailPrint "Error occurred when finishing setting system restore point, return value=|$0|" 272 | ${EndIf} 273 | ${EndIf} 274 | SectionEnd 275 | 276 | Section "Detect USB 3.0" SEC_USB3 277 | SectionIn 1 278 | 279 | Exec '"$INSTDIR\USBPcapCMD.exe" -I' 280 | SectionEnd 281 | 282 | Function .onSelChange 283 | ${If} ${SectionIsSelected} ${SEC_USB3} 284 | !insertmacro SetSectionFlag ${SEC_USBPCAPCMD} ${SF_RO} 285 | !insertmacro SelectSection ${SEC_USBPCAPCMD} 286 | ${Else} 287 | !insertmacro ClearSectionFlag ${SEC_USBPCAPCMD} ${SF_RO} 288 | ${EndIf} 289 | FunctionEnd 290 | 291 | !ifdef INNER 292 | Section "Uninstall" 293 | ${If} ${RunningX64} 294 | ${DisableX64FSRedirection} 295 | SetRegView 64 296 | ${EndIf} 297 | SetOutPath "$INSTDIR" 298 | ExecWait '$SYSDIR\RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultUninstall 132 .\USBPcap.inf' 299 | 300 | Delete $INSTDIR\Uninstall.exe 301 | Delete $INSTDIR\USBPcap.inf 302 | Delete $INSTDIR\USBPcap.sys 303 | ${If} ${RunningX64} 304 | Delete $INSTDIR\USBPcapamd64.cat 305 | ${Else} 306 | Delete $INSTDIR\USBPcapx86.cat 307 | ${EndIf} 308 | 309 | IfFileExists $INSTDIR\USBPcapCMD.exe CMDExists PastCMDCheck 310 | CMDExists: 311 | Delete $INSTDIR\USBPcapCMD.exe 312 | PastCMDCheck: 313 | RMDir /REBOOTOK $INSTDIR 314 | 315 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" 316 | ${If} ${RunningX64} 317 | ${EnableX64FSRedirection} 318 | ${EndIf} 319 | SectionEnd 320 | !endif 321 | 322 | -------------------------------------------------------------------------------- /nsis/bsd-2clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2020, Tomasz Mon 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | 10 | -------------------------------------------------------------------------------- /nsis/build_installer.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | CALL ..\config.bat 4 | 5 | set nsis_compiler= 6 | 7 | if defined NSIS_HOME ( 8 | if exist "%NSIS_HOME%\makensis.exe" ( 9 | set "nsis_compiler=%NSIS_HOME%" 10 | ) 11 | ) 12 | 13 | if %PROCESSOR_ARCHITECTURE%==x86 ( 14 | Set RegQry=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NSIS 15 | ) else ( 16 | Set RegQry=HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\NSIS 17 | ) 18 | 19 | if not defined nsis_compiler ( 20 | for /F "tokens=2*" %%a in ('reg query %RegQry% /v InstallLocation ^|findstr InstallLocation') do set nsis_compiler=%%b 21 | ) 22 | 23 | if not defined nsis_compiler ( 24 | for %%X in (makensis.exe) do (set nsis_compiler=%%~dp$PATH:X) 25 | ) 26 | 27 | if defined nsis_compiler ( 28 | "%nsis_compiler%\makensis.exe" %~dp0USBPcap.nsi 29 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapSetup-%_USBPCAP_VERSION%.exe 30 | pause 31 | ) else ( 32 | echo "Error, build system cannot find NSIS! Please reinstall it, add makensis.exe to your PATH, or defined the NSIS_HOME environment variable." 33 | ) 34 | -------------------------------------------------------------------------------- /nsis/gpl-2.0.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | -------------------------------------------------------------------------------- /wix/USBPcap.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | NOT USBPCAP_NSIS 29 | 30 | %PROCESSOR_ARCHITECTURE ~= "x86" AND %PROCESSOR_ARCHITEW6432 <> "amd64" 31 | 32 | NOT VersionNT < 501 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | VersionNT >= 501 AND VersionNT < 600 45 | 46 | 47 | 48 | 49 | 50 | VersionNT = 600 51 | 52 | 53 | 54 | 55 | 56 | VersionNT = 601 57 | 58 | 59 | 60 | 61 | 62 | VersionNT >= 602 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | NOT Installed AND 93 | NOT Installed 94 | REMOVE="ALL" 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /wix/build.bat: -------------------------------------------------------------------------------- 1 | set _WIX_PATH="C:\Program Files (x86)\WiX Toolset v3.9\bin" 2 | 3 | cd %~dp0 4 | 5 | %_WIX_PATH%\candle.exe -nologo USBPcap.wxs -out USBPcap-x86.wixobj -ext WixUIExtension -arch x86 -dPlatform="x86" 6 | if errorlevel 1 goto error 7 | %_WIX_PATH%\light.exe -nologo USBPcap-x86.wixobj -out USBPcap-x86.msi -ext WixUIExtension 8 | if errorlevel 1 goto error 9 | pause 10 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcap-x86.msi 11 | 12 | %_WIX_PATH%\candle.exe -nologo USBPcap.wxs -out USBPcap-x64.wixobj -ext WixUIExtension -arch x64 -dPlatform="x64" 13 | if errorlevel 1 goto error 14 | %_WIX_PATH%\light.exe -nologo USBPcap-x64.wixobj -out USBPcap-x64.msi -ext WixUIExtension 15 | if errorlevel 1 goto error 16 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcap-x64.msi 17 | 18 | :error 19 | echo ===== Failed to build installer! ===== 20 | pause 21 | exit /B 1 22 | 23 | :end 24 | echo ==== Success! ==== 25 | pause 26 | exit /B 0 27 | --------------------------------------------------------------------------------