Proper use of RegOpenCurrentUser - c++

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.

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.

Check a user is an admin on local machine in C++ in Windows

I am trying to find a solution or winapi to check if a username is admin or not on the local machine.
The process is running under Windows Credential Provider so I believe checking the current user thread won't give me the value I want.
Please note, that I have gone through the other answers in StackOverflow
which points to MSDN which evaluates current thread's user access token.
I have the username for which I need to find the access information, whether user has admin access rights on the current machine
Any pointers or suggestions are welcome.
I'm not sure it'll do what you want, but NetUserGetInfo has a field that's at least pretty similar to what you seem to be asking for:
bool is_user_admin()
{
bool result;
DWORD rc;
wchar_t user_name[256];
USER_INFO_1 *info;
DWORD size = sizeof( user_name );
GetUserNameW( user_name, &size);
rc = NetUserGetInfo( NULL, user_name, 1, (byte **) &info );
if ( rc != NERR_Success )
return false;
result = info->usri1_priv == USER_PRIV_ADMIN;
NetApiBufferFree( info );
return result;
}
There's also LsaEnumerateAccountRights, but (if memory serves) this only shows rights/privileges assigned directly to the account in question, not those it gets via group membership and such (but it's been quite a while and my memory's a long ways from perfect).

Can't load 64-bit key using RegLoadKey in 32-bit service

I need to open up and modify a user's registry key from a 32-bit service (note that the user is not logged in at the time.) I do the following:
//For simplicity error checks are not shown
//I also made sure to enable the following privileges:
// SE_RESTORE_NAME, SE_BACKUP_NAME
//"ntuser.dat" = is the file OS uses to load user's profile
if(RegLoadKey(HKEY_LOCAL_MACHINE, L"Test123", L"C:\\Users\\UserA\\ntuser.dat") == ERROR_SUCCESS)
{
HKEY hKey;
DWORD dwRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"Test123\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotify"),
NULL, KEY_READ | KEY_WOW64_64KEY, &hKey);
//'dwRes' = is returned as 2, or ERROR_FILE_NOT_FOUND
RegUnLoadKey(HKEY_LOCAL_MACHINE, L"Test123");
}
The problem is that the Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify key isn't loaded, even though I know that it exists in the actual user profile. I can verify that by loading the user account and by using 64-bit regedit.
I suspect that this has something to do with the Wow64 redirection but I can't seem to understand what am I doing wrong?
EDIT: Added error check for the first API.
I think I got it. Two corrections to my original code:
First off, since Vista I need to load Usrclass.dat file for the classes hive and not ntuser.dat. It kinda makes sense because ntuser.dat is a part of a user's roaming profile and Classes\Local Settings does not fit into the picture well. So here's the location of the Usrclass.dat file, which contains non-roaming user data (mostly COM stuff, but some other settings as well):
%LocalAppData%\Microsoft\Windows\Usrclass.dat
The key to open after the user hive loads is:
Test123\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify
that is because the original HKCU\Software\Classes is redirected to HKU\<UserSID>_Classes that is stored in the Usrclass.dat file.

How to get the full path to the Windows Explorer in C++

Can I safely assume that Windows Explorer is always started from a Windows system directory? Also, is its process always named "explorer.exe"?
And if not, how to get its full file path?
EDIT: Forgot to mention -- I need this to later find out the process ID of the Windows Explorer running in a given user session. Thus my search for its full path.
EDIT 2: Thanks everyone who contributed, and especially to sehe! After his post I found this page that explains how to set up your own shell. I made a wild test by completely replacing explorer.exe with my own process and here's the result:
Here's the full-size link if you it gets re-sized.
As you can see, I can technically replace explorer.exe with whatever process I may come up with. As you can also see in my screenshot Windows gives me a complete control over the Shell (the screenshot is my entire window.)
So the bottom line, the only way to get "explorer.exe" file path (or whatever Shell process is used) is to use those registry keys from the link I quoted above -- pretty much close to what sehe suggested, with just a few more checks to do, but it's a pretty straightforward stuff.
As for Sean Cline's suggestion, it would be a very elegant solution ONLY if we have the "stock" Windows Explorer running that comes with a tray window with that specific class name.
It is probably safe to assume that explorer.exe is always in the %windir% or %SystemRoot% as it hasn't moved for years. But, if you are trying to invoke something via Explorer, chances are you want to use the ShellExecute() function instead.
If you really do need the path, the easiest way to get it is probably with a call to SHGetKnownFolderPath() using FOLDERID_Windows as the first argument.
Edit:
Here is my stab at some code knowing that you are looking for the PID of the shell process:
DWORD trayPID;
HWND trayWnd = FindWindow("Shell_TrayWnd", NULL);
GetWindowThreadProcessId(trayWnd, &trayPID);
It looks for the hWnd of the taskbar and finds the owning PID. You will likely need to add some error handling for the case that explorer is not running and that window does not exist - unlikely, but possible.
No you can't safely assume that and none of this has to do with C++.
Also, you didn't show any code. Here goes:
The registry key for this is Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Shell (see here).
#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <string>
LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
strValue = strDefaultValue;
WCHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
strValue = szBuffer;
}
return nError;
}
int main()
{
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon", 0, KEY_READ, &hKey);
bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
std::wstring shell;
GetStringRegKey(hKey, L"Shell", shell, L"");
}
Yes to both. Windows Explorer is always located at %WINDIR%\Explorer.exe.

Checking if a registry key exists

I am looking for a clean way to check if a registry key exists. I had assumed that RegOpenKey would fail if I tried to open a key that didn't exist, but it doesn't.
I could use string processing to find and open the parent key of the one I'm looking for, and then enumerate the subkeys of that key to find out if the one I'm interested in exists, but that feels both like a performance hog and a weird way to have to implement such a simple function.
I'd guess that you could use RegQueryInfoKey for this somehow, but MSDN doesn't give too many details on how, even if it's possible.
Update: I need the solution in Win32 api, not in managed code, .NET or using any other library.
The docs in MSDN seem to indicate that you should be able to open a key for read permission and get an error if it doesn't exist, like this:
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
However, I get ERROR_SUCCESS when I try this.
Update 2: My exact code is this:
HKEY subKey = nullptr;
LONG result = RegOpenKeyEx(key, subPath.c_str(), 0, KEY_READ, &subKey);
if (result != ERROR_SUCCESS) {
... but result is ERROR_SUCCESS, even though I'm trying to open a key that does not exist.
Update 3: It looks like you guys are right. This fails on one specific test example (mysteriously). If I try it on any other key, it returns the correct result. Double-checking it with the registry editor still does not show the key. Don't know what to make of all that.
First of all don't worry about performance for stuff like this. Unless you are querying it 100x per sec, it will be more than fast enough. Premature optimization will cause you all kinds of headaches.
RegOpenKeyEx will return ERROR_SUCCESS if it finds the key. Just check against this constant and you are good to go.
RegOpenKey does return an error if the key does not exist. How are you using it? The expected return value is ERROR_FILE_NOT_FOUND.
From your code:
HKEY subKey = nullptr;
LONG result = RegOpenKeyEx(key, subPath.c_str(), 0, KEY_READ, &subKey);
if (result != ERROR_SUCCESS) {
I would look at the value of key and subPath and make sure they are what you expect, and that the key does not actually exist. What is the value of subKey afterwards? It is obviously opening something - try enumerating it to see what the keys and values under it are.
There is no issue with RegOpenKey not returning an error if the key does not exist - I would not try to assume there is some kind of weird OS bug in something as commonly used as the registry.
Maybe you have a registry key that is not visible to you, the user that is running the registry editor, but not to your code? A permissions problem perhaps? Is your code running as an elevated user in windows Vista or server 2008? Did you try running the registry editor as administrator?
Note that beside the "core" Registry functions that start with "Reg" there are also helper functions starting with "SHReg". These are intended for use by the Shell i.e. Explorer but are documented and can be used in normal applications too. They're typically thin wrappers that make some common tasks easier. They're part of the "Shell LightWeight API" (shlwapi.dll)