I want to get executable path of csrss process. I enabled privileges, but GetLastError() function returns error 5 in OpenProcess. I'm running Visual Studio as administrator and compiling program in 64bit mode, also I'm using Windows 8. Thanks to all.
HANDLE hcurrentProcess=GetCurrentProcess();
HANDLE hToken;
size_t error;
if (!OpenProcessToken(hcurrentProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return nullptr;
if (CheckTokenPrivilege(hcurrentProcess, SE_DEBUG_NAME)) {
LUID luid;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
return nullptr;
TOKEN_PRIVILEGES newState,prvsState;
DWORD length;
newState.PrivilegeCount = 1;
newState.Privileges[0].Luid = luid;
newState.Privileges[0].Attributes = 2;
AdjustTokenPrivileges(hToken, FALSE, &newState, 28, &prvsState, &length);
error = GetLastError(); //error = 0
if (error == ERROR_NOT_ALL_ASSIGNED)
return nullptr;
//OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, 876); also error 5
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 876);
error = GetLastError(); } // error 5 Access is denied
csrss.exe is a Protected Processes Light process, this protection was introduced in Windows 8.1. You can no longer access it even with a low permission like PROCESS_VM_READ as a local System user, even with SeDebugPrivelage
Rather than what you're doing, just use GetSystemDirectory() and then append "csrss.exe" on the end of it's result to get the path of the file.
Related
I am working on file virtualization and versioning project. For that, I need to access the logical blocks of file contents directly without copying into memory. Anyone could you help me with code snippets that works on my 64 bit windows?
I tried the following code to access the MFT file. But it responds like 'Access denied' even though I ran with administrator privileges.
#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
// Format the Win32 system error code to string
void ErrorMessage(DWORD dwCode);
int wmain(int argc, WCHAR **argv){
HANDLE hVolume;
WCHAR lpDrive[] = L"\\\\.\\C:";
PNTFS_VOLUME_DATA_BUFFER ntfsVolData = {0};
BOOL bDioControl = FALSE;
DWORD dwWritten = 0;
hVolume = CreateFile(lpDrive, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hVolume == INVALID_HANDLE_VALUE){
wprintf(L"CreateFile() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
else
wprintf(L"CreateFile() is pretty fine!\n");
ntfsVolData = (PNTFS_VOLUME_DATA_BUFFER)malloc(sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA));
bDioControl = DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, ntfsVolData,sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA), &dwWritten, NULL);
if(bDioControl == 0){
wprintf(L"DeviceIoControl() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
getchar();
}
void ErrorMessage(DWORD dwCode){
DWORD dwErrCode = dwCode;
DWORD dwNumChar;
LPWSTR szErrString = NULL; // will be allocated and filled by FormatMessage
dwNumChar = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM, 0, dwErrCode, 0, (LPWSTR)&szErrString, 0,0 ); // since getting message from system tables
if(dwNumChar == 0)wprintf(L"FormatMessage() failed, error %u\n", GetLastError());//else//wprintf(L"FormatMessage() should be fine!\n");
wprintf(L"Error code %u:\n %s\n", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
if(LocalFree(szErrString) != NULL)
wprintf(L"Failed to free up the buffer, error %u\n", GetLastError());//else//wprintf(L"Buffer has been freed\n");
}
CreateFile() failed!
Error code 5:
Access is denied.
hVolume handle was closed successfully!
DeviceIoControl() failed!
Error code 6:
The handle is invalid.
hVolume handle was closed successfully!
Thank you
Admin privileges aren't enough. What you need to do is request backup and restore privileges for your process. MSDN has sample code. Keep in mind that you probably need both SE_BACKUP_NAME and SE_RESTORE_NAME.
The process is a bit cumbersome:
Use OpenProcessToken on your process with TOKEN_ADJUST_PRIVILEGES
Use LookupPrivilegeValue to get the privilege based on the string constants (one for SE_BACKUP_NAME, one for SE_RESTORE_NAME)
Use AdjustTokenPrivileges to acquire the backup and restore privileges
If you do this properly, the rest of your code should work. To actually enumerate the MFT, you'll want to use the FSCTL_ENUM_USN_DATA variant of DeviceIOControl.
Hi,
I'm trying to send messages between applications that are located on different desktops. In order to accomplish this, I'm using BroadCastSystemMessage using BSM_ALLDESKTOPS set for LPDWORD lpdwRecipients parameter.
As the MSDN documentation says, BSM_ALLDESKTOPS - Broadcast to all desktops. Requires the SE_TCB_NAME privilege.
In order to meet this requirement I've found the following example which generates the ERROR_NOT_ALL_ASSIGNED, with the code 1300 - Not all privileges or groups referenced are assigned to the caller, in the last if statement:
BOOL GrantPrivilege::SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
{
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. %u\n ", GetLastError());
return FALSE;
}
return TRUE;
}
Maybe the error is caused by the way I'm making the call for this function:
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
printf("%u", GetLastError());
GrantPrivilege gPriv;
gPriv.SetPrivilege(hToken, L"SeTcbPrivilege", true);
P.S. I've tried runing this application from an elevated prompt, but the result is the same, 1300 error code.
This error code means that current windows user is not allowed to use this privilege (this is why these are privileges, after all: not everyone have them). It is possible to grant a user such privilege, but I strongly advise against it. Instead, you should use some other form of inter-process communication. If you only need a signal without data, named event should be good. Otherwise, it could be a named pipe, socket, or shared memory section.
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.
I use the CreateProcess() function to launch the rdp client app using "mstsc.exe". After that, I want to terminate it so I use TerminateProcess() function, but it fails with error code of 5. If I replace the "mstsc.exe" with "notepad.exe", the terminate function works. The code are as follows:
TCHAR szCommandLine[] = TEXT("mstsc.exe");
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi;
BOOL bResult = CreateProcess(NULL, szCommandLine, NULL, NULL,
FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
::Sleep(3000);
if (TerminateProcess(pi.hProcess, 0) == 0) {
printf("failed: %d", GetLastError());
}
Can anyone help explain it and solve it?
What I observed is that the pid of the pi returned is different from the id of the process "mstsc.exe" observed in taksmanager or "Process Explorer".
Is your host process 32-bit and you are running on 64-bit windows?
If so, you are invoking the 32-bit mstsc and it is spawning a 64-bit version, hence the different PID. Check out this thread
You must gain the privilege before terminating another process.
Try this:
void UpdatePrivilege(void)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
{
LookupPrivilegeValue(NULL,SE_DEBUG_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
}
}
Call this function before calling TerminateProcess.
I have a VC++ console app and I need to check to see if another process is running. I don't have the window title, all I have is the executable name. How do I get the process handle / PID for it? Can I enumerate the processes running with this .exe ?
Use the CreateToolhelp32Snapshot Function
hSnapShot = FCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Followed by Process32First and Process32Next.
You will get a PROCESSENTRY32 struct as follows with an szExeFile member.
PROCESSENTRY32W processInfo;
processInfo.szExeFile
Make sure to first acquire the privilege SeDebugPrivilege before enumerating, that way you will get all processes across all sessions and users.
To acquire the privilege so you get all sessions:
acquirePrivilegeByName(SE_DEBUG_NAME);// SeDebugPrivilege
Where acquirePrivilegeByName is defined as:
BOOL acquirePrivilegeByName(
const TCHAR *szPrivilegeName)
{
HANDLE htoken;
TOKEN_PRIVILEGES tkp;
DWORD dwerr;
//---------------- adjust process token privileges to grant privilege
if (szPrivilegeName == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!LookupPrivilegeValue(NULL, szPrivilegeName, &(tkp.Privileges[0].Luid)))
return FALSE;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken))
return FALSE;
if (!AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, NULL) ||
GetLastError() != ERROR_SUCCESS) // may equal ERROR_NOT_ALL_ASSIGNED
{
dwerr = GetLastError();
CloseHandle(htoken);
SetLastError(dwerr);
return FALSE;
}
CloseHandle(htoken);
SetLastError(ERROR_SUCCESS);
return TRUE;
} //acquirePrivilegeByName()
If you need the full process image name you can use QueryFullProcessImageName, but the szExeFile member may be enough for your needs.
You can use EnumProcesses to enumerate the processes on a system.
You'll need to use OpenProcess to get a process handle, then QueryFullProcessImageName to get the processes executable.