Can't disable SeDebugPrivilege of my own process - c++

I am trying to disable my own process's SE_DEBUG_NAME (SeDebugPrivilege) permissions to learn about adjusting tokens in processes.
Like I am doing with Process Hacker. I have an option to change this permissions to remote processes.
But for the beginning I want to be able to change my own process's token permissions.
I am running Visual Studio with Run As administrator and therefore my process has High integrity and SeDebugPrivilege is enabled.
I read here and took the code from here and made a little change, instead of enabling I changed it to disabling:
#include "stdafx.h"
#include <Windows.h>
#include <sddl.h>
#include <cstdio>
#include <tlhelp32.h>
#include <iostream>
#include <fstream>
using namespace std;
//#pragma comment(lib, "cmcfg32.lib")
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;
}
int main()
{
HANDLE hToken;
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return RTN_ERROR;
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) {
//DisplayError("OpenThreadToken");
return RTN_ERROR;
}
}
else
return RTN_ERROR;
}
// disable SeDebugPrivilege
if (!SetPrivilege(hToken, SE_DEBUG_NAME, FALSE))
{
// DisplayError("SetPrivilege");
// close token handle
CloseHandle(hToken);
// indicate failure
return RTN_ERROR;
}
return 0;
}
I am running it on debug mode but I don't see any changes on the process's token. The SeDebugPrivilege is still enabled.
I don't receive any errors.
Any idea what can be the problem ?

I understood what was my problem.
I needed to use OpenProcessToken.
So I only needed to change the beginning of the main:
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
if (hProc == NULL)
{
// error
}
HANDLE hToken;
if (!OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, &hToken))
{
// error
}

Related

Token impersonation on Windows requires administrator permission Why?

#include <windows.h>
#include <iostream>
#include <Lmcons.h>
#include <conio.h>
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;
}
int main(int argc, char** argv) {
// Print whoami to compare to
thread later
printf("[+] Current user is:
%s\n"); //
(get_username()).c_str());
system("whoami");
// Grab PID from command line
argument
char *pid_c = argv[1];
DWORD PID_TO_IMPERSONATE = 900;
// Initialize variables and
structures
HANDLE tokenHandle = NULL;
HANDLE duplicateTokenHandle =
NULL;
STARTUPINFOW startupInfo;
PROCESS_INFORMATION
processInformation;
ZeroMemory(&startupInfo,
sizeof(STARTUPINFO));
ZeroMemory(&processInformation,
sizeof(PROCESS_INFORMATION));
startupInfo.cb =
sizeof(STARTUPINFO);
// Add SE debug privilege
HANDLE currentTokenHandle =
NULL;
BOOL getCurrentToken =
OpenProcessToken
(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&currentTokenHandle);
if
(SetPrivilege
(currentTokenHandle,
"SeDebugPrivilege", TRUE))
{
printf("[+] SeDebugPrivilege
enabled!\n");
}
// Call OpenProcess(), print
return code and error code
HANDLE processHandle =
OpenProcess
(PROCESS_QUERY_INFORMATION,
true, PID_TO_IMPERSONATE);
if (GetLastError() == NULL)
printf("[+] OpenProcess()
success!\n");
else
{
printf("[-] OpenProcess()
Return Code: %i\n",
processHandle);
printf("[-] OpenProcess()
Error: %i\n",
GetLastError());
}
// Call OpenProcessToken(),
print return code and error
code
BOOL getToken =
OpenProcessToken
(processHandle,
TOKEN_DUPLICATE |
TOKEN_ASSIGN_PRIMARY |
TOKEN_QUERY, &tokenHandle);
if (GetLastError() == NULL)
printf("[+]
OpenProcessToken()
success!\n");
else
{
printf("[-]
OpenProcessToken() Return
Code: %i\n", getToken);
printf("[-] OpenProcessToken()
Error: %i\n",
GetLastError());
}
// Impersonate user in a
thread
BOOL impersonateUser =
ImpersonateLoggedOnUser
(tokenHandle);
if (GetLastError() == NULL)
{
printf("[+]
ImpersonatedLoggedOnUser()
success!\n");
// printf("[+] Current
user is: %s\n",
(get_username()).c_str());
system("whoami");
printf("[+] Reverting thread
to original user context\n");
RevertToSelf();
}
else
{
printf("[-]
ImpersonatedLoggedOnUser()
Return Code: %i\n", getToken);
printf("[-]
ImpersonatedLoggedOnUser()
Error: %i\n", GetLastError());
}
// Call DuplicateTokenEx(),
print return code and error
code
BOOL duplicateToken =
DuplicateTokenEx(tokenHandle,
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID |
TOKEN_QUERY | TOKEN_DUPLICATE
| TOKEN_ASSIGN_PRIMARY, NULL,
SecurityImpersonation,
TokenPrimary,
&duplicateTokenHandle);
if (GetLastError() == NULL)
printf("[+] DuplicateTokenEx()
success!\n");
else
{
printf("[-] DuplicateTokenEx()
Return Code: %i\n",
duplicateToken);
printf("[-] DupicateTokenEx()
Error: %i\n", GetLastError());
}
// Call
CreateProcessWithTokenW(),
print return code and error
code
BOOL createProcess =
CreateProcessWithTokenW
(duplicateTokenHandle,
LOGON_WITH_PROFILE,
L"C:\\Windows\
\System32\\cmd.exe", NULL,
0, NULL, NULL, &startupInfo,
&processInformation);
if (GetLastError() == NULL)
printf("[+] Process
spawned!\n");
else
{
printf("[-]
CreateProcessWithTokenW
Return Code: %i\n",
createProcess);
printf("[-]
CreateProcessWithTokenW Error:
%i\n", GetLastError());
}
getch();
return 0;
}
This is a code that impersonates Winlogon Access token on Windows to give me System rights but it requires me to run the program as administrator before I'm able to impersonate Winlogon...
I believe the reason is based on lack of privileges my program access token has.
If there's anyone that can give me an idea to do this without running as administrator first I'll appreciate.
What it actually requires is that the account holds the SE_IMPERSONATE_NAME privilege and the particular process having it enabled. Normally only highly trusted accounts (an elevated Administrator token or Local System used by default for services) have this privilege but you can assign it to others through the "Local Users and Groups" (or "Active Directory Users and Computers" if using AD) MMC snap-in.

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.

AdjustTokenPrivileges error 6 - handle invalid

Please advise why the AdjustTokenPrivileges function below always returns true, thus giving: "AdjustTokenPrivileges error 6" (ie invalid handle)?
stackoverlow is complaining that I didn't explain this enough
I don't know what else to add. I'm new to c++.
HANDLE hToken;
OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
SetPrivilege(hToken,L"SeBackupPrivilege",1 );
CloseHandle(hToken);
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES oldtp; /* old token privileges */
TOKEN_PRIVILEGES tp;
DWORD dwSize = sizeof (TOKEN_PRIVILEGES);
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) &oldtp,
(PDWORD) &dwSize) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); //Get error 6 here (ie invalid handle)
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
You should request for TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY and correctly call the function:
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
And please: Always check for valid return values!
For a complete example see also: How to Shut Down the System
And just for reference: Your function SetPrivilege was copied from Enabling and Disabling Privileges in C++
&hToken -> hToken
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) &oldtp,
(PDWORD) &dwSize) )

RegLoadKey is giving error code 5 (Access Denied)

Hi I'm trying to load a key from HKLM\\SYSTEM\\CurrentControlSet\\Services\\Fax but i'm getting error 5 (Access Denied). I'm not able to figure it out what is wrong with my code.
Here is my code
#include <windows.h>
#include <tchar.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_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;
}
void _tmain(int argc, TCHAR *argv[])
{
HKEY hKey;
LONG lErrorCode;
HANDLE ProcessToken;
LPCWSTR subkey = L"SYSTEM\\CurrentControlSet\\Services\\Fax";
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken))
{
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
}
lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,subkey ,
0, KEY_ALL_ACCESS, &hKey);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegOpenKeyEx (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully Opened\n"));
}
lErrorCode = RegSaveKey(hKey,L"c:\\load.reg",0);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegSaveKey (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully Saved \n"));
}
lErrorCode = RegLoadKey(HKEY_LOCAL_MACHINE,subkey,L"c:\\load.reg");
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegLoadKey (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully loaded \n"));
}
lErrorCode = RegCloseKey(hKey);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in closing the key (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully closed \n"));
}
}
This is the output
Key is successfully Opened
Key is successfully Saved
Error in RegLoadKey (5).
RegLoadKey can only be used to load a new hive into the registry. You can't use it to overwrite a subkey of an existing hive.
You probably want to use RegRestoreKey instead.
Additional:
To the best of my knowledge, hives can only be loaded at a registry root, i.e., they must be HKEY_LOCAL_MACHINE\foo or HKEY_USERS\foo, never HKEY_LOCAL_MACHINE\foo\bar. Also, I don't think you can load a hive with a name that already exists, e.g., you can't load a hive into HKEY_LOCAL_MACHINE\SOFTWARE. Even if you could do these things, you'd be changing your view of the content, not merging it, and when the system was rebooted the original content would reappear. As previously mentioned, if you want to insert data into an existing hive, use RegRestoreKey rather than RegLoadKey.
You ask about the use cases for RegLoadKey: there aren't many. Mostly, it's used by the operating system; for example, that's how your personal hive is loaded into HKEY_USERS\username when you log in. There are some oddball cases, such as resetting a password offline or otherwise modifying the registry of another Windows instance. The process I use for the unattended installation of Windows on the computers in my teaching lab depends on modifying the registry of the Windows installation image to disable the keyboard and mouse.