在 Windows 2000 系統中,某些登錄機碼因安全性考量被設置了嚴格的存取控制清單(ACL),導致普通應用程式無法直接讀寫。本文將詳細介紹如何透過 Windows API 動態調整登錄機碼權限,實現對受保護機碼的合法操作,並提供完整的 C++ Builder 代碼範例。
Windows 使用安全描述符(Security Descriptor)與存取控制清單(ACL)來管理物件權限。要修改登錄機碼權限,需遵循以下步驟:
GetNamedSecurityInfo - 取得物件安全資訊SetNamedSecurityInfo - 設定物件安全資訊BuildExplicitAccessWithName - 建立明確存取結構SetEntriesInAcl - 建立/修改 ACLLocalFree - 釋放系統分配的記憶體// 開始重新配置使用登錄的權限------------------------------------------------
LPTSTR lpObjectName;
SE_OBJECT_TYPE ObjectType; // #include <aclapi.h>
PACL OldDACL, NewDACL;
PSECURITY_DESCRIPTOR SD;
EXPLICIT_ACCESS ea;
lpObjectName = "MACHINE\\SYSTEM\\ControlSet001\\Enum\\Root";
ObjectType = SE_REGISTRY_KEY;
// 建立空的 ACL
if (SetEntriesInAcl(0, NULL, NULL, &OldDACL) != ERROR_SUCCESS) return;
if (SetEntriesInAcl(0, NULL, NULL, &NewDACL) != ERROR_SUCCESS) return;
// 獲取現有的 ACL 列表到 OldDACL
if (GetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL,
&OldDACL,
NULL, &SD) != ERROR_SUCCESS) {
Application->MessageBox("指定的鍵不存在!", "提示", MB_OK);
return;
}
// 設置用戶名 "Everyone" 對指定的鍵有所有操作權到結構 ea
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(&ea,
"Everyone", // 受信任者名稱
GENERIC_ALL, // 存取類型:完整控制
SET_ACCESS, // 存取模式:設定
SUB_CONTAINERS_AND_OBJECTS_INHERIT); // 讓子鍵繼承權限
// 合併結構 ea 和 OldDACL 的權限列表到新的 NewDACL
if (SetEntriesInAcl(1, &ea, NULL, &NewDACL) != ERROR_SUCCESS)
goto Cleanup;
// 把新的 ACL 寫入到指定的鍵
SetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL,
NewDACL,
NULL);
/////// 開始操作登錄表 //////////////////////////////////////////////////////////
// ................................................... (在此處進行實際的登錄讀寫操作)
//////////////////////////////////////////////////////////////////////////////
// 恢復登錄表的權限
BuildExplicitAccessWithName(&ea,
"Everyone",
GENERIC_READ, // 僅保留讀取權限
SET_ACCESS,
NO_INHERITANCE); // 不繼承
if (SetEntriesInAcl(1, &ea, NULL, &OldDACL) != ERROR_SUCCESS)
goto Cleanup;
// 把舊的 ACL 寫入到指定的鍵
SetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL,
OldDACL,
NULL);
// 釋放指針
Cleanup:
if (SD != NULL) LocalFree((HLOCAL)SD);
if (NewDACL != NULL) LocalFree((HLOCAL)NewDACL);
if (OldDACL != NULL) LocalFree((HLOCAL)OldDACL);
LocalFree 釋放 GetNamedSecurityInfo 分配的安全描述符與 ACLSUB_CONTAINERS_AND_OBJECTS_INHERIT 確保子機碼繼承權限變更此技術適用於需存取系統關鍵機碼的合法應用場景,如:硬體驅動安裝、系統監控工具、企業級部署腳本等。嚴禁用於繞過安全機制的惡意用途。