2016. 3. 6. 22:47ㆍIT-개발/winapi 및 MFC
Enabling and Disabling Privileges
The last program example in the previous Windows User & Groups, we failed to add the SACL to the ACL because we don’t have privilege to do that task. We already demonstrated how to enable a privilege in our earlier program example. Again, in the following program example we will try to enable the required privilege to accomplish our task. Enabling a privilege in an access token allows the process to perform system-level actions that it could not previously. Your application should thoroughly verify that the privilege is appropriate to the type of account, especially for the following powerful privileges:
Before enabling any of these potentially dangerous privileges, determine that functions or operations in your code actually require the privileges. For example, very few functions in the operating system actually require the SeTchPrivilege. The following example shows how to enable or disable a privilege in an access token. The example calls the LookupPrivilegeValue() function to get the LUID that the local system uses to identify the privilege. Then the example calls the AdjustTokenPrivileges() function, which either enables or disables the privilege that depends on the value of the bEnablePrivilege parameter. The following is a code portion used to enable/disable privilege.
BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) |
{
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;
if(!LookupPrivilegeValue(
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;
}
return TRUE;
}
The following is a working program example that enables/disables privilege.
#include <windows.h>
#include <stdio.h>
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
// Token privilege structure
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;
if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() error: %u\n", GetLastError());
return FALSE;
}
else
printf("LookupPrivilegeValue() is OK\n");
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
// Don't forget to disable the privileges after you enabled them,
// or have already completed your task. Don't mess up your system :o)
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}
// Enable the privilege (or disable all privileges).
if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE the function modifies privilege based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n", GetLastError());
return FALSE;
}
else
{
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());
printf("Should be 0, means the operation completed successfully = ERROR_SUCCESS\n");
}
return TRUE;
}
int main()
{
LPCTSTR lpszPrivilege = "SeSecurityPrivilege";
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
HANDLE hToken;
// Open a handle to the access token for the calling process. That is this running program
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() is OK\n");
// Call the user defined SetPrivilege() function to enable and set the needed privilege
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
printf("The SetPrivilege() return value: %d\n\n", test);
//************************************************
// TODO: Complete your task here
//***********************************************
// After we have completed our task, don't forget to disable the privilege
bEnablePrivilege = FALSE;
BOOL test1 = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
printf("The SetPrivilage() return value: %d\n", test1);
return 0;
}
A sample output:
OpenProcessToken() is OK
LookupPrivilegeValue() is OK
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges() is OK, last error if any: 0
Should be 0, means the operation completed successfully = ERROR_SUCCESS
The SetPrivilage() return value: 1
LookupPrivilegeValue() is OK
tp.Privileges[0].Attributes = 0
AdjustTokenPrivileges() is OK, last error if any: 0
Should be 0, means the operation completed successfully = ERROR_SUCCESS
The SetPrivilage() return value: 1
Press any key to continue
In our previous program example, we failed to set the SACL for success auditing on the directory because we don’t have the privilege. Let enable the privilege and then set the SACL using the same program example. First of all let verify through the Testdir3 directory property page.
Figure 1
Then execute our modified program.
// Modifying ACL of an object. Here we are going to
// add Allow standard right access and set an ACE for SACL.
// This Win XP machine is logged in by user named Mike
// who is a member of Administrators group...
// To access a SACL using the GetNamedSecurityInfo()
// or SetNamedSecurityInfo() functions, you have to enable
// the SE_SECURITY_NAME privilege.
#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <stdio.h>
//********* Enabling (Disabling) the privilege *********
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;
if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() error: %u\n", GetLastError());
return FALSE;
}
else
printf("LookupPrivilegeValue() is OK\n");
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
// Don't forget to disable the privilege after you enable them, don't mess up your system :-)
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}
// Enable the privilege (or disable all privileges).
if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE the function modifies privileges based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n", GetLastError());
return FALSE;
}
else
{
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());
printf("Should be 0, means the operation completed successfully = ERROR_SUCCESS\n");
}
return TRUE;
}
//************** Clean up routine ***************
void Cleanup(PSECURITY_DESCRIPTOR pSS, PACL pNewSACL)
{
if(pSS != NULL)
LocalFree((HLOCAL) pSS);
else
printf("pSS cleaning is OK\n");
if(pNewSACL != NULL)
LocalFree((HLOCAL) pNewSACL);
else
printf("pNewSACL cleaning is OK\n");
}
//******** The main() **********
int main()
{
// name of object, here we will add an ACE for a directory
LPTSTR pszObjName = "C:\\Testdir2\\Testdir3";
// type of object, file or directory, a directory
SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;
// access mask for new ACE equal to 0X11000000 - GENERIC_ALL and ACCESS_SYSTEM_SECURITY
DWORD dwAccessRights = 0X11000000;
// type of ACE, set audit for success
ACCESS_MODE AccessMode = SET_AUDIT_SUCCESS;
// inheritance flags for new ACE. The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited ACE.
DWORD dwInheritance = NO_PROPAGATE_INHERIT_ACE;
// format of trustee structure, the trustee is name
TRUSTEE_FORM TrusteeForm = TRUSTEE_IS_NAME;
// the new trustee for the ACE is set to testuser, a normal user
LPTSTR pszTrustee = "testuser";
// Result
DWORD dwRes = 0;
// Existing and new SACL pointers...
PACL pOldSACL = NULL, pNewSACL = NULL;
// Security descriptor
PSECURITY_DESCRIPTOR pSS = NULL;
// EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea;
// Verify the object name validity
if(pszObjName == NULL)
return ERROR_INVALID_PARAMETER;
else
printf("The object name is OK\n");
LPCTSTR lpszPrivilege = "SeSecurityPrivilege";
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
// Handle to the running process that is this (running) program
HANDLE hToken;
//*************** Get the handle to the process ********************
// Open a handle to the access token for the calling process. That is this running program...
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() is OK\n");
//********************* Enabling privilege ***************************
// Call the user defined SetPrivilege() function to enable privilege
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
printf("The SetPrivilege() return value: %d\n\n", test);
//********************* End enabling privilege ************************
// By assuming that we have enabled the required privilege, accomplish our task. Here, get a pointer to the existing SACL.
dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL, &pOldSACL, &pSS);
// Verify
if(dwRes != ERROR_SUCCESS)
{
printf("GetNamedSecurityInfo() Error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("GetNamedSecurityInfo() is OK\n");
// Initialize an EXPLICIT_ACCESS structure for the new ACE. For more ACE entries, declare an array of the EXPLICIT_ACCESS structure
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance= dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
// Other structure elements that might be needed...
// ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
// ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// The trustee is testuser
ea.Trustee.ptstrName = pszTrustee;
// Create a new ACL that merges the new ACE into the existing ACL.
dwRes = SetEntriesInAcl(1, &ea, pOldSACL, &pNewSACL);
if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("SetEntriesInAcl() is OK\n");
// Attach the new ACL as the object's SACL.
dwRes = SetNamedSecurityInfo(pszObjName, ObjectType, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, pNewSACL);
if(dwRes != ERROR_SUCCESS) { printf("SetNamedSecurityInfo() error %u\n", dwRes); Cleanup(pSS, pNewSACL); } else printf("SetNamedSecurityInfo() is OK\n\n");
// Disable the privilege //****************** Disabling privilege ******************* bEnablePrivilege = FALSE; BOOL test1 = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege); printf("The SetPrivilege() return value: %d\n", test1); //****************** End disabling privilege *************** // Close the process handle by calling the CloseHandle(hToken) return 0; } |
A sample output:
The object name is OK
OpenProcessToken() is OK
LookupPrivilegeValue() is OK
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges() is OK, last error if any: 0
Should be 0, means the operation completed successfully = ERROR_SUCCESS
The SetPrivilege() return value: 1
GetNamedSecurityInfo() is OK
SetEntriesInAcl() is OK
SetNamedSecurityInfo() is OK
LookupPrivilegeValue() is OK
tp.Privileges[0].Attributes = 0
AdjustTokenPrivileges() is OK, last error if any: 0
Should be 0, means the operation completed successfully = ERROR_SUCCESS
The SetPrivilege() return value: 1
Press any key to continue
Well, it seems that we have enabled the privilege successfully and set the SACL. Let verify through the Testdir3 directory property, Advanced Security Settingsproperty page.
Figure 2
Searching for a SID in an Access Token
The following example uses the OpenProcessToken() and GetTokenInformation() functions to get the group memberships in an access token. Then it uses theAllocateAndInitializeSid() function to create a SID that identifies the well-known SID of the administrator group for the local computer. Next, it uses the EqualSid()function to compare the well-known SID with the group SIDs from the access token. If the SID is present in the token, the function checks the attributes of the SID to determine whether it is enabled.
The CheckTokenMembership() function used to determine whether a specified SID is present and enabled in an access token. This function eliminates potential misinterpretations of the active group membership if changes to access tokens are made in future releases.
// Searching for a SID in an Access Token.
// This program run on the standalone Windows Xp Pro not a domain based machine...
#include <windows.h>
#include <stdio.h>
#define MAX_NAME 256
BOOL SearchTokenGroupsForSID(void)
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_GROUPS pGroupInfo;
SID_NAME_USE SidType;
char lpName[MAX_NAME];
char lpDomain[MAX_NAME];
BYTE sidBuffer[100];
PSID pSID = (PSID)&sidBuffer;
// Open a handle to the access token for the calling process, that is, this running program (process). So we get the handle
// to the token for the current user that run this program and/or login to this machine.
// Depend on your task, change the TOKEN_QUERY to others accordingly...
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() for the current process is OK\n");
// By assuming that we got the handle to the token...
// Call GetTokenInformation() to get the buffer size for storage. This is for Tokengroups, change accordingly for others such
// as TokenUser, TokenOwner, TokenType etc
if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();
if(dwResult != ERROR_INSUFFICIENT_BUFFER)
{
printf("GetTokenInformation() error %u\n", dwResult);
return FALSE;
}
else
printf("GetTokenInformation() for the buffer size is OK\n");
}
else
printf("GetTokenInformation() for storage of the Token group is OK\n");
// By assuming that we got the storage, then allocate the buffer.
pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc(GPTR, dwSize);
// Call GetTokenInformation() again to get the group information.
if(!GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize))
{
printf("GetTokenInformation() error %u\n", GetLastError());
return FALSE;
}
else
printf("GetTokenInformation() for getting the TokenGroups is OK\n");
//****************** Playing with SIDs *****************************
// Create a SID for the BUILTIN\Administrators group...
// You can try other groups also lol as commented out on the following
// codes. Uncomment/comment out the SIDs for testing....
// This is 32 bit RID value. Applications that require longer RID values,
// use CreateWellKnownSid() instead
//*********************** Administrator group ***********************
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
if(!AllocateAndInitializeSid(&SIDAuth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
return FALSE;
}
else
printf("AllocateAndInitializeSid(), SID for BUILTIN\\Administrators group is\n successfully created\n");
//************************ Local group ********************
// An example for creating a SID for the Local group...
// SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_LOCAL_SID_AUTHORITY;
//
// if(!AllocateAndInitializeSid(&SIDAuth, 1,
// SECURITY_LOCAL_RID,
// 0, 0, 0, 0, 0, 0, 0,
// &pSID))
// {
// printf("AllocateAndInitializeSid() error %u\n", GetLastError());
// return FALSE;
// }
// else
// printf("AllocateAndInitializeSid(), SID for Local group is\n successfully created\n");
//********************* Authenticated users ***********************
// Another example for creating a SID for the Authenticated users...
// SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
// if(!AllocateAndInitializeSid(&SIDAuth, 1,
// SECURITY_AUTHENTICATED_USER_RID,
// 0, 0, 0, 0, 0, 0, 0,
// &pSID))
// {
// printf("AllocateAndInitializeSid() error %u\n", GetLastError());
// return FALSE;
// }
// else
// printf("AllocateAndInitializeSid(), SID for Local group is\n successfully created\n");
//******************************************************************
// Loop through the group SIDs looking for the created group SID.
for(i=0; i<pGroupInfo->GroupCount; i++)
{
// Compare the created SID with the available group SIDs
if(EqualSid(pSID, pGroupInfo->Groups[i].Sid))
{
// Lookup the account name and print it.
dwSize = MAX_NAME;
if(!LookupAccountSid(NULL, pGroupInfo->Groups[i].Sid, lpName, &dwSize, lpDomain, &dwSize, &SidType))
{
// If not found or something wrong...
dwResult = GetLastError();
if(dwResult == ERROR_NONE_MAPPED)
strcpy(lpName, "NONE_MAPPED");
else
{
printf("LookupAccountSid() error %u\n", GetLastError());
return FALSE;
}
}
// If found...
else
{
//******************* Built-in\Administrators group *********************
printf("LookupAccountSid() for BUILTIN\\Administrators group is OK\n");
printf("Current user is a member of the %s\\%s group\n", lpDomain, lpName);
//******************* Local group ***************************************
// printf("LookupAccountSid() for Local group is OK\n");
// printf("Current user is a member of the %s group\n", lpName);
//******************** Authenticated users *******************************
// printf("LookupAccountSid() for Authenticated users is OK\n");
// printf("Current user is a member of the %s\\%s group\n", lpDomain, lpName);
}
//**************** End playing with SIDs *********************************
// Find out whether the SID is enabled in the token.
if(pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
printf("The group SID is enabled.\n");
else if (pGroupInfo->Groups[i].Attributes & SE_GROUP_USE_FOR_DENY_ONLY)
printf("The group SID is a deny-only SID.\n");
else
printf("The group SID is not enabled.\n");
}
}
// Release resources back to system
if(pSID)
FreeSid(pSID);
if(pGroupInfo)
GlobalFree(pGroupInfo);
return TRUE;
}
//******** main() ********
int main()
{
// Call the user defined SearchTokenGroupsForSID() function to search the token group SID
BOOL test = SearchTokenGroupsForSID();
// Verify
printf("The return value of SearchTokenGroupsForSID() is: %d\n", test);
return 0;
}
A sample output:
OpenProcessToken() for the current process is OK
GetTokenInformation() for the buffer size is OK
GetTokenInformation() for getting the TokenGroups is OK
AllocateAndInitializeSid(), SID for BUILTIN\Administrators group is
successfully created
LookupAccountSid() for BUILTIN\Administrators group is OK
Current user is a member of the BUILTIN\Administrators group
The group SID is enabled.
The return value of SearchTokenGroupsForSID() is: 1
Press any key to continue
<<<----------------------------------------------------- smaller version------------------------------------------------------->>>
#include <windows.h>
#include <stdio.h>
BOOL IsUserAdminGrp(void)
/*
This routine returns TRUE if the caller's process is a member of the Administrators local group. Caller is NOT expected
to be impersonating anyone and is expected to be able to open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
*/
{
BOOL check;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
check = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if(check)
{
printf("AllocateAndInitializeSid() is OK\n");
if(!CheckTokenMembership(
NULL, // uses the impersonation token of the calling thread. If the thread is not impersonating,
// the function duplicates the thread's primary token to create an impersonation token.
AdministratorsGroup, // Pointer to a SID structure
&check // Result of the SID
))
{
// If the SID (the 2nd parameter) is present and has the SE_GROUP_ENABLED attribute,
// IsMember (3rd parameter) returns TRUE; otherwise, it returns FALSE.
printf("The received value of the third parameter: %u\n", check);
check = FALSE;
printf("CheckTokenMembership() is NOT OK\n");
}
else
printf("CheckTokenMembership() is OK\n");
printf("You are Administrators Local Group lol!\n");
printf("The received value of the third parameter: %u, last error if any: %u\n", check, GetLastError());
FreeSid(AdministratorsGroup);
}
else
printf("AllocateAndInitializeSid() is NOT OK\n");
return(check);
}
int main()
{
BOOL test = IsUserAdminGrp();
printf("The return value of the IsUserAdminGrp(): %u, last error if any: %u\n", test, GetLastError());
return 0;
}
A sample output:
AllocateAndInitializeSid() is OK
CheckTokenMembership() is OK
You are Administrators Local Group lol!
The received value of the third parameter: 1, last error if any: 0
The return value of the IsUserAdminGrp(): 1, last error if any: 0
Press any key to continue
'IT-개발 > winapi 및 MFC' 카테고리의 다른 글
[Registry] 지정된 레지스트리 Key의 각종정보알기 Enumerating (0) | 2016.03.06 |
---|---|
[Registry] 유용한 Registry 관련 api - 레지스트 특정키이하 모든 Data Copy (0) | 2016.03.06 |
SeDebugPrivilege 권한 갖기~ (0) | 2016.03.06 |
(펌) 현재 프로세스의 권한과 상관없이 자식 프로세스를 관리자 또는 일반 사용자 권한으로 실행하기 (0) | 2016.03.06 |
CListCtrl 유용한 것들 (펌) (0) | 2016.01.19 |