From a5e15752a1e690657ce35b32502704121ef57657 Mon Sep 17 00:00:00 2001 From: Jedihy Date: Mon, 22 Feb 2021 17:20:40 -0800 Subject: [PATCH] Write iftype and ifindex into interface description blocks. (#36) Changes: 1. Write iftype and ifindex into interface description blocks. 2. statically link C runtime so vcredist doesn't need to be installed. Co-authored-by: Matt Olson --- README.md | 6 +- src/etl2pcapng.vcxproj | 342 +++++++++++++++++++++-------------------- src/main.c | 30 +++- src/pcapng.h | 106 +++++++++++-- 4 files changed, 295 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index 40020a4..01b6cb7 100644 --- a/README.md +++ b/README.md @@ -51,15 +51,17 @@ msbuild -t:rebuild -p:configuration=release -p:platform=x64 # History +1.5.0 - Write iftype and ifindex into interface description blocks and statically link C runtime so vcredist doesn't need to be installed. + 1.4.1 - Fix a bug leading to writing corrupt packets. 1.4.0 - Automatically infer original fragment length if captured fragments were truncated. 1.3.0 - Add a comment to each packet containing the process id (PID). -1.2.0 - Write direction info of each packet (epb_flags) +1.2.0 - Write direction info of each packet (epb_flags). -1.1.0 - Added support for multi-event packets found in traces from Win8 and older +1.1.0 - Added support for multi-event packets found in traces from Win8 and older. # Contributing diff --git a/src/etl2pcapng.vcxproj b/src/etl2pcapng.vcxproj index dd80bed..f7ebc87 100644 --- a/src/etl2pcapng.vcxproj +++ b/src/etl2pcapng.vcxproj @@ -1,170 +1,174 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - 16.0 - {CFBFA41A-1D26-45FC-8BDF-310059D7A015} - Win32Proj - etl2pcapng - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - . - - - Console - true - tdh.lib;ws2_32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - . - - - Console - true - tdh.lib;ws2_32.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - . - - - Console - true - true - true - tdh.lib;ws2_32.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - . - - - Console - true - true - true - tdh.lib;ws2_32.lib;%(AdditionalDependencies) - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 16.0 + {CFBFA41A-1D26-45FC-8BDF-310059D7A015} + Win32Proj + etl2pcapng + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + . + MultiThreaded + + + Console + true + tdh.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + . + MultiThreaded + + + Console + true + tdh.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + . + MultiThreaded + + + Console + true + true + true + tdh.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + . + MultiThreaded + + + Console + true + true + true + tdh.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + \ No newline at end of file diff --git a/src/main.c b/src/main.c index f1d40a1..94f5ee9 100644 --- a/src/main.c +++ b/src/main.c @@ -178,10 +178,15 @@ void WriteInterfaces() { // Sorts the interfaces, writes them to the pcapng file, and prints them // for user reference. - struct INTERFACE** InterfaceArray; struct INTERFACE* Interface; unsigned int i, j; + // IF_STRING_MAX_SIZE must be multiple of 4 + #define IF_STRING_MAX_SIZE 256 + char IfName[IF_STRING_MAX_SIZE]; + size_t IfNameLength = 0; + char IfDesc[IF_STRING_MAX_SIZE]; + size_t IfDescLength = 0; InterfaceArray = (struct INTERFACE**)malloc(NumInterfaces * sizeof(struct INTERFACE*)); if (InterfaceArray == NULL) { @@ -201,23 +206,42 @@ void WriteInterfaces() for (i = 0; i < NumInterfaces; i++) { Interface = InterfaceArray[i]; Interface->PcapNgIfIndex = i; - PcapNgWriteInterfaceDesc(OutFile, Interface->Type, MAX_PACKET_SIZE); + memset(IfName, 0, sizeof(IfName)); + memset(IfDesc, 0, sizeof(IfDesc)); + IfDescLength = 0; + IfNameLength = 0; switch (Interface->Type) { case PCAPNG_LINKTYPE_ETHERNET: printf("IF: medium=eth ID=%u\tIfIndex=%u", Interface->PcapNgIfIndex, Interface->LowerIfIndex); + StringCchPrintfA(IfName, IF_STRING_MAX_SIZE, "eth:%lu", Interface->LowerIfIndex); break; case PCAPNG_LINKTYPE_IEEE802_11: printf("IF: medium=wifi ID=%u\tIfIndex=%u", Interface->PcapNgIfIndex, Interface->LowerIfIndex); + StringCchPrintfA(IfName, IF_STRING_MAX_SIZE, "wifi:%lu", Interface->LowerIfIndex); break; case PCAPNG_LINKTYPE_RAW: printf("IF: medium=mbb ID=%u\tIfIndex=%u", Interface->PcapNgIfIndex, Interface->LowerIfIndex); + StringCchPrintfA(IfName, IF_STRING_MAX_SIZE, "mbb:%lu", Interface->LowerIfIndex); break; } + StringCchLengthA(IfName, IF_STRING_MAX_SIZE, &IfNameLength); + if (Interface->LowerIfIndex != Interface->MiniportIfIndex) { printf("\t(LWF over IfIndex %u)", Interface->MiniportIfIndex); + StringCchPrintfA(IfDesc, IF_STRING_MAX_SIZE, "LWF over IfIndex %lu", Interface->MiniportIfIndex); + StringCchLengthA(IfDesc, IF_STRING_MAX_SIZE, &IfDescLength); } printf("\n"); + + PcapNgWriteInterfaceDesc( + OutFile, + Interface->Type, + MAX_PACKET_SIZE, + IfName, + (unsigned short)IfNameLength, + IfDescLength != 0 ? IfDesc : NULL, + (unsigned short)IfDescLength); } free(InterfaceArray); @@ -471,7 +495,7 @@ int __cdecl wmain(int argc, wchar_t** argv) if (argc == 2 && (!wcscmp(argv[1], L"-v") || !wcscmp(argv[1], L"--version"))) { - printf("etl2pcapng version 1.4.1\n"); + printf("etl2pcapng version 1.5.0\n"); return 0; } diff --git a/src/pcapng.h b/src/pcapng.h index 25fe970..acf49a9 100644 --- a/src/pcapng.h +++ b/src/pcapng.h @@ -18,6 +18,8 @@ Helpers for working with .pcapng files. #define PCAPNG_OPTIONCODE_ENDOFOPT 0 #define PCAPNG_OPTIONCODE_COMMENT 1 #define PCAPNG_OPTIONCODE_EPB_FLAGS 2 +#define PCAPNG_OPTIONCODE_IDB_IF_NAME 2 +#define PCAPNG_OPTIONCODE_IDB_IF_DESC 3 #define PCAPNG_LINKTYPE_ETHERNET 1 #define PCAPNG_LINKTYPE_RAW 101 @@ -25,6 +27,8 @@ Helpers for working with .pcapng files. #define PCAPNG_SECTION_HEADER_MAGIC 0x1a2b3c4d // for byte order detection +#define PAD_TO_32BIT(x) ((4 - ((x) & 3)) & 3) + #include struct PCAPNG_BLOCK_HEAD { unsigned long Type; @@ -58,16 +62,17 @@ struct PCAPNG_BLOCK_OPTION_EPB_FLAGS { unsigned short Length; // 4 unsigned long Value; }; -struct PCAPNG_BLOCK_OPTION_COMMENT { - unsigned short Code; // PCAPNG_OPTIONCODE_COMMENT +struct PCAPNG_BLOCK_OPTION_VAR_LENGTH { + unsigned short Code; unsigned short Length; - char Comment[0]; // padded to 4 bytes }; struct PCAPNG_BLOCK_TAIL { unsigned long Length; // Same as PCAPNG_BLOCK_HEAD.Length, for easier backward processing. }; #include +struct PCAPNG_BLOCK_OPTION_ENDOFOPT EndOption = { .Code = PCAPNG_OPTIONCODE_ENDOFOPT, .Length = 0}; + inline int PcapNgWriteSectionHeader( HANDLE File @@ -113,15 +118,39 @@ inline int PcapNgWriteInterfaceDesc( HANDLE File, short LinkType, - long SnapLen + long SnapLen, + char* IfName, + unsigned short IfNameLength, + char* IfDesc, + unsigned short IfDescLength ) { int Err = NO_ERROR; struct PCAPNG_BLOCK_HEAD Head; struct PCAPNG_INTERFACE_DESC_BODY Body; struct PCAPNG_BLOCK_TAIL Tail; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfNameOpt; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfDescOpt; + char Pad[4] = { 0 }; + int TotalLength = sizeof(Head) + sizeof(Body) + sizeof(Tail); + if (IfName != NULL) { + IfNameOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_NAME; + IfNameOpt.Length = IfNameLength; + TotalLength += sizeof(IfNameOpt) + IfNameLength + PAD_TO_32BIT(IfNameLength); + } + + if (IfDesc != NULL) { + IfDescOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_DESC; + IfDescOpt.Length = IfDescLength; + TotalLength += sizeof(IfDescOpt) + IfDescLength + PAD_TO_32BIT(IfDescLength); + } + + if (IfName != NULL || IfDesc != NULL) { + TotalLength += sizeof(EndOption); + } + Head.Type = PCAPNG_BLOCKTYPE_INTERFACEDESC; Head.Length = TotalLength; if (!WriteFile(File, &Head, sizeof(Head), NULL, NULL)) { @@ -139,6 +168,56 @@ PcapNgWriteInterfaceDesc( goto Done; } + if (IfName != NULL) { + if (!WriteFile(File, &IfNameOpt, sizeof(IfNameOpt), NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (!WriteFile(File, IfName, IfNameLength, NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (PAD_TO_32BIT(IfNameLength) > 0) { + if (!WriteFile(File, Pad, PAD_TO_32BIT(IfNameLength), NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + } + + if (IfDesc != NULL) { + if (!WriteFile(File, &IfDescOpt, sizeof(IfDescOpt), NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (!WriteFile(File, IfDesc, IfDescLength, NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (PAD_TO_32BIT(IfDescLength) > 0) { + if (!WriteFile(File, Pad, PAD_TO_32BIT(IfDescLength), NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + } + + if (!WriteFile(File, &EndOption, sizeof(EndOption), NULL, NULL)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + Tail.Length = TotalLength; if (!WriteFile(File, &Tail, sizeof(Tail), NULL, NULL)) { Err = GetLastError(); @@ -153,14 +232,14 @@ PcapNgWriteInterfaceDesc( inline int PcapNgWriteCommentOption( - __in HANDLE File, - __in PCHAR CommentBuffer, - __in unsigned short CommentLength, - __in int CommentPadLength + HANDLE File, + PCHAR CommentBuffer, + unsigned short CommentLength, + int CommentPadLength ) { int Err = NO_ERROR; - struct PCAPNG_BLOCK_OPTION_COMMENT Comment; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH Comment; char Pad[4] = { 0 }; Comment.Code = PCAPNG_OPTIONCODE_COMMENT; @@ -206,18 +285,17 @@ PcapNgWriteEnhancedPacket( int Err = NO_ERROR; struct PCAPNG_BLOCK_HEAD Head; struct PCAPNG_ENHANCED_PACKET_BODY Body; - struct PCAPNG_BLOCK_OPTION_ENDOFOPT EndOption; struct PCAPNG_BLOCK_OPTION_EPB_FLAGS EpbFlagsOption; struct PCAPNG_BLOCK_TAIL Tail; char Pad[4] = {0}; BOOLEAN CommentProvided = (CommentLength > 0 && Comment != NULL); - int CommentPadLength = (4 - (CommentLength & 3)) & 3; // pad to 4 bytes per the spec. - int FragPadLength = (4 - ((sizeof(Body) + FragLength) & 3)) & 3; + int CommentPadLength = PAD_TO_32BIT(CommentLength); + int FragPadLength = PAD_TO_32BIT(sizeof(Body) + FragLength); int TotalLength = sizeof(Head) + sizeof(Body) + FragLength + FragPadLength + sizeof(EpbFlagsOption) + sizeof(EndOption) + sizeof(Tail) + (CommentProvided ? - sizeof(struct PCAPNG_BLOCK_OPTION_COMMENT) + CommentLength + CommentPadLength : 0); + sizeof(struct PCAPNG_BLOCK_OPTION_VAR_LENGTH) + CommentLength + CommentPadLength : 0); Head.Type = PCAPNG_BLOCKTYPE_ENHANCED_PACKET; Head.Length = TotalLength; @@ -271,8 +349,6 @@ PcapNgWriteEnhancedPacket( } } - EndOption.Code = PCAPNG_OPTIONCODE_ENDOFOPT; - EndOption.Length = 0; if (!WriteFile(File, &EndOption, sizeof(EndOption), NULL, NULL)) { Err = GetLastError(); printf("WriteFile failed with %u\n", Err);