├── .gitignore ├── EtwCommon.h ├── EtwConsumer.cpp ├── EtwController.cpp ├── LICENSE.txt ├── NdisCapPacket.cpp ├── NdisCapPacket.def ├── NdisCapPacket.sln ├── NdisCapPacket.vcxproj ├── NdisCapPacket.vcxproj.filters ├── Packet32.h ├── README.md ├── dllmain.cpp ├── stdafx.cpp ├── stdafx.h └── targetver.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ## Ignore Visual Studio temporary files, build results, and 3 | ## files generated by popular Visual Studio add-ons. 4 | 5 | # User-specific files 6 | *.suo 7 | *.user 8 | *.userosscache 9 | *.sln.docstates 10 | 11 | # User-specific files (MonoDevelop/Xamarin Studio) 12 | *.userprefs 13 | 14 | # Build results 15 | [Dd]ebug/ 16 | [Dd]ebugPublic/ 17 | [Rr]elease/ 18 | [Rr]eleases/ 19 | x64/ 20 | x86/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | [Ll]og/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | *.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.pfx 193 | *.publishsettings 194 | node_modules/ 195 | orleans.codegen.cs 196 | 197 | # Since there are multiple workflows, uncomment next line to ignore bower_components 198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 199 | #bower_components/ 200 | 201 | # RIA/Silverlight projects 202 | Generated_Code/ 203 | 204 | # Backup & report files from converting an old project file 205 | # to a newer Visual Studio version. Backup files are not needed, 206 | # because we have git ;-) 207 | _UpgradeReport_Files/ 208 | Backup*/ 209 | UpgradeLog*.XML 210 | UpgradeLog*.htm 211 | 212 | # SQL Server files 213 | *.mdf 214 | *.ldf 215 | 216 | # Business Intelligence projects 217 | *.rdl.data 218 | *.bim.layout 219 | *.bim_*.settings 220 | 221 | # Microsoft Fakes 222 | FakesAssemblies/ 223 | 224 | # GhostDoc plugin setting file 225 | *.GhostDoc.xml 226 | 227 | # Node.js Tools for Visual Studio 228 | .ntvs_analysis.dat 229 | 230 | # Visual Studio 6 build log 231 | *.plg 232 | 233 | # Visual Studio 6 workspace options file 234 | *.opt 235 | 236 | # Visual Studio LightSwitch build output 237 | **/*.HTMLClient/GeneratedArtifacts 238 | **/*.DesktopClient/GeneratedArtifacts 239 | **/*.DesktopClient/ModelManifest.xml 240 | **/*.Server/GeneratedArtifacts 241 | **/*.Server/ModelManifest.xml 242 | _Pvt_Extensions 243 | 244 | # Paket dependency manager 245 | .paket/paket.exe 246 | paket-files/ 247 | 248 | # FAKE - F# Make 249 | .fake/ 250 | 251 | # JetBrains Rider 252 | .idea/ 253 | *.sln.iml 254 | -------------------------------------------------------------------------------- /EtwCommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include "stdafx.h" 34 | 35 | static constexpr const wchar_t* SessionName = L"NdisCapPacket"; 36 | 37 | struct EventTraceData : ADAPTER 38 | { 39 | EventTraceData() 40 | : ADAPTER{} 41 | { 42 | } 43 | 44 | TRACEHANDLE TraceHandleController; 45 | TRACEHANDLE TraceHandleConsumer; 46 | std::thread ConsumerThread; 47 | concurrency::concurrent_queue> Packet; 48 | }; 49 | 50 | std::pair StartCapture(); 51 | void StopCapture(_In_ TRACEHANDLE th); 52 | 53 | void CALLBACK EventRecordCallback(_In_ EVENT_RECORD* per); 54 | -------------------------------------------------------------------------------- /EtwConsumer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "stdafx.h" 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "EtwCommon.h" 40 | 41 | #pragma comment(lib, "tdh.lib") 42 | 43 | struct __declspec(uuid("{83ed54f0-4d48-4e45-b16e-726ffd1fa4af}")) Microsoft_Windows_Networking_Correlation; 44 | struct __declspec(uuid("{2ed6006e-4729-4609-b423-3ee7bcd678ef}")) Microsoft_Windows_NDIS_PacketCapture; 45 | 46 | /* 47 | per->EventDescriptor.Keyword 48 | 49 | 0x80000601'40000001 PacketStart 50 | 0x80000601'80000001 PacketEnd 51 | 0x00000001'00000000 SendPath 52 | 0x00000200'00000000 PiiPresent 53 | 0x00000400'00000000 Packet 54 | */ 55 | 56 | constexpr ULONGLONG KeywordPacketStart = 0x00000000'40000000; 57 | constexpr ULONGLONG KeywordPacketEnd = 0x00000000'80000000; 58 | 59 | struct GuidHash 60 | { 61 | std::size_t operator()(const GUID& x) const noexcept 62 | { 63 | union 64 | { 65 | std::size_t buffer[sizeof(GUID) / sizeof(std::size_t)]; 66 | GUID guid; 67 | }; 68 | static_assert(sizeof buffer == sizeof(GUID), "Unknown arch"); 69 | guid = x; 70 | return std::accumulate(std::begin(buffer), std::end(buffer), std::size_t(), [](auto x, auto y) { return x ^ y; }); 71 | } 72 | }; 73 | 74 | void CALLBACK EventRecordCallback(_In_ EVENT_RECORD* per) 75 | { 76 | auto data = static_cast(per->UserContext); 77 | 78 | static std::unordered_map, GuidHash> fragment; 79 | if (false) 80 | { 81 | std::wostringstream s; 82 | WCHAR tmp[39]; 83 | if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_Networking_Correlation)) 84 | { 85 | s << "C"; 86 | } 87 | else if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_NDIS_PacketCapture)) 88 | { 89 | s << "P"; 90 | } 91 | else 92 | { 93 | StringFromGUID2(per->EventHeader.ProviderId, tmp, ARRAYSIZE(tmp)); 94 | s << tmp; 95 | } 96 | StringFromGUID2(per->EventHeader.ActivityId, tmp, ARRAYSIZE(tmp)); 97 | s << ", Activity ID: " << tmp; 98 | for (int i = 0; i < per->ExtendedDataCount; ++i) 99 | { 100 | const auto& e = per->ExtendedData[i]; 101 | if (e.ExtType == EVENT_HEADER_EXT_TYPE_RELATED_ACTIVITYID) 102 | { 103 | const auto& r = *(const EVENT_EXTENDED_ITEM_RELATED_ACTIVITYID*)(e.DataPtr); 104 | StringFromGUID2(r.RelatedActivityId, tmp, ARRAYSIZE(tmp)); 105 | s << ", RelatedActivityId: " << tmp; 106 | } 107 | else 108 | { 109 | s << ", ExtType: " << e.ExtType; 110 | } 111 | } 112 | if (per->UserDataLength <= 26 || *((BYTE*)per->UserData + 24) != 0x08 || *((BYTE*)per->UserData + 25) != 0x00) 113 | { 114 | if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_NDIS_PacketCapture)) 115 | { 116 | s << " !"; 117 | } 118 | } 119 | if (per->EventHeader.ProviderId != __uuidof(Microsoft_Windows_Networking_Correlation)) 120 | { 121 | ULONG bufferSize = 0; 122 | auto statusSize = TdhGetEventInformation(per, 0, nullptr, nullptr, &bufferSize); 123 | if (statusSize != ERROR_INSUFFICIENT_BUFFER) 124 | { 125 | return; 126 | } 127 | 128 | auto buffer = std::make_unique(bufferSize); 129 | auto info = reinterpret_cast(buffer.get()); 130 | auto status = TdhGetEventInformation(per, 0, nullptr, info, &bufferSize); 131 | if (status != ERROR_SUCCESS) 132 | { 133 | return; 134 | } 135 | for (ULONG i = 0; i < info->TopLevelPropertyCount; i++) 136 | { 137 | const auto& propertyInfo = info->EventPropertyInfoArray[i]; 138 | auto name = reinterpret_cast(buffer.get() + propertyInfo.NameOffset); 139 | if (std::wcscmp(name, L"FragmentSize") != 0) 140 | { 141 | continue; 142 | } 143 | PROPERTY_DATA_DESCRIPTOR desc{ 144 | reinterpret_cast(name), 145 | ULONG_MAX, 146 | }; 147 | ULONG propertyBufferSize; 148 | auto statusPropSize = TdhGetPropertySize(per, 0, nullptr, 1, &desc, &propertyBufferSize); 149 | if (statusPropSize != ERROR_SUCCESS) 150 | { 151 | continue; 152 | } 153 | auto propertyBuffer = std::make_unique(propertyBufferSize); 154 | auto statusProp = TdhGetProperty(per, 0, nullptr, 1, &desc, propertyBufferSize, propertyBuffer.get()); 155 | if (statusProp != ERROR_SUCCESS) 156 | { 157 | continue; 158 | } 159 | if ((propertyInfo.Flags & PropertyStruct) != 0) 160 | { 161 | continue; 162 | } 163 | if (propertyInfo.nonStructType.InType != TDH_INTYPE_UINT32) 164 | { 165 | continue; 166 | } 167 | s << L", Fragment size: " << *reinterpret_cast(propertyBuffer.get()); 168 | } 169 | 170 | } 171 | s << "\r\n"; 172 | OutputDebugStringW(s.str().c_str()); 173 | } 174 | 175 | if (per->EventHeader.ProviderId != __uuidof(Microsoft_Windows_NDIS_PacketCapture)) 176 | { 177 | return; 178 | } 179 | 180 | ULONG bufferSize = 0; 181 | auto statusSize = TdhGetEventInformation(per, 0, nullptr, nullptr, &bufferSize); 182 | if (statusSize != ERROR_INSUFFICIENT_BUFFER) 183 | { 184 | return; 185 | } 186 | 187 | auto buffer = std::make_unique(bufferSize); 188 | auto info = reinterpret_cast(buffer.get()); 189 | auto status = TdhGetEventInformation(per, 0, nullptr, info, &bufferSize); 190 | if (status != ERROR_SUCCESS) 191 | { 192 | return; 193 | } 194 | for (ULONG i = 0; i < info->TopLevelPropertyCount; i++) 195 | { 196 | const auto& propertyInfo = info->EventPropertyInfoArray[i]; 197 | auto name = reinterpret_cast(buffer.get() + propertyInfo.NameOffset); 198 | if (std::wcscmp(name, L"Fragment") != 0) 199 | { 200 | continue; 201 | } 202 | PROPERTY_DATA_DESCRIPTOR desc{ 203 | reinterpret_cast(name), 204 | ULONG_MAX, 205 | }; 206 | ULONG propertyBufferSize; 207 | auto statusPropSize = TdhGetPropertySize(per, 0, nullptr, 1, &desc, &propertyBufferSize); 208 | if (statusPropSize != ERROR_SUCCESS) 209 | { 210 | continue; 211 | } 212 | auto propertyBuffer = std::make_unique(propertyBufferSize); 213 | auto statusProp = TdhGetProperty(per, 0, nullptr, 1, &desc, propertyBufferSize, propertyBuffer.get()); 214 | if (statusProp != ERROR_SUCCESS) 215 | { 216 | continue; 217 | } 218 | if ((propertyInfo.Flags & PropertyStruct) != 0) 219 | { 220 | continue; 221 | } 222 | if (propertyInfo.nonStructType.InType != TDH_INTYPE_BINARY) 223 | { 224 | continue; 225 | } 226 | 227 | std::wostringstream s; 228 | WCHAR tmp[39]; 229 | StringFromGUID2(per->EventHeader.ActivityId, tmp, ARRAYSIZE(tmp)); 230 | s << tmp << ' ' << std::hex << per->EventHeader.Flags; 231 | 232 | auto it = fragment.find(per->EventHeader.ActivityId); 233 | if (it == fragment.end()) 234 | { 235 | if ((per->EventHeader.EventDescriptor.Keyword & KeywordPacketEnd) != 0) 236 | { 237 | data->Packet.push(std::vector(propertyBuffer.get(), propertyBuffer.get() + propertyBufferSize)); 238 | } 239 | else 240 | { 241 | fragment.emplace( 242 | per->EventHeader.ActivityId, 243 | std::vector(propertyBuffer.get(), propertyBuffer.get() + propertyBufferSize)); 244 | } 245 | } 246 | else 247 | { 248 | it->second.insert( 249 | it->second.end(), 250 | propertyBuffer.get(), 251 | propertyBuffer.get() + propertyBufferSize); 252 | if ((per->EventHeader.EventDescriptor.Keyword & KeywordPacketEnd) != 0) 253 | { 254 | data->Packet.push(std::move(it->second)); 255 | fragment.erase(it); 256 | } 257 | } 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /EtwController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "stdafx.h" 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "EtwCommon.h" 39 | 40 | #pragma comment(lib, "wevtapi.lib") 41 | 42 | using namespace std::literals; 43 | 44 | struct ServiceHandleDeleter 45 | { 46 | typedef SC_HANDLE pointer; 47 | void operator()(_In_opt_ SC_HANDLE hsc) const noexcept 48 | { 49 | if (hsc != nullptr) 50 | { 51 | CloseServiceHandle(hsc); 52 | } 53 | } 54 | }; 55 | 56 | using service_handle = std::unique_ptr; 57 | 58 | struct HKeyDeleter 59 | { 60 | typedef HKEY pointer; 61 | void operator()(_In_opt_ HKEY hk) const noexcept 62 | { 63 | if (hk != nullptr) 64 | { 65 | RegCloseKey(hk); 66 | } 67 | } 68 | }; 69 | 70 | using hkey = std::unique_ptr; 71 | 72 | union EventTracePropertiesWithBuffer 73 | { 74 | // buffer size: EVENT_TRACE_PROPERTIES + logFileName + sessionName 75 | char buffer[sizeof(EVENT_TRACE_PROPERTIES) + (1024 + 1024) * sizeof(WCHAR)]; 76 | EVENT_TRACE_PROPERTIES etp; 77 | }; 78 | 79 | // {2ED6006E-4729-4609-B423-3EE7BCD678EF} 80 | static constexpr GUID GUID_Microsoft_Windows_NDIS_PacketCapture = { 0x2ED6006E, 0x4729, 0x4609,{ 0xB4, 0x23, 0x3E, 0xE7, 0xBC, 0xD6, 0x78, 0xEF } }; 81 | 82 | static DWORD StartNdisCapService() 83 | { 84 | service_handle hscm(OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT)); 85 | ATLENSURE_RETURN_VAL(hscm != nullptr, GetLastError()); 86 | service_handle hsc(OpenService(hscm.get(), L"ndiscap", SERVICE_START)); 87 | ATLENSURE_RETURN_VAL(hsc != nullptr, GetLastError()); 88 | return StartService(hsc.get(), 0, nullptr); 89 | } 90 | 91 | static DWORD SetNdisCapParameters(bool enable) 92 | { 93 | ATL::CRegKey key; 94 | auto lstatusCreate = key.Create( 95 | HKEY_LOCAL_MACHINE, 96 | LR"(System\CurrentControlSet\Services\NdisCap\Parameters)"); 97 | ATLENSURE_RETURN_VAL(lstatusCreate == ERROR_SUCCESS, lstatusCreate); 98 | 99 | DWORD refCount; 100 | auto lstatusQuery = key.QueryDWORDValue(L"RefCount", refCount); 101 | ATLENSURE_RETURN_VAL(lstatusQuery == ERROR_SUCCESS, lstatusQuery); 102 | 103 | if (enable) 104 | { 105 | ++refCount; 106 | auto lstatusSetRefCount = key.SetDWORDValue(L"RefCount", refCount); 107 | ATLENSURE_RETURN_VAL(lstatusSetRefCount == ERROR_SUCCESS, lstatusSetRefCount); 108 | } 109 | else 110 | { 111 | if (refCount > 0) 112 | { 113 | --refCount; 114 | auto lstatusSetRefCount = key.SetDWORDValue(L"RefCount", refCount); 115 | ATLENSURE_RETURN_VAL(lstatusSetRefCount == ERROR_SUCCESS, lstatusSetRefCount); 116 | } 117 | } 118 | 119 | if (enable) 120 | { 121 | auto lstatusSetCaptureMode = key.SetDWORDValue(L"CaptureMode", 0); 122 | ATLENSURE_RETURN_VAL(lstatusSetCaptureMode == ERROR_SUCCESS, lstatusSetCaptureMode); 123 | } 124 | 125 | return ERROR_SUCCESS; 126 | } 127 | 128 | static DWORD EnableCapture(bool enable) 129 | { 130 | Microsoft::WRL::ComPtr nc; 131 | auto hrCreate = CoCreateInstance(CLSID_CNetCfg, nullptr, CLSCTX_SERVER, IID_PPV_ARGS(&nc)); 132 | ATLENSURE_RETURN_HR(SUCCEEDED(hrCreate), hrCreate); 133 | 134 | Microsoft::WRL::ComPtr lock; 135 | auto hrQueryL = nc.As(&lock); 136 | ATLENSURE_RETURN_HR(SUCCEEDED(hrQueryL), hrQueryL); 137 | 138 | auto hrLock = lock->AcquireWriteLock(5000, L"NdisCapPacket", nullptr); 139 | ATLENSURE_RETURN_HR(SUCCEEDED(hrLock), hrLock); 140 | 141 | auto hrInit = nc->Initialize(nullptr); 142 | ATLENSURE_RETURN_HR(SUCCEEDED(hrInit), hrInit); 143 | 144 | Microsoft::WRL::ComPtr ndisCap; 145 | auto hrFind = nc->FindComponent(L"ms_ndiscap", &ndisCap); 146 | ATLENSURE_RETURN_HR(SUCCEEDED(hrFind), hrFind); 147 | 148 | Microsoft::WRL::ComPtr bindings; 149 | auto hrQueryB = ndisCap.As(&bindings); 150 | ATLENSURE_RETURN_HR(SUCCEEDED(hrQueryB), hrQueryB); 151 | 152 | Microsoft::WRL::ComPtr enumBindingPath; 153 | auto hrEnum = bindings->EnumBindingPaths(EBP_BELOW, &enumBindingPath); 154 | ATLENSURE_RETURN_HR(SUCCEEDED(hrEnum), hrEnum); 155 | 156 | for (;;) 157 | { 158 | ATL::CComPtr bindingPath; 159 | ULONG fetched; 160 | auto hrNext = enumBindingPath->Next(1, &bindingPath, &fetched); 161 | ATLENSURE_RETURN_HR(SUCCEEDED(hrNext), hrNext); 162 | if (hrNext != S_OK) 163 | { 164 | break; 165 | } 166 | 167 | auto hrEnable = bindingPath->Enable(static_cast(enable)); 168 | ATLENSURE_RETURN_HR(SUCCEEDED(hrEnable), hrEnable); 169 | } 170 | auto hrApply = nc->Apply(); 171 | ATLENSURE_RETURN_HR(SUCCEEDED(hrApply), hrApply); 172 | 173 | ATL::CRegKey session; 174 | auto lstatusCreate = session.Create( 175 | HKEY_CURRENT_USER, 176 | LR"(System\CurrentControlSet\Control\NetTrace\Session)", 177 | nullptr, 178 | REG_OPTION_NON_VOLATILE, 179 | KEY_SET_VALUE); 180 | ATLENSURE_RETURN_VAL(lstatusCreate == ERROR_SUCCESS, lstatusCreate); 181 | 182 | auto lstatusSet = session.SetDWORDValue(L"CaptureEnabled", 1u); 183 | ATLENSURE_RETURN_VAL(lstatusSet == ERROR_SUCCESS, lstatusSet); 184 | 185 | auto hrReleaseLock = lock->ReleaseWriteLock(); 186 | ATLENSURE_RETURN_HR(SUCCEEDED(hrReleaseLock), hrReleaseLock); 187 | 188 | auto hrUninit = nc->Uninitialize(); 189 | ATLENSURE_RETURN_HR(SUCCEEDED(hrUninit), hrUninit); 190 | 191 | return S_OK; 192 | } 193 | 194 | static std::pair StartTrace() 195 | { 196 | TRACEHANDLE th; 197 | EventTracePropertiesWithBuffer buffer{}; 198 | buffer.etp.Wnode.BufferSize = sizeof buffer; 199 | buffer.etp.Wnode.ClientContext = 2; // Query perfomance counter 200 | buffer.etp.Wnode.Flags = WNODE_FLAG_TRACED_GUID; 201 | buffer.etp.BufferSize = 128; 202 | buffer.etp.MaximumBuffers = 128; 203 | buffer.etp.MaximumFileSize = 250; 204 | buffer.etp.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; 205 | buffer.etp.LoggerNameOffset = sizeof buffer.etp; 206 | auto resultStartTrace = StartTrace(&th, SessionName, &buffer.etp); 207 | if (resultStartTrace == ERROR_ALREADY_EXISTS) 208 | { 209 | auto resultControlTrace = ControlTrace(0, SessionName, &buffer.etp, EVENT_TRACE_CONTROL_STOP); 210 | ATLENSURE_RETURN_VAL(resultControlTrace == ERROR_SUCCESS, std::make_pair(resultControlTrace, TRACEHANDLE())); 211 | resultStartTrace = StartTrace(&th, SessionName, &buffer.etp); 212 | } 213 | ATLENSURE_RETURN_VAL(resultStartTrace == ERROR_SUCCESS, std::make_pair(resultStartTrace, TRACEHANDLE())); 214 | 215 | ENABLE_TRACE_PARAMETERS params{}; 216 | params.Version = ENABLE_TRACE_PARAMETERS_VERSION; 217 | auto resultEnableTrace = EnableTraceEx2(th, 218 | &GUID_Microsoft_Windows_NDIS_PacketCapture, 219 | EVENT_CONTROL_CODE_ENABLE_PROVIDER, 220 | TRACE_LEVEL_INFORMATION, 221 | 0, 222 | 0, 223 | 0, 224 | ¶ms); 225 | ATLENSURE_RETURN_VAL(resultEnableTrace == ERROR_SUCCESS, std::make_pair(resultEnableTrace, TRACEHANDLE())); 226 | 227 | return{ ERROR_SUCCESS, th }; 228 | } 229 | 230 | std::pair StartCapture() 231 | { 232 | for (;;) 233 | { 234 | auto resultService = StartNdisCapService(); 235 | if (resultService == ERROR_SUCCESS) 236 | { 237 | break; 238 | } 239 | else if (resultService == ERROR_INVALID_FUNCTION) 240 | { 241 | Sleep(50); 242 | continue; 243 | } 244 | return{ resultService, TRACEHANDLE() }; 245 | } 246 | 247 | auto resultParameters = SetNdisCapParameters(true); 248 | ATLENSURE_RETURN_VAL(resultParameters == ERROR_SUCCESS, std::make_pair(resultParameters, TRACEHANDLE())); 249 | 250 | auto resultCapture = EnableCapture(true); 251 | ATLENSURE_RETURN_VAL(resultCapture == ERROR_SUCCESS, std::make_pair(resultCapture, TRACEHANDLE())); 252 | 253 | return StartTrace(); 254 | } 255 | 256 | void StopCapture(_In_ TRACEHANDLE th) 257 | { 258 | EventTracePropertiesWithBuffer buffer{}; 259 | buffer.etp.Wnode.BufferSize = sizeof buffer; 260 | buffer.etp.LoggerNameOffset = sizeof buffer.etp; 261 | buffer.etp.LogFileNameOffset = sizeof buffer.etp + 1024 * sizeof (WCHAR); 262 | ControlTrace(th, nullptr, &buffer.etp, EVENT_TRACE_CONTROL_STOP); 263 | 264 | EnableCapture(false); 265 | SetNdisCapParameters(false); 266 | } 267 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The BSD 3-Clause License 2 | 3 | Copyright (c) 2016 Egtra All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | * Neither the name of {{ project }} nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /NdisCapPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "stdafx.h" 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include "EtwCommon.h" 38 | 39 | #pragma comment(lib, "iphlpapi.lib") 40 | 41 | using namespace std::literals; 42 | 43 | class ComInitializer 44 | { 45 | public: 46 | ComInitializer() 47 | : m_hr(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE)) 48 | { 49 | assert(IsInitialized()); 50 | } 51 | 52 | bool IsInitialized() const 53 | { 54 | return SUCCEEDED(m_hr) || m_hr == RPC_E_CHANGED_MODE; 55 | } 56 | 57 | ~ComInitializer() 58 | { 59 | if (m_hr == S_OK) 60 | { 61 | CoUninitialize(); 62 | } 63 | } 64 | 65 | private: 66 | const HRESULT m_hr; 67 | 68 | ComInitializer(const ComInitializer&) = delete; 69 | ComInitializer& operator=(const ComInitializer&) = delete; 70 | }; 71 | 72 | PCHAR PacketGetVersion() 73 | { 74 | static char version[] = "NdisCapPacket 0.1"; 75 | return version; 76 | } 77 | 78 | PCHAR PacketGetDriverVersion() 79 | { 80 | static char driverVersion[] = "NdisCap"; 81 | return driverVersion; 82 | } 83 | 84 | BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject, int nbytes) 85 | { 86 | //assert(false); 87 | return TRUE; 88 | } 89 | 90 | BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject, int nwrites) 91 | { 92 | assert(false); 93 | return FALSE; 94 | } 95 | 96 | BOOLEAN PacketSetMode(LPADAPTER AdapterObject, int mode) 97 | { 98 | assert(false); 99 | return TRUE; 100 | } 101 | 102 | BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject, int timeout) 103 | { 104 | //assert(false); 105 | return TRUE; 106 | } 107 | 108 | BOOLEAN PacketSetBpf(LPADAPTER AdapterObject, bpf_program *fp) 109 | { 110 | //assert(false); 111 | return TRUE; 112 | } 113 | 114 | BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior) 115 | { 116 | assert(false); 117 | return TRUE; 118 | } 119 | 120 | INT PacketSetSnapLen(LPADAPTER AdapterObject, int snaplen) 121 | { 122 | assert(false); 123 | return 0; 124 | } 125 | 126 | BOOLEAN PacketGetStats(_In_ LPADAPTER AdapterObject, _Out_ bpf_stat* s) 127 | { 128 | if (s == nullptr) 129 | { 130 | SetLastError(ERROR_INVALID_PARAMETER); 131 | return FALSE; 132 | } 133 | *s = {}; 134 | return TRUE; 135 | } 136 | 137 | BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject, bpf_stat *s) 138 | { 139 | assert(false); 140 | return FALSE; 141 | } 142 | 143 | BOOLEAN PacketSetBuff(LPADAPTER AdapterObject, int dim) 144 | { 145 | //assert(false); 146 | return TRUE; 147 | } 148 | 149 | BOOLEAN PacketGetNetType(_In_ LPADAPTER AdapterObject, _Out_ NetType* type) 150 | { 151 | type->LinkType = 0; // NdisMedium802_3 152 | type->LinkSpeed = 100 * 1000 * 1000; 153 | return TRUE; 154 | } 155 | 156 | LPADAPTER PacketOpenAdapter(_In_ PCHAR AdapterName) 157 | { 158 | if (AdapterName == nullptr) 159 | { 160 | SetLastError(ERROR_INVALID_PARAMETER); 161 | return nullptr; 162 | } 163 | if (std::strlen(AdapterName) + 1 > sizeof EventTraceData::Name) 164 | { 165 | SetLastError(ERROR_INVALID_PARAMETER); 166 | return nullptr; 167 | } 168 | 169 | try 170 | { 171 | auto data = std::make_unique(); 172 | strcpy_s(data->Name, AdapterName); 173 | 174 | if (!data->ConsumerThread.joinable()) 175 | { 176 | ComInitializer comInit; 177 | 178 | auto resultStartCapture = StartCapture(); 179 | if (std::get<0>(resultStartCapture) != ERROR_SUCCESS) 180 | { 181 | SetLastError(std::get<0>(resultStartCapture)); 182 | return nullptr; 183 | } 184 | data->TraceHandleController = std::get<1>(resultStartCapture); 185 | 186 | EVENT_TRACE_LOGFILE etl{}; 187 | #if 1 188 | etl.LoggerName = const_cast(SessionName); 189 | etl.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_REAL_TIME; 190 | #else 191 | etl.LogFileName = LR"(T:\a.etl)"; 192 | etl.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD; 193 | #endif 194 | etl.EventRecordCallback = EventRecordCallback; 195 | etl.Context = data.get(); 196 | auto hTrace = OpenTrace(&etl); 197 | // See “Return Value” section: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364089(v=vs.85).aspx 198 | #ifdef _WIN64 199 | ATLENSURE_RETURN_VAL(hTrace != 0xFFFFFFFFFFFFFFFF, nullptr); 200 | #else 201 | ATLENSURE_RETURN_VAL(hTrace != 0x00000000FFFFFFFF, nullptr); 202 | #endif 203 | data->TraceHandleConsumer = hTrace; 204 | data->ConsumerThread = std::thread([hTrace]() mutable 205 | { 206 | ProcessTrace(&hTrace, 1, nullptr, nullptr); 207 | }); 208 | } 209 | return data.release(); 210 | } 211 | catch (const std::system_error& e) 212 | { 213 | if (e.code().category() == std::system_category()) 214 | { 215 | SetLastError(static_cast(e.code().value())); 216 | } 217 | else 218 | { 219 | SetLastError(E_FAIL); 220 | } 221 | } 222 | catch (const std::bad_alloc&) 223 | { 224 | SetLastError(ERROR_OUTOFMEMORY); 225 | } 226 | catch (...) 227 | { 228 | SetLastError(E_FAIL); 229 | } 230 | return nullptr; 231 | } 232 | 233 | BOOLEAN PacketSendPacket(LPADAPTER AdapterObject, LPPACKET pPacket, BOOLEAN Sync) 234 | { 235 | assert(false); 236 | return FALSE; 237 | } 238 | 239 | INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync) 240 | { 241 | assert(false); 242 | return FALSE; 243 | } 244 | 245 | LPPACKET PacketAllocatePacket() 246 | { 247 | return new(std::nothrow) PACKET{}; 248 | } 249 | 250 | VOID PacketInitPacket(_Inout_ LPPACKET lpPacket, _In_ PVOID Buffer, _In_ UINT Length) 251 | { 252 | lpPacket->Buffer = Buffer; 253 | lpPacket->Length = Length; 254 | lpPacket->ulBytesReceived = 0; 255 | lpPacket->bIoComplete = FALSE; 256 | } 257 | 258 | VOID PacketFreePacket(_In_opt_ LPPACKET lpPacket) 259 | { 260 | delete lpPacket; 261 | } 262 | 263 | BOOLEAN PacketReceivePacket(_In_ LPADAPTER AdapterObject, _In_ LPPACKET lpPacket, _In_ BOOLEAN Sync) 264 | { 265 | if (AdapterObject == nullptr || lpPacket == nullptr) 266 | { 267 | return FALSE; 268 | } 269 | 270 | auto data = static_cast(AdapterObject); 271 | std::vector packet; 272 | while (!data->Packet.try_pop(packet)) 273 | { 274 | lpPacket->ulBytesReceived = 0; 275 | return TRUE; 276 | } 277 | 278 | auto p = static_cast(lpPacket->Buffer); 279 | auto header = reinterpret_cast(p); 280 | header->bh_tstamp.tv_sec = time(nullptr); 281 | header->bh_tstamp.tv_usec = 0; 282 | header->bh_caplen = packet.size(); 283 | header->bh_datalen = packet.size(); 284 | header->bh_hdrlen = sizeof(bpf_hdr); 285 | memcpy(p + sizeof(bpf_hdr), packet.data(), packet.size()); 286 | 287 | lpPacket->ulBytesReceived = packet.size(); 288 | 289 | return TRUE; 290 | } 291 | 292 | BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject, ULONG Filter) 293 | { 294 | //assert(false); 295 | return TRUE; 296 | } 297 | 298 | BOOLEAN PacketGetAdapterNames(_Out_opt_ PSTR pStr, _Inout_ PULONG BufferSize) 299 | { 300 | if (BufferSize == nullptr) 301 | { 302 | SetLastError(ERROR_INVALID_PARAMETER); 303 | return FALSE; 304 | } 305 | 306 | static constexpr char data[] = "NdisCapPacket\0\0NdisCapPacket\0"; 307 | if (pStr == nullptr || *BufferSize < sizeof data) 308 | { 309 | SetLastError(ERROR_INSUFFICIENT_BUFFER); 310 | *BufferSize = sizeof data; 311 | return FALSE; 312 | } 313 | 314 | memcpy(pStr, data, sizeof data); 315 | *BufferSize = sizeof data; 316 | return TRUE; 317 | } 318 | 319 | BOOLEAN PacketGetNetInfoEx(_In_ PCHAR AdapterName, _Out_ npf_if_addr* buffer, _Inout_ PLONG NEntries) 320 | { 321 | if (AdapterName == nullptr || buffer == nullptr || NEntries == nullptr) 322 | { 323 | return FALSE; 324 | } 325 | constexpr DWORD Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME; 326 | ULONG addressesBufferSize; 327 | auto resultSize = GetAdaptersAddresses(AF_UNSPEC, Flags, nullptr, nullptr, &addressesBufferSize); 328 | if (resultSize != ERROR_BUFFER_OVERFLOW) 329 | { 330 | return FALSE; 331 | } 332 | std::unique_ptr addressesBuffer(new(std::nothrow) std::uint8_t[addressesBufferSize]); 333 | if (addressesBuffer == nullptr) 334 | { 335 | return FALSE; 336 | } 337 | auto addresses = reinterpret_cast(addressesBuffer.get()); 338 | auto resultAddress = GetAdaptersAddresses(AF_UNSPEC, Flags, nullptr, addresses, &addressesBufferSize); 339 | if (resultAddress != ERROR_SUCCESS) 340 | { 341 | return FALSE; 342 | } 343 | ULONG n = *NEntries; 344 | ULONG i = 0; 345 | for (; i < n && addresses != nullptr; ++i, addresses = addresses->Next) 346 | { 347 | auto a = addresses->FirstUnicastAddress; 348 | memcpy(&buffer[i].IPAddress, a->Address.lpSockaddr, a->Address.iSockaddrLength); 349 | buffer[i].SubnetMask = {}; 350 | buffer[i].Broadcast = {}; 351 | } 352 | *NEntries = i; 353 | return TRUE; 354 | } 355 | 356 | BOOLEAN PacketRequest(LPADAPTER AdapterObject, BOOLEAN Set, PPACKET_OID_DATA OidData) 357 | { 358 | assert(false); 359 | return FALSE; 360 | } 361 | 362 | HANDLE PacketGetReadEvent(LPADAPTER AdapterObject) 363 | { 364 | assert(false); 365 | return nullptr; 366 | } 367 | 368 | BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len) 369 | { 370 | assert(false); 371 | return FALSE; 372 | } 373 | 374 | BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks) 375 | { 376 | assert(false); 377 | return FALSE; 378 | } 379 | 380 | BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync) 381 | { 382 | assert(false); 383 | return FALSE; 384 | } 385 | 386 | BOOL PacketStopDriver() 387 | { 388 | assert(false); 389 | return TRUE; 390 | } 391 | 392 | void PacketCloseAdapter(_In_ LPADAPTER lpAdapter) 393 | { 394 | if (lpAdapter == nullptr) 395 | { 396 | return; 397 | } 398 | auto data = static_cast(lpAdapter); 399 | 400 | ComInitializer comInit; 401 | StopCapture(data->TraceHandleController); 402 | data->ConsumerThread.join(); 403 | CloseTrace(data->TraceHandleConsumer); 404 | delete data; 405 | } 406 | 407 | BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength) 408 | { 409 | assert(false); 410 | return FALSE; 411 | } 412 | 413 | BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags) 414 | { 415 | assert(false); 416 | return FALSE; 417 | } 418 | 419 | PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject) 420 | { 421 | assert(false); 422 | return nullptr; 423 | } 424 | -------------------------------------------------------------------------------- /NdisCapPacket.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | PacketGetVersion 4 | PacketGetDriverVersion 5 | PacketSetMinToCopy 6 | PacketSetNumWrites 7 | PacketSetMode 8 | PacketSetReadTimeout 9 | PacketSetBpf 10 | PacketSetLoopbackBehavior 11 | PacketSetSnapLen 12 | PacketGetStats 13 | PacketGetStatsEx 14 | PacketSetBuff 15 | PacketGetNetType 16 | PacketOpenAdapter 17 | PacketSendPacket 18 | PacketSendPackets 19 | PacketAllocatePacket 20 | PacketInitPacket 21 | PacketFreePacket 22 | PacketReceivePacket 23 | PacketSetHwFilter 24 | PacketGetAdapterNames 25 | PacketGetNetInfoEx 26 | PacketRequest 27 | PacketGetReadEvent 28 | PacketSetDumpName 29 | PacketSetDumpLimits 30 | PacketIsDumpEnded 31 | PacketStopDriver 32 | PacketCloseAdapter 33 | PacketStartOem 34 | PacketStartOemEx 35 | PacketGetAirPcapHandle 36 | -------------------------------------------------------------------------------- /NdisCapPacket.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NdisCapPacket", "NdisCapPacket.vcxproj", "{0A51E5F1-7522-44B9-8F9E-B6052F88E721}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Debug|x64.ActiveCfg = Debug|x64 17 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Debug|x64.Build.0 = Debug|x64 18 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Debug|x86.ActiveCfg = Debug|Win32 19 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Debug|x86.Build.0 = Debug|Win32 20 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Release|x64.ActiveCfg = Release|x64 21 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Release|x64.Build.0 = Release|x64 22 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Release|x86.ActiveCfg = Release|Win32 23 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /NdisCapPacket.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {0A51E5F1-7522-44B9-8F9E-B6052F88E721} 23 | Win32Proj 24 | NdisCapPacket 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | Packet 75 | $(SolutionDir)bin\$(Configuration)-$(Platform)\ 76 | obj\$(Configuration)-$(Platform)\ 77 | 78 | 79 | true 80 | Packet 81 | $(SolutionDir)bin\$(Configuration)-$(Platform)\ 82 | obj\$(Configuration)-$(Platform)\ 83 | 84 | 85 | false 86 | Packet 87 | $(SolutionDir)bin\$(Configuration)-$(Platform)\ 88 | obj\$(Configuration)-$(Platform)\ 89 | 90 | 91 | false 92 | Packet 93 | $(SolutionDir)bin\$(Configuration)-$(Platform)\ 94 | obj\$(Configuration)-$(Platform)\ 95 | 96 | 97 | 98 | Use 99 | Level4 100 | Disabled 101 | WIN32;_DEBUG;_WINDOWS;_USRDLL;NDISCAPPACKET_EXPORTS;%(PreprocessorDefinitions) 102 | true 103 | ProgramDatabase 104 | Guard 105 | 106 | 107 | Windows 108 | true 109 | NdisCapPacket.def 110 | 111 | 112 | 113 | 114 | Use 115 | Level4 116 | Disabled 117 | _DEBUG;_WINDOWS;_USRDLL;NDISCAPPACKET_EXPORTS;%(PreprocessorDefinitions) 118 | true 119 | ProgramDatabase 120 | Guard 121 | 122 | 123 | Windows 124 | true 125 | NdisCapPacket.def 126 | 127 | 128 | 129 | 130 | Level4 131 | Use 132 | MaxSpeed 133 | true 134 | true 135 | WIN32;NDEBUG;_WINDOWS;_USRDLL;NDISCAPPACKET_EXPORTS;%(PreprocessorDefinitions) 136 | true 137 | Guard 138 | 139 | 140 | Windows 141 | true 142 | true 143 | true 144 | NdisCapPacket.def 145 | 146 | 147 | 148 | 149 | Level4 150 | Use 151 | MaxSpeed 152 | true 153 | true 154 | NDEBUG;_WINDOWS;_USRDLL;NDISCAPPACKET_EXPORTS;%(PreprocessorDefinitions) 155 | true 156 | Guard 157 | 158 | 159 | Windows 160 | true 161 | true 162 | true 163 | NdisCapPacket.def 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | false 176 | 177 | 178 | false 179 | 180 | 181 | false 182 | 183 | 184 | false 185 | 186 | 187 | 188 | 189 | 190 | 191 | Create 192 | Create 193 | Create 194 | Create 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /NdisCapPacket.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | 49 | 50 | 51 | Source Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /Packet32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) 3 | * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the Politecnico di Torino, CACE Technologies 16 | * nor the names of its contributors may be used to endorse or promote 17 | * products derived from this software without specific prior written 18 | * permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | 34 | /** @ingroup packetapi 35 | * @{ 36 | */ 37 | 38 | /** @defgroup packet32h Packet.dll definitions and data structures 39 | * Packet32.h contains the data structures and the definitions used by packet.dll. 40 | * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included 41 | * by the applications that use the functions of this library 42 | * @{ 43 | */ 44 | 45 | #ifndef __PACKET32 46 | #define __PACKET32 47 | 48 | #include 49 | 50 | #ifdef HAVE_AIRPCAP_API 51 | #include 52 | #else 53 | #if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) 54 | #define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ 55 | typedef struct _AirpcapHandle *PAirpcapHandle; 56 | #endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */ 57 | #endif /* HAVE_AIRPCAP_API */ 58 | 59 | #ifdef HAVE_DAG_API 60 | #include 61 | #endif /* HAVE_DAG_API */ 62 | 63 | // Working modes 64 | #define PACKET_MODE_CAPT 0x0 ///< Capture mode 65 | #define PACKET_MODE_STAT 0x1 ///< Statistical mode 66 | #define PACKET_MODE_MON 0x2 ///< Monitoring mode 67 | #define PACKET_MODE_DUMP 0x10 ///< Dump mode 68 | #define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode 69 | 70 | 71 | /// Alignment macro. Defines the alignment size. 72 | #define Packet_ALIGNMENT sizeof(int) 73 | /// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. 74 | #define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) 75 | 76 | #define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent 77 | #define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent 78 | #define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent 79 | #define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent 80 | #define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent 81 | #define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent 82 | 83 | // Loopback behaviour definitions 84 | #define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver 85 | #define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver 86 | 87 | /*! 88 | \brief Network type structure. 89 | 90 | This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. 91 | */ 92 | typedef struct NetType 93 | { 94 | UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) 95 | ULONGLONG LinkSpeed; ///< The speed of the network in bits per second 96 | }NetType; 97 | 98 | 99 | //some definitions stolen from libpcap 100 | 101 | #ifndef BPF_MAJOR_VERSION 102 | 103 | /*! 104 | \brief A BPF pseudo-assembly program. 105 | 106 | The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. 107 | */ 108 | struct bpf_program 109 | { 110 | UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. 111 | struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. 112 | }; 113 | 114 | /*! 115 | \brief A single BPF pseudo-instruction. 116 | 117 | bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. 118 | */ 119 | struct bpf_insn 120 | { 121 | USHORT code; ///< Instruction type and addressing mode. 122 | UCHAR jt; ///< Jump if true 123 | UCHAR jf; ///< Jump if false 124 | int k; ///< Generic field used for various purposes. 125 | }; 126 | 127 | /*! 128 | \brief Structure that contains a couple of statistics values on the current capture. 129 | 130 | It is used by packet.dll to return statistics about a capture session. 131 | */ 132 | struct bpf_stat 133 | { 134 | UINT bs_recv; ///< Number of packets that the driver received from the network adapter 135 | ///< from the beginning of the current capture. This value includes the packets 136 | ///< lost by the driver. 137 | UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. 138 | ///< Basically, a packet is lost when the the buffer of the driver is full. 139 | ///< In this situation the packet cannot be stored and the driver rejects it. 140 | UINT ps_ifdrop; ///< drops by interface. XXX not yet supported 141 | UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and 142 | ///< thus reach the application. 143 | }; 144 | 145 | /*! 146 | \brief Packet header. 147 | 148 | This structure defines the header associated with every packet delivered to the application. 149 | */ 150 | struct bpf_hdr 151 | { 152 | struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. 153 | ///< It is stored in a TimeVal structure. 154 | UINT bh_caplen; ///< Length of captured portion. The captured portion can be different 155 | ///< from the original packet, because it is possible (with a proper filter) 156 | ///< to instruct the driver to capture only a portion of the packets. 157 | UINT bh_datalen; ///< Original length of packet 158 | USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, 159 | ///< a padding could be added between the end of this structure and the packet 160 | ///< data for performance reasons. This filed can be used to retrieve the actual data 161 | ///< of the packet. 162 | }; 163 | 164 | /*! 165 | \brief Dump packet header. 166 | 167 | This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). 168 | It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a 169 | packet in a dump file. This makes straightforward sending WinPcap dump files to the network. 170 | */ 171 | struct dump_bpf_hdr{ 172 | struct timeval ts; ///< Time stamp of the packet 173 | UINT caplen; ///< Length of captured portion. The captured portion can smaller than the 174 | ///< the original packet, because it is possible (with a proper filter) to 175 | ///< instruct the driver to capture only a portion of the packets. 176 | UINT len; ///< Length of the original packet (off wire). 177 | }; 178 | 179 | 180 | #endif 181 | 182 | struct bpf_stat; 183 | 184 | #define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices 185 | #define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links 186 | #define NMAX_PACKET 65535 187 | 188 | /*! 189 | \brief Addresses of a network adapter. 190 | 191 | This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with 192 | an adapter. 193 | */ 194 | typedef struct npf_if_addr { 195 | struct sockaddr_storage IPAddress; ///< IP address. 196 | struct sockaddr_storage SubnetMask; ///< Netmask for that address. 197 | struct sockaddr_storage Broadcast; ///< Broadcast address. 198 | }npf_if_addr; 199 | 200 | 201 | #define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. 202 | #define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. 203 | #define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. 204 | #define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. 205 | 206 | 207 | typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API 208 | typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API 209 | 210 | #define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter 211 | #define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET 212 | #define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card 213 | #define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file 214 | #define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. 215 | #define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card 216 | #define INFO_FLAG_NPFIM_DEVICE 32 217 | 218 | /*! 219 | \brief Describes an opened network adapter. 220 | 221 | This structure is the most important for the functioning of packet.dll, but the great part of its fields 222 | should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters 223 | */ 224 | typedef struct _ADAPTER { 225 | HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. 226 | CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. 227 | int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated 228 | ///< on the wire. 229 | HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. 230 | ///< It can be passed to standard Win32 functions (like WaitForSingleObject 231 | ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some 232 | ///< data. It is particularly useful in GUI applications that need to wait 233 | ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() 234 | ///< function can be used to define the minimum amount of data in the kernel buffer 235 | ///< that will cause the event to be signalled. 236 | 237 | UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and 238 | ///< ReadEvent will be signaled, also if no packets were captured 239 | CHAR Name[ADAPTER_NAME_LENGTH]; 240 | PWAN_ADAPTER pWanAdapter; 241 | UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. 242 | 243 | #ifdef HAVE_AIRPCAP_API 244 | PAirpcapHandle AirpcapAd; 245 | #endif // HAVE_AIRPCAP_API 246 | 247 | #ifdef HAVE_NPFIM_API 248 | void* NpfImHandle; 249 | #endif // HAVE_NPFIM_API 250 | 251 | #ifdef HAVE_DAG_API 252 | dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter 253 | PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card 254 | struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure 255 | unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry 256 | DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). 257 | #endif // HAVE_DAG_API 258 | } ADAPTER, *LPADAPTER; 259 | 260 | /*! 261 | \brief Structure that contains a group of packets coming from the driver. 262 | 263 | This structure defines the header associated with every packet delivered to the application. 264 | */ 265 | typedef struct _PACKET { 266 | HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. 267 | OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. 268 | PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for 269 | ///< details about the organization of the data in this buffer 270 | UINT Length; ///< Length of the buffer 271 | DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data 272 | ///< received by the last call to PacketReceivePacket() 273 | BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. 274 | } PACKET, *LPPACKET; 275 | 276 | /*! 277 | \brief Structure containing an OID request. 278 | 279 | It is used by the PacketRequest() function to send an OID to the interface card driver. 280 | It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, 281 | the list of the multicast groups defined on it, and so on. 282 | */ 283 | struct _PACKET_OID_DATA { 284 | ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h 285 | ///< for a complete list of valid codes. 286 | ULONG Length; ///< Length of the data field 287 | UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received 288 | ///< from the adapter. 289 | }; 290 | typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; 291 | 292 | #ifdef __cplusplus 293 | extern "C" { 294 | #endif 295 | 296 | /** 297 | * @} 298 | */ 299 | 300 | /* 301 | BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName, 302 | CHAR *Value, 303 | UINT *pValueLen, 304 | CHAR *DefaultVal); 305 | 306 | BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName, 307 | WCHAR *Value, 308 | UINT *pValueLen, 309 | WCHAR *DefaultVal); 310 | */ 311 | 312 | //--------------------------------------------------------------------------- 313 | // EXPORTED FUNCTIONS 314 | //--------------------------------------------------------------------------- 315 | 316 | PCHAR PacketGetVersion(); 317 | PCHAR PacketGetDriverVersion(); 318 | BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); 319 | BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); 320 | BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); 321 | BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); 322 | BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); 323 | BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior); 324 | INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); 325 | BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); 326 | BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); 327 | BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); 328 | BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); 329 | LPADAPTER PacketOpenAdapter(PCHAR AdapterName); 330 | BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); 331 | INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); 332 | LPPACKET PacketAllocatePacket(void); 333 | VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); 334 | VOID PacketFreePacket(LPPACKET lpPacket); 335 | BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); 336 | BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); 337 | BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); 338 | BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); 339 | BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); 340 | HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); 341 | BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); 342 | BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); 343 | BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); 344 | BOOL PacketStopDriver(); 345 | VOID PacketCloseAdapter(LPADAPTER lpAdapter); 346 | BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength); 347 | BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags); 348 | PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject); 349 | 350 | // 351 | // Used by PacketStartOemEx 352 | // 353 | #define PACKET_START_OEM_NO_NETMON 0x00000001 354 | 355 | #ifdef __cplusplus 356 | } 357 | #endif 358 | 359 | #endif //__PACKET32 360 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NdisCapPacket 2 | 3 | NdisCapPacket is a packet capture DLL. 4 | API is compatible to WinPcap's packet.dll. 5 | 6 | Microsoft Windows 7+ have ndiscap.sys, a device driver for packet capture. 7 | NdisCapPacket use ndiscap.sys. 8 | 9 | ## License 10 | 11 | The BSD 3-Clause License. See LICENSE.txt. 12 | -------------------------------------------------------------------------------- /dllmain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "stdafx.h" 32 | 33 | BOOL APIENTRY DllMain(_In_ HMODULE, _In_ DWORD, _Reserved_ void*) 34 | { 35 | return TRUE; 36 | } 37 | -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "stdafx.h" 32 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include "targetver.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #define WIN32_LEAN_AND_MEAN 46 | #include 47 | #include 48 | #include 49 | 50 | #define PTSTR PSTR 51 | #include "packet32.h" 52 | #undef PTSTR 53 | 54 | #define _ATL_NO_AUTOMATIC_NAMESPACE 55 | 56 | #include 57 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | /* 2 | The BSD 3-Clause License 3 | 4 | Copyright (c) 2016 Egtra All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of {{ project }} nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #pragma once 32 | 33 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 34 | #include 35 | --------------------------------------------------------------------------------