Enumerating registry subkeys in HKEY_LOCAL_MACHINE\SOFTWARE in c++ - c++

I have trouble enumerating subkeys of HKEY_LOCAL_MACHINE\SOFTWARE, all I can get is subkeys on HKEY_LOCAL_MACHINE.
WCHAR Temp[255];
DWORD TMP = 255;
HKEY hKey;
int count = 0;
long regError;
...
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\", NULL, KEY_ENUMERATE_SUB_KEYS, &hKey);
if (regError == ERROR_SUCCESS){
file<<"Key opened!\nSubkeys of HKEY_LOCAL_MACHINE\\SOFTWARE:\n\n";
while ((regError = RegEnumKeyEx(HKEY_LOCAL_MACHINE, count, Temp, &TMP, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS){
TMP = sizeof (Temp);
count++;
file<<count<<". "<<Temp<<std::endl;
}
if (regError == ERROR_NO_MORE_ITEMS) file<<"Done.";
else file << std::endl <<"RegEnumKeyEx error!";
}
else file << std::endl <<"RegOpenKeyEx error!";
RegCloseKey(hKey);
Here is my file:
Key opened!
Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE:
1. BCD00000000
2. DRIVERS
3. HARDWARE
4. SAM
5. SECURITY
6. SOFTWARE
7. SYSTEM
Done.
How can I output keys inside of HKEY_LOCAL_MACHINE\SOFTWARE and not just HKLM? Thanks.

You are passing the wrong HKEY to RegEnumKeyEx(). You are passing the HKLM root, but you need to pass the HKEY that RegOpenKeyEx() returns. In other words, change this:
RegEnumKeyEx(HKEY_LOCAL_MACHINE, ...)
To this:
RegEnumKeyEx(hKey, ...)

Related

RegCreateKeyEx succeeding, but no key added

I am trying to get into C++ programming on Windows for reverse engineering purpose, and I am stuck trying to had a Windows registry key. The functions RegCreateKey and RegSetValueEx are returning ERROR_SUCCESS, but the key is missing when checking the registry.
Here is the code:
void AddRunKey() {
wchar_t subkey[512];
wchar_t cmd[512];
wcscpy_s(subkey, L"Test");
wcscpy_s(cmd, L"%windir%\system32\cmd.exe");
HKEY runKey;
long res;
res = RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurentVersion\\Run", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &runKey, NULL);
if (res != ERROR_SUCCESS) {
std::cout << "fail\n";
}
res = RegSetValueEx(runKey, subkey, 0, REG_EXPAND_SZ, (BYTE*)cmd, wcslen(cmd) + 1);
if (res != ERROR_SUCCESS) {
std::cout << "fail\n";
}
RegCloseKey(runKey);
}
int _tmain() {
AddRunKey();
}
I compiled it on Visual Studio, release mode, 64 bits on a Windows 10 - 64 bits virtual machine. No errors are returned when running the code.
When opening the Windows registry editor, under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run, the key cannot be found
What is causing this behavior ? How can I fix it ?
EDIT (updated the key path): RegCloseKey returns 0
I see several mistakes in your code.
You need to escape the \ characters in your file path.
You misspelled CurentVersion in the key path. It needs to be CurrentVersion instead.
You are calling RegSetValueEx() and RegCloseKey() unconditionally whether RegCreateKeyEx() succeeds or fails.
You need to specify the value size in the last parameter of RegSetValueEx() in bytes and not in characters.
Try this instead:
void AddRunKey() {
wchar_t subkey[512];
wchar_t cmd[512];
wcscpy_s(subkey, L"Test");
wcscpy_s(cmd, L"%windir%\\system32\\cmd.exe");
HKEY runKey;
long res = RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, KEY_SET_VALUE, NULL, &runKey, NULL);
if (res != ERROR_SUCCESS) {
std::cout << "fail\n";
}
else
{
res = RegSetValueEx(runKey, subkey, 0, REG_EXPAND_SZ, (BYTE*)cmd, (wcslen(cmd) + 1) * sizeof(cmd[0]));
if (res != ERROR_SUCCESS) {
std::cout << "fail\n";
}
RegCloseKey(runKey);
}
}
int _tmain() {
AddRunKey();
}

How to write a 32 Bit D-Word to Windows registry in C++

I am trying to disable the Windows Defender using a C++ Win32API application.
To do that I need to write a D Word into the registry (DisableAntiSpyware = 1).
I always do that manually after installing a new Windows.
So here is my code, but its not working.
Maybe someone could tell me why or what is wrong with it. Thank you!
OK I've changed the code a bit, still not working...
case 1:
//::MessageBeep(MB_ICONERROR);
::MessageBox(hWnd, L"Button was Pressed",L"Button was clicked?",MB_OK);
LONG
SetRegValue
(
const wchar_t* path
, const wchar_t *name
, const BYTE *value
);
{
LONG status;
HKEY hKey;
DWORD value = 0x00000001;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"\\SOFTWARE\\Policies\\Microsoft\\Windows Defender", 0, KEY_ALL_ACCESS, &hKey);
if ((status == ERROR_SUCCESS) && (hKey != NULL))
{
status = RegSetValueEx(hKey, L"test", 0, REG_DWORD, (const BYTE*)&value,sizeof(value));
RegCloseKey(hKey);
}
return status;
::MessageBeep(MB_ICONERROR);
}
}
}
break;
When opening a Registry key, you should request only the rights you actually need. So replace KEY_ALL_ACCESS with KEY_SET_VALUE instead, since all you are doing is writing a value. But even then, you might still need to run your app with elevated permissions in order to write to HKEY_LOCAL_MAHCINE, unless you give your user account write access to the Windows Defender key beforehand.
Also, if your code is compiled as 32bit and runs on a 64bit system, and it needs to write to the 64bit Registry, then you have to include the KEY_WOW64_64KEY flag otherwise you may be subject to Registry Reflection/Registry Redirection.
Try something more like this instead:
case 1:
{
::MessageBox(hWnd, L"Button was Pressed", L"Button was clicked?", MB_OK);
DWORD value = 1;
DWORD flags = KEY_SET_VALUE;
#if !defined(_WIN64)
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
flags |= KEY_WOW64_64KEY;
#endif
HKEY hKey;
LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"\\SOFTWARE\\Policies\\Microsoft\\Windows Defender", 0, flags, &hKey);
if ((status == ERROR_SUCCESS) && (hKey != NULL))
{
status = RegSetValueEx(hKey, L"DisableAntiSpyware", 0, REG_DWORD, (const BYTE*)&value, sizeof(value));
RegCloseKey(hKey);
}
::MessageBeep(MB_ICONERROR);
}
break;
You can't write to any key under HKEY_LOCAL_MACHINE unless the program is running with elevated privileges, i.e. administrator mode. The call to RegOpenKeyEx or RegSetValueEx will fail.

Returning invalid data from RegQueryValueEx() DWORD

I'm trying to read a DWORD value from the registry. In the registry, it's stored as 0x00000068 (104). When I read the value from the registry, I'm getting a very large number (3435973836). Any help is appreciated!
DWORD getRecentId(PDWORD id) {
HKEY hKey;
LONG lRes = RegOpenKeyEx(HKEY_CURRENT_USER, _T("SOFTWARE\\My App\\Feed Reader"), 0, KEY_QUERY_VALUE, &hKey);
if (!lRes == ERROR_SUCCESS)
{
RegCloseKey(hKey);
return ERROR_FILE_NOT_FOUND;
}
DWORD dwSize = sizeof(DWORD);
lRes = RegQueryValueEx(hKey, _T("Latest"), NULL, NULL, (LPBYTE)&id, &dwSize);
if (!lRes == ERROR_SUCCESS)
{
RegCloseKey(hKey);
return ERROR_NOT_ENOUGH_MEMORY;
}
RegCloseKey(hKey);
return lRes;
}
3435973836 is a magic number. Convert it to hex to get 0xcccccccc. When you see that back in the Visual Studio debugger then you know that you are using an uninitialized variable.
It is, using &id was wrong. That alters the pointer, not the pointed-to value. Use id instead.

Trying to find the path to excel by searching the registry

I'm trying to find the path to Excel using the registry, and have tried to adapt some code I've found on the internet. I'm using 64-bit Win7 and have confirmed the key is there using regedit.
#include <windows.h>
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
HKEY hKey = 0;
char buf[255] = {0};
DWORD dwType = 0;
DWORD dwBufSize = sizeof(buf);
const char* subkey = "SOFTWARE\\Classes\\Excel.Application\\CLSID";
if( RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey) == ERROR_SUCCESS)
{
dwType = REG_SZ;
if( RegQueryValueEx(hKey,"default",0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
{
cout << "key value is '" << buf << "'\n";
}
else
cout << "can not query for key value\n";
RegCloseKey(hKey);
}
else
cout << "Can not open key\n";
cin.ignore();
return 0;
}
Does anyone know why this isn't working?
Thanks
James
Try changing the
RegQueryValueEx(hKey,"default",0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
with
RegQueryValueEx(hKey, NULL, 0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
If you want the "default" value, you should pass NULL or a empty string in the lpValueName field.
Also if your application is not 64-bit and you are running in a 64-bit OS, you should check the KEY_WOW64_64KEY flag on the RegOpenKeyEx function, to have access to the key you want.
Almost all Windows API functions, when the fail, set a more detailed error code that you can get by calling GetLastError() for more details. You should call that after a call to RegOpenKey() fails.
In your example, the RegOpenKey() is probably failing with an access denied error. RegOpenKey() open a registry key with full read/write/delete access. A standard user on Windows 7 doesn't have write or delete access on HKLM so RegOpenKey() will fail.
You should instead use RegOpenKeyEx() which will let you specify read-only access, as below.
RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &hKey)
PS. When asking a question like the one above you should be more descriptive on how the code is failing. In your example above you should include which line/function call is failing. For example "When I use this code, the call to RegOpenKey is failing.

Create new data in registry key?

I just create new registry key called MyTestApp, and want to add new data in it, but don't know how. So I have following code.
bool CreateSectionDataRegistry(CString sectionData, CString sectionValue)
{
HKEY hKey; //registry key handle
LONG lResult; //result of registry operations
DWORD dwType, dwSize=0;
//try to open the key that we are currently pointing at with rootPath
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, rootPath + "\\" + "MyTestApp", NULL, KEY_ALL_ACCESS, &hKey);
if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
{
//we have successfully opened the registry key. Now try to access the data
lResult = RegQueryValueEx(HKEY_LOCAL_MACHINE, sectionData, 0, &dwType, NULL, &dwSize);
if(lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
{
//data already exists, so just return
RegCloseKey(hKey);
return true;
}
else//section data does not exist, so create new data
{
DWORD dwDisposition;
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sectionData, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition);
RegCloseKey(hKey);
return true;
}
}
return false;
}
But when I trace down to the RegCreateKeyEx() call, it returns success but data is not created under the MyTestApp registry key or anywhere in the registry. Am I using the correct function to create new data under MyTestApp. Also from the argument above, I have CString sectionValue, so how do I check if I need to create data for REG_SZ or REG_DWORD?
Thanks!
It seems I just need to call RegSetValueEx() to create registry value under MyTestApp. Probably just me but when I look at the RegSetValueEx() definition in Microsoft website, it says set the value, but it does not say if value does not exist, it will create the value.
LPTSTR lpszData = new TCHAR[sectionValue.GetLength() + 1];
_tcscpy(lpszData, sectionValue);
lResult = RegSetValueEx(hKey, sectionData, 0, REG_SZ, (LPBYTE)lpszData, sectionValue.GetLength());
So now it creates the registry value, however I cannot still tell if sectionValue is REG_SZ or REG_DWORD.