提示:本文修改后包含編程方法以及附注的工具方法,傳統(tǒng)的資源管理器交互方法等等。
由于文件是安全對象,因此訪問它們受訪問控制模型控制,該模型控制對 Windows 中所有其他安全對象的訪問。?
更改文件或目錄對象的安全描述符,需要調(diào)用?SetNamedSecurityInfo?或?SetSecurityInfo?等函數(shù)。
ACL:Access Control List,用來表示用戶(組)權(quán)限的列表,包括?DACL?和?SACL ;
ACE:Access Control Entry,ACL?中的元素;
DACL:Discretionary Access Control List,用來表示安全對象權(quán)限的列表;
SACL:System Access Control List,用來記錄對安全對象訪問的日志。
關(guān)于這幾個概念已經(jīng)有很多資料解釋,這里就不詳細展開了。(以下僅介紹通過 Win32API 修改文件安全屬性的一些內(nèi)容)。
本文以 SetNamedSecurityInfo 函數(shù)為例,簡單講解如何通過編程修改指定文件的 ACL 主體和添加 ACE 條目。后文修改的文件比較特殊,它們受到本地內(nèi)置安全主體?TrustedInstaller 的完全控制保護,本文旨在通過相關(guān)?API?實現(xiàn)修改這類文件的完全控制權(quán)限。有關(guān)內(nèi)置安全主體?TrustedInstaller 的信息,需要具有一定的知識基礎(chǔ),限于篇幅原因這里不詳細展開。
一、編程實現(xiàn)方法闡述
1.1 修改 ACL 的所有者
SetNamedSecurityInfo 函數(shù)用于在指定對象的安全描述符(ACL)中設(shè)置指定的安全信息。 調(diào)用方按名稱標識對象。
這里的按名稱標識對象,表示設(shè)置安全信息時候,目標對象名是字符串格式,且對于不同對象類型的字符串格式,可以參閱說明:SE_OBJECT_TYPE。我們這里要修改NTFS文件系統(tǒng)中指定文件的安全屬性,按照標準需要填寫文件絕對路徑的寬字符串,其中路徑以反斜杠 (" / ") 或者雙斜杠 (" \\ ") 給出,并且要以 NULL 結(jié)尾。
下面給出該函數(shù)的參數(shù):
DWORD SetNamedSecurityInfoW(
[in] LPWSTR pObjectName,
[in] SE_OBJECT_TYPE ObjectType,
[in] SECURITY_INFORMATION SecurityInfo,
[in, optional] PSID psidOwner,
[in, optional] PSID psidGroup,
[in, optional] PACL pDacl,
[in, optional] PACL pSacl
);
這些參數(shù)的定義是:
pObjectName 指定目標對象的名稱;
ObjectType 指示 pObjectName 的類型,如果修改 NTFS 文件則填寫為 SE_FILE_OBJECT;
SecurityInfo 指示要設(shè)置的安全信息的類型;
psidOwner 指向標識對象所有者的 SID 結(jié)構(gòu)的指針;
psidGroup 指向標識對象主組的 SID 的指針;
pDacl 指向 對象的新 DACL 的指針;
pSacl 指向 對象的新 SACL 的指針。
其中,如果 SecurityInfo 填寫為 OWNER_SECURITY_INFORMATION 表明對安全主體的操作(也就是控制列表所有者);如果填寫為?DACL_SECURITY_INFORMATION 則表明對安全對象(ACE)的權(quán)限的操作。這里需要注意:如果調(diào)用方令牌對應(yīng)的賬戶標識符(SID)不是文件安全主體指向的賬戶標識符,則對安全對象權(quán)限的操作會被拒絕。
修改文件安全屬性需要進程的令牌具有一定的訪問控制權(quán)限,這里我們需要獲取兩個權(quán)限?SE_SECURITY_NAME 和?SE_TAKE_OWNERSHIP_NAME 。這兩個權(quán)限可以通過?AdjustTokenPrivileges 函數(shù)獲得,而賦予新的令牌則需要調(diào)用方線程具有管理員權(quán)限。所以進程需要以提升的令牌啟動才能正確獲取權(quán)限。
從零開始的項目都是不容易的,有一個參考最好不過了。這里我們可以參考資源管理器的功能實現(xiàn)文件安全屬性的修改,下面的圖片展示了通過資源管理器查看的目標文件的安全屬性頁面信息:

通過觀察,我們可以發(fā)現(xiàn),當前的所有者為 TrustedInstaller 并且只有它具有完全控制權(quán)限,其他安全對象只具有讀取和執(zhí)行的權(quán)限。此外我們還發(fā)現(xiàn),對于該文件權(quán)限修改的按鈕都是灰色或者具有盾牌圖標。我們將其與用戶具有完全訪問控制權(quán)的文件安全信息進行對比,就可以發(fā)現(xiàn)所有者信息起到了至關(guān)重要的作用,調(diào)用方必須為文件的安全主體或者權(quán)限比安全主體高,否則不能修改安全屬性表。所以當正確獲取權(quán)限后,我們首先需要修改文件的安全主體(所有者)。
首先我們簡述一下通過資源管理器進行修改的步驟:
Step 1: 首先選中要修改的文件(夾),打開右鍵菜單,在菜單中找到“屬性”項目,點擊打開屬性對話框;
Step 2: 在屬性對話框中選中“安全”選項卡,右下角點擊“高級(安全設(shè)置)”按鈕;
Step 3: 可以看到該頁面包含兩個主要部分:1)所有者;2)成員及其權(quán)限
并且后面都有帶有盾牌的“更改”按鈕,再結(jié)合說明文檔可知,如果當前進程代表的賬戶權(quán)限低于所有者所具有的權(quán)限,則低權(quán)限進程不具有修改高權(quán)限進程的權(quán)限能力;
這里我們需要先修改所有者,點擊最上面的TrustedInstaller字樣后面的更改按鈕,此時可能彈出UAC對話框提示用戶需要提升權(quán)限,也可能沒有提示直接提升(取決于計算機配置的UAC警告級別)
Step 4: 此時會彈出選擇所有者的對話框,點擊“高級”按鈕展開這個編輯器窗口:
Step 5: 在高級窗口中點擊立即查找,在查找的列表中找到當前登陸用戶的用戶名,然后點擊確定,或者選擇everyone(字面意思,代表任何用戶)。
Step 6: 逐級確定并應(yīng)用,可以發(fā)現(xiàn)所有者被成功更改:
最后一步點擊“應(yīng)用”,然后再點擊確定,應(yīng)用更改,隨后重新打開高級安全設(shè)置頁面,選擇要修改權(quán)限的成員,并發(fā)現(xiàn)編輯區(qū)域按鈕被點亮,點擊“添加/編輯”:
隨后,在打開的窗口中,先點擊藍色字“選擇主體”,類似于修改所有者的操作完成權(quán)限配置,并點擊確定,最后點擊應(yīng)用即可完成整個修改操作:
最后,補充一下修改完成后改回TrustedInstaller的方法:在更改所有者時候,直接輸入?NT SERVICE\TrustedInstaller 需要注意不能有拼寫錯誤!然后其他步驟不變。
我們通過設(shè)置?SetNamedSecurityInfo 函數(shù)的?SecurityInfo 參數(shù)為 OWNER_SECURITY_INFORMATION 并指定 psidOwner 為指向新所有者的安全描述符 (SID) 結(jié)構(gòu)的指針。
SID 就相當于所有者的身份證,那么我們?nèi)绾潍@取到所需要的 SID 呢?
LookupAccountName 函數(shù)可供獲取指定用戶名對應(yīng)的 SID 。
其參數(shù)如下:
BOOL LookupAccountNameW(
[in, optional] LPCWSTR lpSystemName,
[in] LPCWSTR lpAccountName,
[out, optional] PSID Sid,
[in, out] LPDWORD cbSid,
[out, optional] LPWSTR ReferencedDomainName,
[in, out] LPDWORD cchReferencedDomainName,
[out] PSID_NAME_USE peUse
);
其中,lpAccountName 指向指定帳戶名稱的以?NULL 結(jié)尾的字符串的指針。這里的本地賬戶名稱可以通過輸入已知的字符串如 "Administrators" 。注:采用 domain_name\user_name 格式的完全限定字符串來確保 LookupAccountName?函數(shù)在所需域中查找?guī)簦疚牟徽劶坝騼?nèi)操作,只談本地操作。
關(guān)于賬戶名稱的獲取,有多種方法,如 GetUserName 可以獲得創(chuàng)建當前調(diào)用線程所在帳戶名稱的字符串,環(huán)境變量函數(shù) GetEnvironmentVariable?通過設(shè)置 lpName 參數(shù)為"USERNAME"可以獲得當前所在帳戶名稱的字符串;使用 Windows Terminal Session API 獲取當前會話對應(yīng)的賬戶名稱字符串,等等。這里通過 WTSQuerySessionInformation 函數(shù)并指定相關(guān)參數(shù)設(shè)置以獲取當前登錄賬戶的名稱:
WTSQuerySessionInformationW(
WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION,
WTS_INFO_CLASS::WTSUserName,
&userName,
&nameSize);
然后將得到的字符串傳遞給?LookupAccountName 函數(shù),獲取對應(yīng)的 SID 。
隨后,調(diào)用?SetNamedSecurityInfo 并設(shè)置?pObjectName,?ObjectType,?SecurityInfo?和 psidOwner?參數(shù)即可修改目標對象的所有者。
1.2 修改訪問控制對象 (ACE) 信息
本文以在原有DACL表上添加新的對象權(quán)限為例進行講解。有關(guān)于覆蓋、刪除、復(fù)制的方法需要自行調(diào)試。
一種通用的更新方法就是先獲取到原始的DACL表,然后將其與要添加的內(nèi)容合并為一張新的表。最后將新的表更新到文件對應(yīng)的表上。
整個過程我們需要這幾個步驟:
Step1: 調(diào)用 GetNamedSecurityInfo 并設(shè)置 DACL_SECURITY_INFORMATION 類型,獲取舊的DACL表;
Step2: 調(diào)用 BuildExplicitAccessWithName 用于構(gòu)建一個 ACE,包含需要的權(quán)限;
Step3: 調(diào)用 SetEntriesInAcl 合并 ACE 到 舊的DACL,返回合并后的新的 DACL;
Step4: 調(diào)用 SetNamedSecurityInfo 綁定新的 DACL 到文件對象。
一個典型的示例代碼如下,其中 Step2 也可以直接為結(jié)構(gòu)體成員賦值:
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
LPWSTR pszTrustee, // trustee for new ACE
TRUSTEE_FORM TrusteeForm, // format of trustee structure
DWORD dwAccessRights, // access mask for new ACE
ACCESS_MODE AccessMode, // type of ACE
DWORD dwInheritance // inheritance flags for new ACE
)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea = {};
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
printf("|*|:為用戶 %ws 獲取文件:%ws 的訪問權(quán)限。\n", pszTrustee, pszObjName);
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfoW(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes) {
printf("GetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
//ea.grfAccessPermissions = dwAccessRights;
//ea.grfAccessMode = AccessMode;
//ea.grfInheritance = dwInheritance;
//ea.Trustee.TrusteeForm = TrusteeForm;
//ea.Trustee.ptstrName = pszTrustee;
// 生成指定用戶帳戶的訪問控制信息(這里指定賦予全部的訪問權(quán)限)
BuildExplicitAccessWithNameW(&ea, pszTrustee, dwAccessRights, AccessMode, dwInheritance);
// Create a new ACL that merges the new ACE
// into the existing DACL.
dwRes = SetEntriesInAclW(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfoW(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
else {
printf("成功:已經(jīng)為用戶 %ws 獲取文件:%ws 的訪問權(quán)限。\n", pszTrustee, pszObjName);
return dwRes;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
std::cout << "|*|:操作失敗! " << std::endl;
return -1;
}
通過以上方法即可對指定路徑文件進行安全訪問權(quán)限的修改。
二、完整編程代碼
2.1 完整代碼
下面是按照上文思路編寫的簡單實現(xiàn)代碼,需要將編譯好的程序在提升的命令行中執(zhí)行,命令行參數(shù)為 TestFile.exe <文件路徑> 。(編譯環(huán)境:Visual Studio C++)
#include <iostream>
#include <stdio.h>
#include <aclapi.h>
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <aclapi.h>
#include <wtsapi32.h>
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Wtsapi32.lib")
#define MAX_NAME 260
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCWSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValueW(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL SeTakeOwnershipToken()
{
printf("|*|操作:獲取相關(guān)權(quán)限。該特權(quán)可以修改目標文件的 Ownership。\n");
HANDLE hToken;
BOOL bRet = OpenProcessToken(
GetCurrentProcess(), // 進程句柄(當前進程)
TOKEN_ALL_ACCESS, // 全權(quán)訪問令牌
&hToken // 返回的參數(shù) 進程令牌句柄 (就是AdjustTokenPrivileges的第一個參數(shù))
); // 獲取進程的令牌句柄
if (bRet != TRUE) {
printf("獲取令牌句柄失敗!\nPlease wait...\n");
return FALSE;
}
// 提升權(quán)限
BOOL set_SECURITY = SetPrivilege(hToken, SE_SECURITY_NAME, TRUE);
if (!set_SECURITY || GetLastError() != ERROR_SUCCESS)
{
printf("提升SECURITY權(quán)限失敗 Error: %u\n|*|:操作失敗!\nPlease wait...\n", GetLastError());
Sleep(5000);
return FALSE;
}
// 提升獲得所有者權(quán)限
BOOL set_OWNER = SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE);
if (!set_OWNER || GetLastError() != ERROR_SUCCESS)
{
printf("提升TAKE OWNERSHIP權(quán)限失敗 Error: %u\n|*|:操作失敗!\nPlease wait...\n", GetLastError());
Sleep(5000);
return FALSE;
}
printf("提升權(quán)限成功! \n");
return TRUE;
}
BOOL ChangeTrusteeViaObjectsSecurity(
LPTSTR pszObjName, // name of object
LPTSTR pszTrustee, // trustee for new ACE
SE_OBJECT_TYPE ObjectType, // type of object. value :SE_FILE_OBJECT, /* 注冊表為:SE_REGISTRY_KEY */
SECURITY_INFORMATION SecurityInfo // Security Operational Information. value:OWNER_SECURITY_INFORMATION
)
{
DWORD dwRes = 0;
// LookupAccountName函數(shù)所需要的變量
wchar_t* userName = nullptr;
wchar_t sid[MAX_NAME]{ L'\0' };
DWORD nameSize = 0;
WTSQuerySessionInformationW(
WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION,
WTS_INFO_CLASS::WTSUserName,
&userName,
&nameSize);
wchar_t userSID[MAX_NAME]{ L'\0' };
wchar_t userDomain[MAX_NAME]{ L'\0' };
DWORD sidSize = sizeof(userSID);
DWORD signSidSize = sizeof(userSID);
DWORD domainSize = sizeof(userDomain) / sizeof(WCHAR);
SID_NAME_USE snu;
dwRes = LookupAccountNameW(NULL,
userName,
userSID,
&sidSize,
userDomain,
&domainSize,
&snu);
WTSFreeMemory(userName);
//獲取用戶名SID
if (ERROR_SUCCESS != dwRes)// 調(diào)用成功返回值為0
{
PSID_IDENTIFIER_AUTHORITY psia = GetSidIdentifierAuthority(userSID);
signSidSize = swprintf_s(sid, sizeof(sid)/sizeof(wchar_t), L"S-%lu-", SID_REVISION);
signSidSize = (signSidSize + swprintf_s(sid + wcslen(sid), sizeof(sid), L"%-lu", psia->Value[5]));
int i = 0;
int subAuthorities = *GetSidSubAuthorityCount(userSID);
for (i = 0; i < subAuthorities; i++)
{
signSidSize += swprintf_s(sid + signSidSize, sizeof(sid), L"-%lu", *GetSidSubAuthority(userSID, i));
}
printf("Account SID: %ws\n", sid);
// 更改所有者
if (!SetNamedSecurityInfoW
(pszObjName,
ObjectType, /* 注冊表為:SE_REGISTRY_KEY */
SecurityInfo, /* 更改所有者 */
&userSID, /* 需要更改所有者的SID */
NULL, NULL, NULL))
{
printf("成功更改所有者! \n");
return TRUE;
}
else {
printf("Security Info:OWNER_SECURITY_INFORMATION.\nSetNamedSecurityInfo Error %u\nPlease wait...\n", dwRes);
Sleep(5000);
}
}
else {
printf("LookupAccountName Error %u\nPlease wait...\n", dwRes);
Sleep(5000);
}
return FALSE;
}
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
LPWSTR pszTrustee, // trustee for new ACE
TRUSTEE_FORM TrusteeForm, // format of trustee structure
DWORD dwAccessRights, // access mask for new ACE
ACCESS_MODE AccessMode, // type of ACE
DWORD dwInheritance // inheritance flags for new ACE
)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea = {};
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
printf("|*|:為用戶 %ws 獲取文件:%ws 的訪問權(quán)限。\n", pszTrustee, pszObjName);
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfoW(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes) {
printf("GetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
//ea.grfAccessPermissions = dwAccessRights;
//ea.grfAccessMode = AccessMode;
//ea.grfInheritance = dwInheritance;
//ea.Trustee.TrusteeForm = TrusteeForm;
//ea.Trustee.ptstrName = pszTrustee;
// 生成指定用戶帳戶的訪問控制信息(這里指定賦予全部的訪問權(quán)限)
BuildExplicitAccessWithNameW(&ea, pszTrustee, dwAccessRights, AccessMode, dwInheritance);
// Create a new ACL that merges the new ACE
// into the existing DACL.
dwRes = SetEntriesInAclW(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfoW(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
else {
printf("成功:已經(jīng)為用戶 %ws 獲取文件:%ws 的訪問權(quán)限。\n", pszTrustee, pszObjName);
return dwRes;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
std::cout << "|*|:操作失敗! " << std::endl;
return -1;
}
int wmain(int argc, wchar_t* argv[])
{
setlocale(LC_CTYPE, "CHS");//讓wprintf()支持中文
if (argc != 2)
{
std::cout << "Invalid Parameters!" << std::endl;
return 0;
}
wchar_t* path = argv[1];
wchar_t* pszObjName = path;
// 獲取當前用戶名
wchar_t* currentUser = nullptr;
DWORD dwSize_currentUser = 0;
WTSQuerySessionInformationW(
WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION,
WTS_INFO_CLASS::WTSUserName,
¤tUser,
&dwSize_currentUser);
if (!SeTakeOwnershipToken()) {
std::cout << "|*|:在未獲得SE_TAKE_OWNERSHIP_NAME特權(quán)時,繼續(xù)更改文件所有者可能失敗! " << std::endl;
}
// 更改ACL下的安全主體,以獲得ACE控制權(quán)
if (ChangeTrusteeViaObjectsSecurity(pszObjName,
currentUser, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION))
{
// 覆蓋ACL以獲得完全控制的訪問權(quán)限
if (AddAceToObjectsSecurityDescriptor(pszObjName,
SE_FILE_OBJECT,
currentUser,
TRUSTEE_IS_OBJECTS_AND_SID,
GENERIC_ALL,
GRANT_ACCESS,
SUB_CONTAINERS_AND_OBJECTS_INHERIT) == -1)
{
std::cout << "ACE操作已執(zhí)行。" << std::endl;
}
}
else {
std::cout << "無法更改ACL下的安全主體,繼續(xù)更改ACE控制權(quán)可能會失敗。" << std::endl;
// 覆蓋ACL以獲得完全控制的訪問權(quán)限
if (AddAceToObjectsSecurityDescriptor(pszObjName,
SE_FILE_OBJECT,
currentUser,
TRUSTEE_IS_OBJECTS_AND_SID,
GENERIC_ALL,
GRANT_ACCESS,
SUB_CONTAINERS_AND_OBJECTS_INHERIT) == -1)
{
std::cout << "ACE操作已執(zhí)行。" << std::endl;
}
}
std::cout << "所有操作已完成。" << std::endl;
system("pause");
return 0;
}
2.2 調(diào)試效果
下圖是在提升的命令提示符中執(zhí)行的效果:

從圖中可見程序執(zhí)行完畢,并且沒有錯誤。
下圖展示的是程序執(zhí)行完畢后,目標對象的屬性變化:

從圖中可以看出目標對象的所有者發(fā)生變化,且為當前登陸賬戶添加了完全控制權(quán)限。
三、利用Windows工具實現(xiàn)修改安全控制對象權(quán)限
3.1 通過 ICacls 命令實現(xiàn)修改訪問控制權(quán)限
? ?? ?icacls
? ? ? Intergrity Control Access Control List: 完整性權(quán)限控制列表
? ? ? Windows系統(tǒng)下控制文件及文件夾的訪問權(quán)限的命令行指令,相當于Linux中的chmod
原命令cacls已經(jīng)被廢棄。
? ? ? 這一篇博客園作者整理的命令詳細信息比較全面清晰:Cacls和ICacls - 儺舞 - 博客園 (cnblogs.com)
3.2 通過 powershell / 注冊表 實現(xiàn)修改訪問控制權(quán)限
就不詳細列出了,這里給出一篇知乎,整理的也比較全面:滲透技巧——Windows下的Access Control List - 知乎
本文為原創(chuàng)文章,轉(zhuǎn)載請注明出處。(修改于:2023/9/19)文章來源:http://www.zghlxwxcb.cn/news/detail-754118.html
本人博客:漣幽516-CSDN博客漣幽516擅長C++學(xué)習(xí)筆記,Win10動態(tài)壁紙開發(fā),Windows上的編程,等方面的知識,漣幽516關(guān)注python,c++,c語言,系統(tǒng)安全領(lǐng)域.https://blog.csdn.net/qq_59075481文章來源地址http://www.zghlxwxcb.cn/news/detail-754118.html
到了這里,關(guān)于修改 Windows 文件訪問權(quán)限的多種方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!