Windows下访问/修改UEFI变量(C++/C#)

您所在的位置:网站首页 uefi固件更改设置 Windows下访问/修改UEFI变量(C++/C#)

Windows下访问/修改UEFI变量(C++/C#)

2024-02-16 11:45| 来源: 网络整理| 查看: 265

UEFI,全称 Unified Extensible Firmware Interface,译为“统一可扩展固件接口”。

UEFI 相比传统的 BIOS(Legacy) 启动方式,除了启动方便,还有一个最大的特点就是 UEFI 支持图形化操作,使用户操作更简单便捷,尤其是对于外行的朋友,可视化界面总比一堆看不懂的“代码”操作简便。

简单来讲 UEFI 启动是新一代的 BIOS,功能更加强大,被看作是 Legacy BIOS 的继任者。

Windows 下访问 UEFI 变量,MSDN 提供了几个接口: GetFirmwareEnvironmentVariableExA function GetFirmwareEnvironmentVariableExW function SetFirmwareEnvironmentVariableExA function SetFirmwareEnvironmentVariableExW function

1,在调用这些接口之前,首先需要判断当前计算机是否为 UEFI 的固件类型:GetFirmwareType function

C++:

bool DetectFirmwareType() { FIRMWARE_TYPE firmwareType; if (GetFirmwareType(&firmwareType)) { if (firmwareType != FIRMWARE_TYPE::FirmwareTypeUefi) { return false; } } return true; }

C#:

[DllImport("kernel32.dll")] private static extern bool GetFirmwareType(ref FirmwareType FirmwareType); internal enum FirmwareType { FirmwareTypeUnknown = 0, FirmwareTypeBios = 1, FirmwareTypeUefi = 2, FirmwareTypeMax = 3 }; private static FirmwareType GetFirmwareType() { FirmwareType type = FirmwareType.FirmwareTypeUnknown; if (GetFirmwareType(ref type)) { return type; } return FirmwareType.FirmwareTypeUnknown; }

2,根据 MSDN 的描述: To read a UEFI firmware environment variable, the user account that the app is running under must have the SE_SYSTEM_ENVIRONMENT_NAME privilege.

因此需要提升进程权限:AdjustTokenPrivileges function

C++:

// newPrivileges -> 提升权限值 // enable -> 提升/降低(恢复) bool promoteProcessPrivileges(const TCHAR* newPrivileges, const bool enable) { HANDLE tokenHandle; //获得当前进程的access token句柄 if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle) == FALSE) return false; TOKEN_PRIVILEGES structTkp; //查找newPrivileges参数对应的Luid,并将结果写入structTkp.Privileges[0]的Luid域中 if (::LookupPrivilegeValue(NULL, newPrivileges, &structTkp.Privileges[0].Luid) == FALSE) { CloseHandle(tokenHandle); return false; } //设置structTkp结构 structTkp.PrivilegeCount = 1; structTkp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; //通知操作系统更改权限 if (::AdjustTokenPrivileges(tokenHandle, FALSE, &structTkp, sizeof(structTkp), NULL, NULL) == FALSE) { CloseHandle(tokenHandle); return false; } CloseHandle(tokenHandle); return true; }

C#:

internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; internal const int TOKEN_QUERY = 0x00000008; internal const int SE_PRIVILEGE_ENABLED = 0x00000002; private const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"; [DllImport("kernel32.dll", ExactSpelling = true)] internal static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokenPrivelege newst, int len, IntPtr prev, IntPtr relen); [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TokenPrivelege { public int Count; public long Luid; public int Attr; } /// /// 提升进程权限 /// /// 权限 /// 提升/恢复 /// private static bool PromoteProcessPrivileges(string privilege, bool enable) { IntPtr hToken = IntPtr.Zero; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken)) { Console.WriteLine("OpenProcessToken failed!"); return false; } TokenPrivelege tp; tp.Count = 1; tp.Luid = 0; tp.Attr = enable ? SE_PRIVILEGE_ENABLED : 0; if (!LookupPrivilegeValue(null, privilege, ref tp.Luid)) { Console.WriteLine("LookupPrivilegeValue failed!"); return false; } if (!AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero)) { Console.WriteLine("AdjustTokenPrivileges failed!"); return false; } return true; }

Refer: Enabling and Disabling Privileges in C++

3.1,获取 UEFI 变量值(需要使用管理员权限运行):

C++:

typedef struct { UINT8 Variable; UINT8 Reserved[3]; } VARIABLE; enum Status { Disable, Enable, UnknownStatus }; LPCTSTR lpName = _T(""); LPCTSTR lpGuid = _T(""); DWORD dwAttribute = 0; VARIABLE lenStru = { 0 }; Status GetUEFIVariable() { Status status = Status::UnknownStatus; DWORD isSuss = GetFirmwareEnvironmentVariableEx(lpName, lpGuid, &lenStru, sizeof(lenStru), &dwAttribute); uint32_t u32LastError = GetLastError(); if (u32LastError != ERROR_SUCCESS) cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3