Do I need SE_SHUTDOWN_NAME privilege to log off a user? - c++

I need to log off a user from a C++ program. I use ExitWindowsEx API for that, but I'm not sure from the documentation if I need any special privileges for that?

You do. Here's an example
bool ShutdownWindows(void)
{
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tkp = {0};
bool bRet = false;
// Get a token for this process.
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid)) {
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
if (AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0)) {
::CloseHandle(hToken);
if (ERROR_SUCCESS == GetLastError()) {
DWORD dwFlags = EWX_POWEROFF;
DWORD dwReason = SHTDN_REASON_MAJOR_SYSTEM;
if (ExitWindowsEx(dwFlags, dwReason)) {
bRet = true;
}
}
}
}
}
return bRet;
} // ShutdownWindows

Related

OpenProcessBlocked even i use SetPrivilege(hToken, SE_DEBUG_NAME, true);

I have a problem, I want to read some values with ReadProcessMemory from a process, this process blocks OpenProcess, now I heard that I just need to Privilege the file who want to do OpenProcess with SE_DEBUG_NAME.
I googled and found this function :
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege){
TOKEN_PRIVILEGES tp;
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;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;}
Now i tried the following :
bool bStart(std::string szProcessName)
{
if (szProcessName.empty())
return false;
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
SetPrivilege(hToken, SE_DEBUG_NAME, true);
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
{
std::cout << "SetPrivilege";
// close token handle
CloseHandle(hToken);
// indicate failure
return false;
}
std::cout << "hi";
HANDLE hSnapshot = (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
bool bFoundProcess = false;
PROCESSENTRY32 PE32 = { sizeof(PROCESSENTRY32) };
if (Process32First(hSnapshot, &PE32))
{
do
{
if (!szProcessName.compare(PE32.szExeFile))
{
m_dwProcessId = (XOR(PE32.th32ProcessID));
bFoundProcess = true;
break;
}
} while (Process32Next(hSnapshot, &PE32));
}
CloseHandle(m_hProcess);
if (!bFoundProcess)
return false;
m_hProcess = (XOR(OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId)));
if (m_hProcess == INVALID_HANDLE_VALUE)
return false;
return true;
}
I don't get any error or anything, but for any reason, the OpenProcess doesn't work. Can someone please help me?
Thanks in advance!
this process blocks OpenProcess
This means the game's anticheat is blocking process handle creation via a kernel mode anticheat.
There is nothing you can do to bypass this from usermode, you must also make a kernel driver and disable their protection.
The most simple way for them to prevent handle creation is with ObRegisterCallbacks so you will need to reverse engineer their implementation of that.
Keep in mind this technique is from 5+ years ago, they have much more complicated protection now.

Thread32First returning bogus thread id

Thread32First returns true so I know the function isn't failing. However, it keeps returning the same value for the th32ThreadID data member of THREADENTRY32, 0. Doesn't matter what process I try it on, it continues to be the same thread id: 0.
Here's my code:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
BOOL EnableDebugPriv(HANDLE proc);
int main()
{
HANDLE hSnapshot;
HANDLE hThread;
THREADENTRY32 thread32;
DWORD dwPid = 15404;
EnableDebugPriv(OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid));
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPid);
if(hSnapshot == INVALID_HANDLE_VALUE)
{
printf("Error getting snapshot: %lu\n", GetLastError());
return 1;
}
thread32.dwSize = sizeof(THREADENTRY32);
if(!Thread32First(hSnapshot, &thread32))
{
printf("Error thread32first\n");
return 1;
}
printf("Thread Id: %lu\n", thread32.th32ThreadID);
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread32.th32ThreadID);
if(hThread == NULL)
{
printf("Error getting handle: %lu\n", GetLastError());
return 1;
}
return 0;
}
BOOL EnableDebugPriv(HANDLE proc)
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
// pass our opened process handle
OpenProcessToken(proc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
{
CloseHandle(hToken);
return TRUE;
}
else
{
MessageBox(NULL,"Bro, you gotta be an admin to set privs like this", "Shit", MB_OK);
CloseHandle(hToken);
return FALSE;
}
}
Note: I am aware that using a static process ID like I am could cause problems. However, I make sure the process is still running with the same process ID. That's not the problem.

Not able to add Audit policy (ACE) for object access (Folder) in windows using c++

I was writing a c++ program to add ACE for object access Audit to SASL. Though all the functions return success, When I go and check the properties of the folder manually, I could not see any policy has been set.
Below is my code. I have modified the sample code given in MSDN site at the below link to add to SASL instead of DACL .
https://msdn.microsoft.com/en-us/library/windows/desktop/aa379283(v=vs.85).aspx
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;
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;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
LPTSTR pszTrustee // trustee for new ACE
)
{
DWORD dwRes = 0;
PACL pOldSACL = NULL, pNewSACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
HANDLE hToken;
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
// Open a handle to the access token for the calling process.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
printf("OpenProcessToken failed: %u\n", GetLastError());
goto Cleanup;
}
// Enable the SE_SECURITY_NAME privilege.
if (!SetPrivilege(hToken, SE_SECURITY_NAME, TRUE))
{
printf("You must be logged on as Administrator.\n");
goto Cleanup;
}
// Get a pointer to the existing SACL.
dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL, &pOldSACL, &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.grfAccessPermissions = GENERIC_ALL;
//ea.grfAccessMode = AccessMode;
ea.grfAccessMode = SET_AUDIT_SUCCESS;
//ea.grfInheritance = dwInheritance;
ea.grfInheritance = INHERIT_ONLY;
//ea.Trustee.TrusteeForm = TrusteeForm;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.ptstrName = pszTrustee;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// Create a new ACL that merges the new ACE
// into the existing SACL.
dwRes = SetEntriesInAcl(1, &ea, pOldSACL, &pNewSACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's SACL.
dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL, pNewSACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Disable the SE_SECURITY_NAME privilege.
if (!SetPrivilege(hToken, SE_SECURITY_NAME, FALSE))
{
printf("You must be logged on as Administrator.\n");
goto Cleanup;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewSACL != NULL)
LocalFree((HLOCAL)pNewSACL);
return dwRes;
}
int _tmain(int argc, _TCHAR* argv[])
{
LPTSTR objstrname = L"C:\\path\\to\\folder\\Test_Folder";
LPTSTR trusteeName = L"UserName"; // I have mentioned username here
AddAceToObjectsSecurityDescriptor(objstrname, SE_FILE_OBJECT, trusteeName);
return 0;
}
Though all the functions return success, I am not able to see any new audit policy is getting set. Might I am setting the parameters wrong, I that case I expect the functions to fail. Please help to resolve the issue.
I believe the problem is that you are setting the wrong inheritance flags.
INHERIT_ONLY means that the ACE should not apply to the object, but only be inherited by child objects.
However, you have not set either CONTAINER_INHERIT_ACE or OBJECT_INHERIT_ACE. So the ACE does not apply to child objects.
Since the ACE applies to neither the parent nor to children, it has no effect, so Windows discards it.

OpenProcess() return error access denided?

I wrote the function GetProcessHandleAndID() as below code:
bool GetProcessHandleAndID( char* _processName, PROCESS_INFORMATION* _processInfo /* out */ )
{
HANDLE SnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( SnapShot == INVALID_HANDLE_VALUE )
{
return false;
}
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( SnapShot, &procEntry ) )
{
CloseHandleSafely(SnapShot);
return false;
}
do
{
if( strcmp( procEntry.szExeFile, _processName ) == 0 )
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEntry.th32ProcessID);
if(hProcess != NULL)
{
_processInfo->hProcess = hProcess;
_processInfo->dwProcessId = procEntry.th32ProcessID;
CloseHandleSafely(SnapShot);
return true;
}
}
}
while( Process32Next( SnapShot, &procEntry ) );
CloseHandleSafely(SnapShot);
return false;
}
OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEntry.th32ProcessID)work fine on Administrator account, But it will return NULL with GetLastError() = 5 = Access_Denied when run on Normal accounts.
Note that I have called function EnableDebugPriv() before GetProcessHandleAndID().
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
CloseHandle(hToken);
}
I have search and read more about this error, but I don't know how to make it work fine on normal user without making it "Run As Administrator"!
Many thanks,
T&T

How do I check if my program is ran by user as administrator (Vista/Win7, C++) [duplicate]

This question already has answers here:
Detect if program is running with full administrator rights
(2 answers)
Closed 6 years ago.
I saw IsInRole method but I can't find information on how to use it with C++.
There's a C++ code snippet in this old answer taken from the UACHelpers project on CodePlex.
This code solves your problem. Feel free to use it. It works with SE_GROUP_USE_FOR_DENY_ONLY.
/**
IsGroupMember determines if the current thread or process has a token that contais a given and enabled user group.
Parameters
dwRelativeID: Defines a relative ID (par of a SID) of a user group (e.g. Administrators DOMAIN_ALIAS_RID_ADMINS (544) = S-1-5-32-544)
bProcessRelative: Defines whether to use the process token (TRUE) instead of the thread token (FALSE). If FALSE and no thread token is present
the process token will be used though.
bIsMember: Returns the result of the function. The value returns TRUE if the user is an enabled member of the group; otherwise FALSE.
Return Value
If the function succeeds, the return value is TRUE; otherwise FALSE. Call GetLastError for more information.
*/
BOOL IsGroupMember(DWORD dwRelativeID, BOOL bProcessRelative, BOOL* pIsMember)
{
HANDLE hToken, hDupToken;
PSID pSid = NULL;
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
if (!pIsMember)
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
if (bProcessRelative || !OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_DUPLICATE, TRUE, &hToken))
{
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken))
{
return FALSE;
}
}
if (!DuplicateToken(hToken, SecurityIdentification, &hDupToken))
{
CloseHandle(hToken);
return FALSE;
}
CloseHandle(hToken);
hToken = hDupToken;
if (!AllocateAndInitializeSid(&SidAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, dwRelativeID, 0, 0, 0, 0, 0, 0,
&pSid))
{
CloseHandle(hToken);
return FALSE;
}
if (!CheckTokenMembership(hToken, pSid, pIsMember))
{
CloseHandle(hToken);
FreeSid(pSid);
*pIsMember = FALSE;
return FALSE;
}
CloseHandle(hToken);
FreeSid(pSid);
return TRUE;
}
BOOL IsUserAdministrator(BOOL* pIsAdmin)
{
return IsGroupMember(DOMAIN_ALIAS_RID_ADMINS, FALSE, pIsAdmin);
}
The documentation of IsUSerAnAdmin explains that it's deprecated since Vista, but points you to CheckTokenMembership. That should do the job for you.
You might try this piece of code. It gives a sketch of what needs to be done:
const HANDLE hProcess = GetCurrentProcess();
if (hProcess==NULL)
return FAILURE;
HANDLE hToken;
const BOOL lR = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
if (lR == NULL)
return FAILURE;
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY x = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(
&x, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
&psidAdministrators))
return FAILURE;
bool isAdmin = false; //dummy init
DWORD size;
GetTokenInformation(hToken, TokenGroups, NULL, 0, &size);
char* buffer = new char[size];
DWORD notUsed;
if (!GetTokenInformation(hToken, TokenGroups, (void*)buffer, size, &notUsed))
return FAILURE;
TOKEN_GROUPS* ptgGroups = (TOKEN_GROUPS*)buffer;
isAdmin = false; //until proven otherwise
for (UINT32 i=0; i<ptgGroups->GroupCount; ++i)
{
if (EqualSid(psidAdministrators, ptgGroups->Groups[i].Sid))
{
isAdmin = true;
break;
}
}
FreeSid(psidAdministrators);
return isAdmin;