From 2d0facae5323e343c3a7e70426faf5bcb92b4cbe Mon Sep 17 00:00:00 2001 From: Vivian Nowka-Keane Date: Tue, 9 Apr 2024 13:00:06 -0700 Subject: [PATCH] Advanced Logger Binary Dump Windows Executable (#453) ## Description Console app to get Advanced Logger binary dump. For each item, place an "x" in between `[` and `]` if true. Example: `[x]`. _(you can also check items in the GitHub UI)_ - [ ] Impacts functionality? - **Functionality** - Does the change ultimately impact how firmware functions? - Examples: Add a new library, publish a new PPI, update an algorithm, ... - [ ] Impacts security? - **Security** - Does the change have a direct security impact on an application, flow, or firmware? - Examples: Crypto algorithm change, buffer overflow fix, parameter validation improvement, ... - [ ] Breaking change? - **Breaking change** - Will anyone consuming this change experience a break in build or boot behavior? - Examples: Add a new library class, move a module to a different repo, call a function in a new library class in a pre-existing module, ... - [ ] Includes tests? - **Tests** - Does the change include any explicit test code? - Examples: Unit tests, integration tests, robot tests, ... - [ x] Includes documentation? - **Documentation** - Does the change contain explicit documentation additions outside direct code modifications (and comments)? - Examples: Update readme file, add feature readme file, link to documentation on an a separate Web page, ... ## How This Was Tested Built and ran on ARM and x64 machines. Verified output was identical to DecodeUefiLog script raw dump. ## Integration Instructions N/A --- .../Application/Windows/AdvLoggerDumpWin.sln | 37 ++++ .../AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj | 164 +++++++++++++++++ .../AdvLoggerDumpWin/PropertySheet.props | 16 ++ .../Windows/AdvLoggerDumpWin/ReadMe.md | 51 ++++++ .../Windows/AdvLoggerDumpWin/main.cpp | 171 ++++++++++++++++++ .../Windows/AdvLoggerDumpWin/main.h | 17 ++ .../Windows/AdvLoggerDumpWin/packages.config | 4 + 7 files changed, 460 insertions(+) create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/PropertySheet.props create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h create mode 100644 AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/packages.config diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln new file mode 100644 index 0000000000..696b697898 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvLoggerDumpWin", "AdvLoggerDumpWin\AdvLoggerDumpWin.vcxproj", "{F983380B-B6C4-44EE-8835-0137E0876321}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|ARM64.Build.0 = Debug|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x64.ActiveCfg = Debug|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x64.Build.0 = Debug|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x86.ActiveCfg = Debug|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x86.Build.0 = Debug|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|ARM64.ActiveCfg = Release|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|ARM64.Build.0 = Release|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x64.ActiveCfg = Release|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x64.Build.0 = Release|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x86.ActiveCfg = Release|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {514003CD-1327-488E-9C4E-8761C728A1E3} + EndGlobalSection +EndGlobal diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj new file mode 100644 index 0000000000..768e896926 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj @@ -0,0 +1,164 @@ + + + + + true + true + true + true + 15.0 + {f983380b-b6c4-44ee-8835-0137e0876321} + Win32Proj + AdvLoggerDumpWin + 10.0.22621.0 + 10.0.17134.0 + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Application + v143 + v142 + v141 + v140 + Unicode + + + true + true + + + false + true + true + + + Static + + + Static + + + Static + + + + + + + + + + + + + + + + NotUsing + + + + + _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + Level4 + %(AdditionalOptions) /permissive- /bigobj + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebugDLL + false + ProgramDatabase + false + + + Console + false + RequireAdministrator + RequireAdministrator + true + + + + + WIN32;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + MultiThreaded + Default + true + true + true + + + Console + false + + + false + + + RequireAdministrator + RequireAdministrator + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/PropertySheet.props b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/PropertySheet.props new file mode 100644 index 0000000000..9099073af9 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/PropertySheet.props @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md new file mode 100644 index 0000000000..4186477966 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md @@ -0,0 +1,51 @@ +# AdvLoggerPkg - AdvLoggerDumpWin + +AdvLoggerDumpWin is used to retrieve the advanced UEFI debug log stored in system memory. +If the Advanced Logger is enabled, the debug log is stored in memory and is available through the UEFI +Variable store. + +## About + +This tool creates a Windows executable that writes the UEFI variable data to a binary log file. As the +log in memory has additional metadata and alignment structure, DecodeUefiLog.py (in AdvLoggerPkg) +parses the in-memory UefiLog to a text stream and writes the decoded log to a local file. The Python +script can be used to both retrieve the log and decode it. +AdvLoggerDumpWin is able to be used in systems without Python. + +## Building + +To build the project, install Visual Studio 2022 with the following workloads: + +* Desktop development with C++ +* Universal Windows Platform development + +For individual components, ensure the following are installed (may be included with the above workloads): + +* Windows 11 SDK +* NugGet package manager +* MSVC v143 - VS 2022 C++ (Your Architecture) build tools +* C++ ATL fot latest v143 build tools (Your Architecture) +* C++ MFC for latest v143 build tools (Your Architecture) + +In Visual Studio, open the project solution file AdvLoggerPkg\Application\Windows\AdvLoggerDumpWin.sln + +The packages.config should tell NuGet to install the Microsoft.Windows.CppWinRT package. If not, add nuget.org +as a package source and install the package. + +Build the solution in Release mode. The executable will be in the Release folder for the given architecture. + +## Usage + +With administrator privileges, run the executable. +In an administrator command prompt: + +```.sh +AdvLoggerDumpWin.exe +``` + +The program creates a new log file `new_logfile.bin` in the current directory. + +## Copyright + +Copyright (C) Microsoft Corporation. \ +SPDX-License-Identifier: BSD-2-Clause-Patent diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp new file mode 100644 index 0000000000..6e41deed07 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp @@ -0,0 +1,171 @@ +/** @file +main.cpp + +Copyright (C) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "main.h" +#include +#include +#include +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; +using namespace std; + +// +// Elevate current process system environment privileges to access UEFI variables +// +static int +ElevateCurrentPrivileges ( + ) +{ + HANDLE ProcessHandle = GetCurrentProcess (); + DWORD DesiredAccess = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY; + HANDLE hProcessToken; + TOKEN_PRIVILEGES tp; + LUID luid; + int Status = 0; + + if (!LookupPrivilegeValue (NULL, L"SeSystemEnvironmentPrivilege", &luid)) { + Status = GetLastError (); + cout << "Failed to lookup privilege value. Errno " << Status << endl; + return Status; + } + + if (!OpenProcessToken (ProcessHandle, DesiredAccess, &hProcessToken)) { + Status = GetLastError (); + cout << "Failed to open process token. Errno " << Status << endl; + return Status; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges (hProcessToken, FALSE, &tp, sizeof (TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { + Status = GetLastError (); + cout << "Failed to adjust token privileges. Errno " << Status << endl; + return Status; + } + + if (GetLastError () == ERROR_NOT_ALL_ASSIGNED) { + Status = (int)ERROR_NOT_ALL_ASSIGNED; + cout << "The token does not have the specified privilege. Errno " << Status << endl; + return Status; + } + + CloseHandle (ProcessHandle); + return SUCCESS; +} + +// +// Create log file by retrieving AdvancedLogger variables from UEFI interface +// +int +ReadLogFromUefiInterface ( + fstream &lfile + ) +{ + int Status = 0; + int i = 0; + DWORD length = 0; + DWORD err = 0; + + stringstream varName; + char *varBuffer = (char *)malloc (MAX_VAR_LENGTH + 1); + + // string to LPCWSTR conversion + string tmpGuid = "{a021bf2b-34ed-4a98-859c-420ef94f3e94}"; + wstring tmpGuidW = wstring (tmpGuid.begin (), tmpGuid.end ()); + LPCWSTR guid = tmpGuidW.c_str (); + + // + // Parse variables by index until reached end of log + // + while (Status == 0) { + string tmpVarName = "V" + to_string (i); + wstring tmpVarNameW = wstring (tmpVarName.begin (), tmpVarName.end ()); + LPCWSTR varNameConst = tmpVarNameW.c_str (); + + // Retrieve one advanced logger indexed variable via kernel32 API + length = GetFirmwareEnvironmentVariableW (varNameConst, guid, varBuffer, MAX_VAR_LENGTH); + + if (length == 0) { + err = GetLastError (); + + // If error is ERROR_NOT_FOUND (203), reached end of variables + if (err != 203) { + Status = EFI_ERROR; + cout << "Error reading variable " << tmpVarName << " errno: " << err << endl; + return Status; + } else { + Status = (int)err; + } + } + + if (Status == 0) { + i += 1; + streamsize varSize = (streamsize)length; + lfile.write (varBuffer, varSize); + if (lfile.fail ()) { + cout << "Failed to write to file\n"; + Status = CONS_ERROR; + return Status; + } + } else if (i == 0) { + cout << "No variables found.\n"; + return Status; + } else { + cout << i << " variables read. " << lfile.tellg () << " chars written.\n"; + } + + if (varBuffer) { + ZeroMemory (varBuffer, MAX_VAR_LENGTH); + } + } + + free (varBuffer); + return SUCCESS; +} + +int +main ( + ) +{ + fstream logfile; + const char *newRawFilename = ".\\new_logfile.bin"; + int Status = 0; + + Status = ElevateCurrentPrivileges (); + if (Status != 0) { + cout << "Failed to elevate privileges, errno:" << Status << endl; + return Status; + } + + // Create new binary logfile + logfile.open (newRawFilename, ios::out | ios::binary); + if (!logfile) { + cout << "Error opening file.\n"; + Status = FILE_ERROR; + return Status; + } + + Status = ReadLogFromUefiInterface (logfile); + if (Status != SUCCESS) { + cerr << "Error reading log, exiting.\n"; + return LOG_ERROR; + } + + logfile.close (); + if (logfile.fail ()) { + cout << "Error closing file.\n"; + return FILE_ERROR; + } + + return SUCCESS; +} diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h new file mode 100644 index 0000000000..bff9be79c9 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h @@ -0,0 +1,17 @@ +/** @file +main.h + +Copyright (C) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#pragma once +#include +#include + +#define EFI_ERROR 1 +#define CONS_ERROR 2 +#define FILE_ERROR 3 +#define LOG_ERROR 4 +#define SUCCESS 0 +#define MAX_VAR_LENGTH 1024*1024 diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/packages.config b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/packages.config new file mode 100644 index 0000000000..90f0d13a53 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/packages.config @@ -0,0 +1,4 @@ + + + +