How to check if a process has the administrative rights - c++

How do I properly check if a process is running with administrative rights?
I checked the IsUserAnAdim function in MSDN, but it is not recommended as it might be altered or unavailable in subsequent versions of Windows. Instead, it is recommended to use the CheckTokenMembership function.
Then I looked at the alternate example in MSDN from a description of the CheckTokenMembership function. However, there is Stefan Ozminski's comment in MSDN that mentions that this example does not work properly in Windows Vista if UAC is disabled.
Finally I tried to use Stefan Ozminski's code from MSDN, but it determines that the process has administrative rights even if I launch it under an ordinary user without the administrative rights in Windows 7.

This will tell you if you are running with elevated privileges or not. You can set the manifest to run with most possible if you want it to prompt. There are also other ways to ask windows through code for alternate credentials.
BOOL IsElevated( ) {
BOOL fRet = FALSE;
HANDLE hToken = NULL;
if( OpenProcessToken( GetCurrentProcess( ),TOKEN_QUERY,&hToken ) ) {
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof( TOKEN_ELEVATION );
if( GetTokenInformation( hToken, TokenElevation, &Elevation, sizeof( Elevation ), &cbSize ) ) {
fRet = Elevation.TokenIsElevated;
}
}
if( hToken ) {
CloseHandle( hToken );
}
return fRet;
}

You can use LsaOpenPolicy() function.
The LsaOpenPolicy function opens a handle to the Policy object on a local or remote system.
You must run the process "As Administrator" so that the call doesn't fail with ERROR_ACCESS_DENIED.
Source: MSDN

Related

TerminateProcess not working for specific processes

I need to terminate some processes before my program can run, but whenever I run TerminateProcess(), GetLastError() returns 5. What I know so far is that this means that access is denied, I also know that to elevate my rights i need to use AdjustTokenPrivileges(), based on Rango's answer here and Microsoft's documentation here.
What i don't know is why it wont work. Based on what I've read, the following should work:
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_ALL_ACCESS;
//DWORD dwDesiredAccess = ACCESS_SYSTEM_SECURITY;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = NULL;
TOKEN_PRIVILEGES tp = { 0 };
LUID luid;
LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hProcess, FALSE, &tp, 0, NULL, NULL);
hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
As you can tell from the above, I am not sure which dwDesiredAccess I am supposed to use. PROCESS_ALL_ACCESS lets me terminate other simple processes, such as chrome.exe or notepad.exe, but not what i need to terminate. ACCESS_SYSTEM_SECURITY is whats' said to be used by microsoft, but then i cannot terminate any process at all.
Also, is this even close to what i need to do, if not can you please point me in the right direction.
UPDATE: Added UpdatePrivilege() function from here, and called it before calling OpenProcess() function, still no bite.
UPDATE 2: The process I need to terminate is the "afwServ.exe" process, i.e. Avast's firewall. I need to do this so that my firewall is the sole firewall used by Windows. This a requirement of my project.
I think you misunderstood the difference between right and privileges, this answer explains it.
In this case, your current user may not have permission to terminate the specified process. You may first need to use LogonUser and use administrator identity to simulate the process context.
What you want to terminate is a service, you can try using ControlService with SERVICE_CONTROL_STOP to stop the services. But you also need to switch to the user with permission first.

Proper use of RegOpenCurrentUser

I went here and made a test program to see if it actually disables the task manager. Basically a simple bool switch on then switch off to see if the task manager was actually disabled. It works as intended when i compiled and ran it.
Edit: the code now looks like this
#include <iostream>
#include <Windows.h>
using namespace std;
void LockTaskManager(bool Lock);
void main(void) {
LockTaskManager(true);
cout << "Testing task manager disable." << endl;
getchar();
LockTaskManager(false);
cout << "Testing task manager enabled." << endl;
getchar();
}
void LockTaskManager(bool Lock)
{
HKEY currKey;
DWORD dwDisposition;
DWORD dwType, dwSize;
DWORD value;
if (Lock)
value = 1;
else
value = 0;
LRESULT lResult = RegOpenCurrentUser(KEY_WRITE, &currKey);
if (RegCreateKeyEx(currKey,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\system"),
0,
NULL,
0,
KEY_SET_VALUE,
NULL,
&currKey,
&dwDisposition) == ERROR_SUCCESS)
{
dwType = REG_DWORD;
dwSize = sizeof(DWORD);
RegSetValueEx(currKey, TEXT("DisableTaskMgr"), 0, dwType, (PBYTE)&value, dwSize);
RegCloseKey(currKey);
}
}
However, after i moved the .exe to a guest user on the same computer, it does not disable the task manager. So i went to look into how and why it worked, from microsoft's MSDN here i found that HKEY_CURRENT_USER does not change and requires the use of RegOpenCurrentUser to set the current key to the user that is running that program. i know about this post but the answer is not conclusive.
So with that said, I wish to know the correct way to approach this. The goal here is to make whoever that runs the .exe of this code be unable to run task manager.
FYI, Just so whoever reads this knows, i intend to use this as a defense mechanism in the event a flag is triggered, i want to stop malicious entities from killing this process through task manager.
what is HKEY_CURRENT_USER ? this is really \REGISTRY\USER\<UserSid> where <UserSid> some sid. when process first time use HKEY_CURRENT_USER (root of the current user key is yet not opened) system query current user sid ( TokenUser ), convert sid to string, append \REGISTRY\USER\ prefix, open and cache opened key. when process next time use, HKEY_CURRENT_USER - used already opened and cached key. even if thread is impersonating - this change nothing. however some time we need access different user key, after impersonating. exactly for this situation and RegOpenCurrentUser and used. this api query current thread (or process) token for TokenUser, format path based on current user sid, open \REGISTRY\USER\<UserSid1> and return handle to you. it not cache this handle, instead you must close it, when you no longer need the returned handle.
so at first senseless use RegOpenCurrentUser if you not impersonating current thread.
at second, this code always senseless:
LRESULT lResult = RegOpenCurrentUser(KEY_READ, &hkey);
if (RegCreateKeyEx(HKEY_CURRENT_USER,..
you not use returned hKey anyway. what sense open it in this case ?
need use it in place HKEY_CURRENT_USER !
LRESULT lResult = RegOpenCurrentUser(KEY_READ, &hkey);
if (RegCreateKeyEx(hKey,..
why code not worked under guest ? when you call RegCreateKeyEx and resulting key (system in your case) yet not exist - you need have KEY_CREATE_SUB_KEY access to the parent (Policies key). however by default guest have not any write access to key. you simply have not KEY_CREATE_SUB_KEY access. and KEY_SET_VALUE you also have not. sure that under guest call RegCreateKeyEx return ERROR_ACCESS_DENIED to you.

C++ program needs an file association

I'm distributing a freeware product that reads and writes text files with a unique extension. I hoped that double-clicking such a file would automatically start the app.
While developing on Windows 7 Professional, I set up an association to open my files upon double-click, by right-clicking the file->Open With...->Choose Default Program...->Browse... followed by "Always use the selected program to open this type of file." Good. It did just what it needed to. I was going to ship my program with instructions for the users to do the same.
However, when I moved the location of the binary, I see the "Always use" is now grayed out/insensitive, so while I could browse to the new binary I couldn't make it default. Since I thought my users would have trouble with this too, I wanted to see if I could have installation or run of the program take care of the mapping.
I looked at Windows Installer for about 5 minutes before determining it was far more power and complexity than I needed (For my needs, a zip file would be sufficient except for this file mapping.)
So I took a look at having my program, at start-up, set up the mapping itself if it wasn't there already. (I know this would be very bad behavior if we were talking about a common file type such as .html or .jpg, but in this case its some .blahblah extension that surely no-one else uses for anything.)
Based on information at http://www.cplusplus.com/forum/windows/26987/ and http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx I was able to have my program, at startup, open HKEY_CLASSES_ROOT\.blahblah and confirm (and change if needed) the default text to be an accurate description of the file (replacing some text that may have been created by default when I did the manual association last summer). However, when it came to creating HKEY_CLASSES_ROOT\firm.app.1\shell\open\command, my RegCreateKeyEx() wrapper that works fine to change the value of \.blahblah is now giving return code 5, apparently a lack of permission.
Upon further research it seems that the permissions model may cause all such requests to fail. Can anyone confirm or deny this? If confirm, is there a good reference I should study on the matter?
Otherwise, what are the suggestions? Should I bite the bullet and study Windows Installer? Or is there a way to get the permissions I need to edit the registry when my own software starts the first time?
Note I'm developing with Visual Studio 2008 on Windows 7 Professional, and although still an amateur Windows programmer I've been doing C++ since the '80s on Unix/Linux...
OK, I got it working and I'll share what I learned.
1) Decide a ProgID. It should be vender.app.versionnumber according to docs, but regedit shows that practically no vendor follows that rule. I did though.
2) Most of the MSFT docs on this topic talk about creating entries under HKEY_CLASSES_ROOT, but I found important info on http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx:
Important considerations about file types include: The
HKEY_CLASSES_ROOT subtree is a view formed by merging
HKEY_CURRENT_USER\Software\Classes and
HKEY_LOCAL_MACHINE\Software\Classes In general, HKEY_CLASSES_ROOT is
intended to be read from but not written to. For more information, see
the HKEY_CLASSES_ROOT article.
3) to have the association show up without rebooting, you must call SHChangeNotify(). (This threw me, because even when I had the right code, the results didn't show up correctly in Explorer.)
Here's the code I ended up with. If I go through with REGEDIT and delete all mention of .moselle (my extention) and MoselleIDE (my application) then run my program once by hand, I get the click-to-open behavior, file icon becomes the same as the app, etc. Note the code uses a logging function, and it also verbosely reports which type of success it has: 1) variable already correct, 2) variable changed, 3) variable didn't exist.
void RegSet( HKEY hkeyHive, const char* pszVar, const char* pszVa
lue ) {
HKEY hkey;
char szValueCurrent[1000];
DWORD dwType;
DWORD dwSize = sizeof( szValueCurrent );
int iRC = RegGetValue( hkeyHive, pszVar, NULL, RRF_RT_ANY, &dwType, szValueCurrent, &dwSize );
bool bDidntExist = iRC == ERROR_FILE_NOT_FOUND;
if ( iRC != ERROR_SUCCESS && !bDidntExist )
AKS( AKSFatal, "RegGetValue( %s ): %s", pszVar, strerror( iRC ) );
if ( !bDidntExist ) {
if ( dwType != REG_SZ )
AKS( AKSFatal, "RegGetValue( %s ) found type unhandled %d", pszVar, dwType );
if ( strcmp( szValueCurrent, pszValue ) == 0 ) {
AKS( AKSTrace, "RegSet( \"%s\" \"%s\" ): already correct", pszVar, pszValue );
return;
}
}
DWORD dwDisposition;
iRC = RegCreateKeyEx( hkeyHive, pszVar, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition );
if ( iRC != ERROR_SUCCESS )
AKS( AKSFatal, "RegCreateKeyEx( %s ): %s", pszVar, strerror( iRC ) );
iRC = RegSetValueEx( hkey, "", 0, REG_SZ, (BYTE*) pszValue, strlen( pszValue ) + 1 );
if ( iRC != ERROR_SUCCESS )
AKS( AKSFatal, "RegSetValueEx( %s ): %s", pszVar, strerror( iRC ) );
if ( bDidntExist )
AKS( AKSTrace, "RegSet( %s ): set to \"%s\"", pszVar, pszValue );
else
AKS( AKSTrace, "RegSet( %s ): changed \"%s\" to \"%s\"", pszVar, szValueCurrent, pszValue );
RegCloseKey(hkey);
}
int SetUpRegistry() {
//app doesn't have permission for this when run as normal user, but may for Admin? Anyway, not needed.
//RegSet( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\MoselleIDE.exe", "C:\\Moselle\\bin\\MoselleIDE.exe" );
RegSet( HKEY_CURRENT_USER, "Software\\Classes\\.moselle", "Moselle.MoselleIDE.1" );
// Not needed.
RegSet( HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\Content Type", "text/plain" );
RegSet( HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\PerceivedType", "text" );
//Not needed, but may be be a way to have wordpad show up on the default list.
//RegSet( HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\OpenWithProgIds\\Moselle.MoselleIDE.1", "" );
RegSet( HKEY_CURRENT_USER, "Software\\Classes\\Moselle.MoselleIDE.1", "Moselle IDE" );
RegSet( HKEY_CURRENT_USER, "Software\\Classes\\Moselle.MoselleIDE.1\\Shell\\Open\\Command", "C:\\Moselle\\bin\\MoselleIDE.exe %1" );
SHChangeNotify( SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL );
return 0;
}
Finally, yes, I know I should figure out an installer, but I'm a C++ expert, not a Windows configuration and terminology expert and its a lot easier for me to write the above 50 lines than it is to even start figuring out how to configure an installer. This is for an alpha release and I'll watch this topic for better ideas for future releases.
Registry changes and all actions that require higher permissions should be done at installation stage, not at application startup. You probably want to use installation software. Otherwise your software will create serious security breach.

Creating a registry key - access denied

Hi I am trying to create a registry key in C++ but I keep getting the error 5 which googling told me it was access denied but I don't know to do get the correct privileges. I'm using windows 7 and here's my code. Thanks
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR szValueBuf = NULL;
char szProductName[MAX_PATH];
LPSECURITY_ATTRIBUTES lpsa;
HKEY hOrchKey;
DWORD dwOpenStatus,
dwType;
char szProuductKey[MAX_PATH];
hr = WcaInitialize(hInstall, "CreateProductKey");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
if (!(lpsa = default_sa()))
return FALSE;
hr = WcaGetProperty(L"PRODUCTNAME",&szValueBuf);
ExitOnFailure(hr, "failed to get Product Name");
wcstombs(szProductName, szValueBuf, 260);
sprintf(szProuductKey,"SOFTWARE\\Company\\%s",szProductName);
// Open the registery Orchestrator key
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
szProuductKey,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE,
lpsa,
&hOrchKey,
&dwOpenStatus) != ERROR_SUCCESS )
return FALSE;
OS_RegCloseKey(hOrchKey);
return TRUE;
Run as administrator to run it with elevated access.
You must access the registry key HKEY_LOCAL_MACHINE as administrator in order to edit values. (e.g. If you wanted to edit the key via the Registry Editor application, then you would have to right click and select "run as administrator") Since you want to write the values in code, so you need to set your compiler to have administrator rights when you run it. In Visual Studio 2008 this can be done in the Properties Page of your solution, you set it to run as admin.
Heres how to do it; Right click your solution in the Solution Explorer and select Properties; Go to Configuration Properties->Linker->Manifest File; Set UAC Execution Level as "requireAdministrator".
Next time you hit run, it should prompt you to open it as admin, and then it'll allow you to change the key. I'm not sure how to do this with other compilers, but it should be relatively the same. However, it will always ask you for admin rights, even in the release, not ideal for most programs. If this is an installer or something, then Id say that'd be fine, but if this is an app that'll be run a lot, Id suggest using HKEY_LOCAL_USER, it doesn't require admin rights. I recently went through all that malarkey and the registry is a bitch to get right, so I'd suggest avoiding it as much as possible!
Hope that helps!

How to check if a process is running or not using C++

I should not display certain context menu options if one process is not running?.
I am checking if the process is running or not using the process name.
But the issue is, the process name is showing different way in different windows platforms.
ie, windows 64 bit process name on windows task bar is " applicationname.exe"
some windows xp machine shows the same process name as "applica~2.exe"
Please let me know the consistent way to check if the process is running or not?
My development environment is C++ and Visual Studio 2010
DWORD getProcessID(const std::wstring& processName)
{
PROCESSENTRY32 info;
info.dwSize = sizeof(info);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if ( snapshot == INVALID_HANDLE_VALUE )
return 0;
Process32First(snapshot, &info);
if ( !processName.compare(info.szExeFile) )
{
CloseHandle(snapshot);
return info.th32ProcessID;
}
while ( Process32Next(snapshot, &info) )
{
if ( !processName.compare(info.szExeFile) )
{
CloseHandle(snapshot);
return info.th32ProcessID;
}
}
CloseHandle(snapshot);
return 0;
}
EnumProcesses is the other way to enumerate active processes.
The difference is that you need to allocate the space for PIDs,call EnumProcesses, open each process with PROCESS_QUERY_INFORMATION access flag and then call GetProcessImageFileName on it's handle and do the comparison.
Using WMI to interrogate instances of Win32_Process allows you to check the fullpath of the running processes for a match on the one you need to see.
Are you the author of the process in question? If so, a more robust design would be to use IPC to interrogate the process directly. That way, you don't necessarily have to poll and you don't have irritating issues such as what happens if you detect the process, create the context menu and then the process goes down?