I am attempting to read values from the Windows Registry. I am reading one value from HKLM\System and one value from HKLM\Software. I can easily read the value from System... but I cannot read the value from Software.
Snippit from Registry Editor:
Snippit from ReadReg():
int ReadReg(LPCTSTR subkey, LPCTSTR name, DWORD type)
{
HKEY key;
TCHAR value[255];
DWORD valuelen = 255;
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &key);
cout << "RegOpenKeyEx Req is: " << subkey << endl;
cout << "RegOpenKeyEx result is: " << PrintErrorCode(result) << endl;
result = RegQueryValueEx(key, name, NULL, &type, (LPBYTE)&value, &valuelen);
cout << "RegQueryValueEx Req is: " << name << endl;
cout << "RegQueryValueEx result is: " << PrintErrorCode(result) << "\n" << endl;
RegCloseKey(key);
return 0;
}
Snippit from Inject():
int Inject()
{
ReadReg("Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", "demo", REG_MULTI_SZ);
ReadReg("System\\CurrentControlSet\\services\\SvcHostDemo\\Parameters", "ServiceDll", REG_EXPAND_SZ);
return 0;
}
Snippit from Standard Out:
The big question is... why can't I look at the value from "demo"?
You need to add the KEY_WOW64_64KEY flag when calling RegOpenKeyEx(). And you should change KEY_READ to KEY_QUERY_VALUE since you are just reading a value and don't need the other rights that KEY_READ grants.
Also, the last parameter of RegQueryValueEx() needs to be expressed in bytes, not in TCHARs.
#ifndef KEY_WOW64_64KEY
#define KEY_WOW64_64KEY 0x0100
#endif
int ReadReg(LPCTSTR subkey, LPCTSTR name, DWORD type)
{
HKEY key;
TCHAR value[255];
DWORD valuelen = sizeof(value);
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &key);
cout << "RegOpenKeyEx Req is: " << subkey << endl;
cout << "RegOpenKeyEx result is: " << PrintErrorCode(result) << endl;
result = RegQueryValueEx(key, name, NULL, &type, (LPBYTE)&value, &valuelen);
cout << "RegQueryValueEx Req is: " << name << endl;
cout << "RegQueryValueEx result is: " << PrintErrorCode(result) << "\n" << endl;
RegCloseKey(key);
return 0;
}
Related
Trying to write code to change the registry keys with c++ after endless amount of time I reached this point but this code still does not edit the registry even when running as admin
to change the registry 4 functions are needed according to this question which I used and every single one of them returns a zero which means that the function completed without errors but still no values are changed in the registry gui
the SecurityHealth strartup service is running on my machine and has the path %windir%\system32\SecurityHealthSystray.exe and type REG_EXPAND_SZ
I even tried creating a new entry similar to the SecurityHealth and still nothing is changed
I am compiling as admin and running as admin
HKEY open_reg()
{
int result;
LPCSTR lpSubKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
HKEY hKey;
result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_QUERY_VALUE|KEY_WRITE|KEY_READ|KEY_SET_VALUE, &hKey);
if ( result != 0)
{
cout << " Failed to open registry. - [ "<< result<< "]" <<endl;
}
else
{
cout << "Found registry key. - [" << result<<"]" << endl;
}
return hKey;
}
HKEY find_reg_value(HKEY handle)
{
LPCSTR lpValueName = "SecurityHealth";
DWORD BufferSize = TOTALBYTES;
DWORD cbData;
int dwRet;
PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
cbData = BufferSize;
cout << "\nRetrieving the data..." << endl;
dwRet = RegQueryValueExA( handle,
lpValueName,
NULL,
NULL,
(LPBYTE) PerfData,
&cbData );
if ( dwRet == 0 )
{
cout << "Successfully quered [" << dwRet << "]"<<endl;
}
else
{
cout << "Failed to query Error code : [" << dwRet << "]"<<endl;
}
return handle;
}
void set_reg_value(HKEY handle)
{
int result;
LPCSTR lpValueName = "SecurityHealth";
std::string file = "C:\\Windows\\System32\\cmd.exe";
const char * sth = file.c_str();
unsigned char m_Test[file.size()];
strcpy((char*)m_Test, sth);
DWORD DATA_SIZE = file.size()+1;
result = RegSetValueExA(handle,lpValueName,0,REG_EXPAND_SZ,m_Test,DATA_SIZE);
if ( result == 0 )
{
cout << "Successfully changed value [" << result << "]"<<endl;
}
else
{
cout << "Failed to change value Error code : [" << result << "]"<<endl;
}
RegCloseKey (handle);
}
int main()
{
cout << "testing windows registry " << endl;
HKEY reg_handle = open_reg();
HKEY handler = find_reg_value(reg_handle);
set_reg_value(handler);
system("PAUSE");
return 0;
}
the compiled exe output in the terminal
testing windows registry
Found registry key. - [0]
Retrieving the data...
Successfully quered [0]
Successfully changed value [0]
Press any key to continue . . .
Compiled with g++ regutil.cpp
I suspect you are compiling as a 32-bit program but looking at a 64-bit registry. Switch to compiling as 64-bit instead. (There is a 32-bit registry instead, which can be found buried within the 64-bit hives but you likely want to change the actual 64-bit version).
every single one of them returns a zero which means that the function completed without errors but still no values are changed in the registry GUI
The only way that can happen is if either:
You are not updating the GUI after making the changes.
you are modifying a different area of the Registry then you are viewing, ie if you are modifying the 32bit Registry but viewing the 64bit Registry, or vice versa. Read up about the Registry Redirector, Registry Keys Affected by WOW64 and Accessing an Alternate Registry View on MSDN for more details about working with the 32bit and 64bit Registry views.
That being said, there are a number of other mistakes in your code.
Try something more like this instead:
HKEY open_reg()
{
HKEY hKey = NULL;
int result = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0,
KEY_QUERY_VALUE | KEY_SET_VALUE /* | KEY_WOW64_(32|64)KEY if needed */,
&hKey );
if ( result != 0 )
{
cout << " Failed to open Registry, Error " << result << endl;
return NULL;
}
else
{
cout << "Opened Registry key" << endl;
return hKey;
}
}
void query_reg_value(HKEY handle)
{
DWORD cbBuffer = TOTALBYTES;
std::vector<char> buffer(cbBuffer);
cout << "\nRetrieving the data..." << endl;
int result = RegQueryValueExA( handle,
"SecurityHealth",
NULL,
NULL,
reinterpret_cast<LPBYTE>(buffer.data()),
&cbBuffer );
if ( result == 0 )
{
cout << "Successfully quered: ";
while (cbBuffer != 0 && buffer[cbBuffer-1] == '\0') --cbBuffer; // ignore null terminator(s)
cout.write(buffer.data(), cbBuffer);
cout << endl;
}
else
{
cout << "Failed to query, Error " << result << endl;
}
}
void set_reg_value(HKEY handle)
{
std::string file = "C:\\Windows\\System32\\cmd.exe";
int result = RegSetValueExA( handle,
"SecurityHealth",
0,
REG_EXPAND_SZ,
reinterpret_cast<LPCBYTE>(file.c_str()),
file.size()+1);
if ( result == 0 )
{
cout << "Successfully changed value" << endl;
}
else
{
cout << "Failed to change value, Error " << result << endl;
}
}
int main()
{
cout << "testing Windows Registry" << endl;
HKEY hKey = open_reg();
if (hKey) {
query_reg_value(hKey);
set_reg_value(hKey);
RegCloseKey(hKey);
}
system("PAUSE");
return 0;
}
However, it should be noted that only admin users have write access to HKLM keys by default, most users have read-only access. As such, it is not a good idea to open a key under HKLM for both reading and writing at the time same, unless you know what you are doing. You should open a key for reading only, read from it, and close it. Same for writing. For instance:
HKEY open_reg(bool isWriting)
{
HKEY hKey = NULL;
int result = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0,
(isWriting ? KEY_SET_VALUE : KEY_QUERY_VALUE) /* | KEY_WOW64_(32|64)KEY if needed */,
&hKey );
if ( result != 0 )
{
cout << " Failed to open Registry, Error " << result << endl;
return NULL;
}
else
{
cout << "Opened registry key" << endl;
return hKey;
}
}
void query_reg_value()
{
HKEY hKey = open_reg(false);
if (!hKey) return;
DWORD cbBuffer = TOTALBYTES;
std::vector<char> buffer(cbBuffer);
cout << "\nRetrieving the data..." << endl;
int result = RegQueryValueExA( hKey,
"SecurityHealth",
NULL,
NULL,
reinterpret_cast<LPBYTE>(buffer.data()),
&cbBuffer );
if ( result == 0 )
{
cout << "Successfully quered: ";
while (cbBuffer != 0 && buffer[cbBuffer-1] == '\0') --cbData; // ignore null terminator(s)
cout.write(buffer.data(), cbBuffer);
cout << endl;
}
else
{
cout << "Failed to query, Error " << result << endl;
}
RegCloseKey(hKey);
}
void set_reg_value()
{
HKEY hKey = open_reg(true);
if (!hKey) return;
std::string file = "C:\\Windows\\System32\\cmd.exe";
int result = RegSetValueExA( hKey,
"SecurityHealth",
0,
REG_EXPAND_SZ,
reinterpret_cast<LPCBYTE>(file.c_str()),
file.size()+1);
if ( result == 0 )
{
cout << "Successfully changed value" << endl;
}
else
{
cout << "Failed to change value, Error " << result << endl;
}
RegCloseKey(hKey);
}
int main()
{
cout << "testing Windows Registry" << endl;
query_reg_value();
set_reg_value();
system("PAUSE");
return 0;
}
#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;
DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
MODULEENTRY32 lpModuleEntry = {0};
HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );
if(!hSnapShot)
return NULL;
lpModuleEntry.dwSize = sizeof(lpModuleEntry);
BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
while(bModule)
{
if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
{
CloseHandle( hSnapShot );
return (DWORDLONG)lpModuleEntry.modBaseAddr;
}
bModule = Module32Next( hSnapShot, &lpModuleEntry );
}
CloseHandle( hSnapShot );
return NULL;
}
int main() {
DWORD pID;
DWORDLONG off1, off2;
DWORDLONG baseAddress;
char moduleName[] = _T("AoE2DE_s.exe");
HWND hGameWindow;
HANDLE pHandle;
//Get Handles
hGameWindow = FindWindow(NULL, "Age of Empires II: Definitive Edition");
cout << "Game Window: " << hGameWindow << std::endl;
GetWindowThreadProcessId(hGameWindow, &pID);
cout << "Process ID: " << pID << std::endl;
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
cout << "Process Handle: " << std::hex << pHandle << std::endl;
//Get Client Base Addy
DWORDLONG clientBase = GetModuleBase(moduleName, pID);
cout << "Client Base: " << clientBase << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
DWORD lastError = GetLastError();
cout << "Error: " << lastError << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x18), &off1, sizeof(DWORDLONG), NULL);
cout << "After Offset 1: " << std::hex << off1 << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x9230), &off2, sizeof(DWORDLONG), NULL);
cout << "After Final Offset: " << off2 << std::endl;
cin.get();
}
The error occurs on this line:
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
Application output for debugging purposes:
Game Window: 0x1307c2
Process ID: 11988
Process Handle: 0xec
Client Base: cc640000
Error: 12b
Base Address: 0
After Offset 1: 401519
After Final Offset: 8
Not sure how it is failing here, I'm somewhat new to this. Everything else goes through perfectly without error's but fails on the first ReadProcessMemory() if someone can help bring the solution for this to light I would be grateful.
ReadProcessMemory is defined like this:
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesRead
);
If it returns zero then there has been an error, and only in that case GetLastError will return a meaningfull error number.
So correct usage would be:
SIZE_T readBytes;
if (!ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), &readBytes)) {
DWORD lastError = GetLastError();
cout << "ReadProcessMemory failed: Error: " << lastError << " read " << readBytes << std::endl;
}
else
{
cout << "ReadProcessMemory succeeded"; << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
}
How to write/read a string in windows registry in C++ ?
I am able to write/read DWORD (number) in windows registry using the following code. But, unable to write/read a string value, as it gets stored as chinese like characters in the registry.
void SetVal(HKEY hKey, LPCTSTR lpValue, DWORD data)
{
LONG nError = RegSetValueEx(hKey, lpValue, NULL, REG_DWORD, (LPBYTE)&data, sizeof(DWORD));
if (nError)
cout << "Error: " << nError << " Could not set registry value: " << (char*)lpValue << endl;
}
DWORD GetVal(HKEY hKey, LPCTSTR lpValue)
{
DWORD data; DWORD size = sizeof(data); DWORD type = REG_DWORD;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
if (nError==ERROR_FILE_NOT_FOUND)
data = 0; // The value will be created and set to data next time SetVal() is called.
else if (nError)
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
return data;
}
Code used to write/read string value (Stored as chinese like characters in the registry):
void SetVal(HKEY hKey, LPCTSTR lpValue, string data)
{
LONG nError = RegSetValueEx(hKey, lpValue, NULL, REG_SZ, (LPBYTE)&data, sizeof(data));
if (nError)
cout << "Error: " << nError << " Could not set registry value: " << (char*)lpValue << endl;
}
string GetVal(HKEY hKey, LPCTSTR lpValue)
{
string data; DWORD size = sizeof(data); DWORD type = REG_SZ;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
if (nError==ERROR_FILE_NOT_FOUND)
data = "0"; // The value will be created and set to data next time SetVal() is called.
else if (nError)
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
return data;
}
The problem with your code is that you are naively casting string type variables to LPBYTE.
This is your code with corrections:
void SetVal(HKEY hKey, LPCTSTR lpValue, string data)
{
const char *x = data.c_str();
LONG nError = RegSetValueEx(hKey, lpValue, NULL, REG_SZ, (LPBYTE)data.c_str(), data.size());
if (nError)
cout << "Error: " << nError << " Could not set registry value: " << (char*)lpValue << endl;
}
string GetVal(HKEY hKey, LPCTSTR lpValue)
{
string data;
#define MAXLENGTH 100
char buffer[100];
DWORD size = sizeof(buffer);
DWORD type = REG_SZ;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)buffer, &size);
if (nError == ERROR_FILE_NOT_FOUND)
{
data = "0"; // The value will be created and set to data next time SetVal() is called.
return data;
}
else if (nError)
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
data = buffer;
return data;
}
There is still room for improvement, for example the maximum string length is limited to 100 and the error handling should be improved.
Explanations:
This is your code in SetVal
RegSetValueEx(hKey, lpValue, NULL, REG_DWORD, (LPBYTE)&data, sizeof(DWORD));
you are naively casting data to LPBYTE.
sizeof(DWORD) is wrong, because you need to provide the length of the string
This is your code in GetVal:
string data;
DWORD size = sizeof(data);
DWORD type = REG_SZ;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
sizeof(data) when data is a string doesn't make any sense. It is not the length of the string, which at that moment is 0 anyway.
you are again casting naively string to LPBYTE when calling RegQueryValueEx
I'm using some Registry functions from the Windows API (RegOpenKeyEx, RegQueryInfoKey and RegEnumValue)Let's say this is the code I have so far:
const int MAX_VALUE_NAME= 16383;
const int MAX_DATA = 16383;
DWORD i;
HKEY hKey = HKEY_CURRENT_USER;
LPCTSTR lpSubKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU");
DWORD ulOptions = 0;
REGSAM samDesired = KEY_READ | KEY_WRITE | KEY_QUERY_VALUE;
HKEY phkResult;
DWORD dwIndex = 0;
TCHAR lpValueName[MAX_VALUE_NAME];
LPCTSTR ValueMRU;
BYTE *DataMRU;
DWORD lpcchValueName = MAX_VALUE_NAME;
BYTE lpData[MAX_DATA+2];
DWORD cbData = sizeof(lpData);
DWORD type;
TCHAR lpClass[MAX_PATH] = TEXT("");
DWORD lpcClass = MAX_PATH;
LPDWORD lpReserved = NULL;
DWORD lpcSubKeys = 0;
DWORD lpcMaxSubKeyLen;
DWORD lpcMaxClassLen;
DWORD lpcValues;
DWORD lpcMaxValueNameLen;
DWORD lpcMaxValueLen;
DWORD lpcbSecurityDescriptor;
FILETIME lpfLastWriteTime;
char *pMsg = NULL;
long R;
long OpenK = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &phkResult);
if (OpenK == ERROR_SUCCESS)
{
long Query = RegQueryInfoKey(phkResult, lpClass, &lpcClass, lpReserved, &lpcSubKeys, &lpcMaxSubKeyLen,
&lpcMaxClassLen, &lpcValues, &lpcMaxValueLen, &lpcMaxValueLen, &lpcbSecurityDescriptor, &lpfLastWriteTime);
if (Query == ERROR_SUCCESS)
{
if (lpcValues)
{
cout << "Number of values in the subkey: " << lpcValues << endl;
cout << "\nThe values are:: \n" << endl;
//Show RunMRU values and content.
for (i = 0; i < lpcValues; i++)
{
lpcchValueName = MAX_VALUE_NAME;
//lpValueName[0] = '\0';
lpValueName[MAX_VALUE_NAME];
//lpData[MAX_DATA + 2];
cbData = MAX_DATA;
R = RegEnumValue(phkResult, i, lpValueName, &lpcchValueName, NULL,
&type, lpData, &cbData);
int Quantity = strlen((const char *)lpData);
if (R != ERROR_NO_MORE_ITEMS)
{
cout << "\0" << lpValueName << ": " << lpData << endl;
cout << "Number of characters: " << Quantity << endl;
cout << "\n";
}
else
{
cout << "Error enumerating values. Code: " << R << endl;
}
}
} //EOIF.
And this is what I got:
The questions are:
How do I remove the "\1" at the end of the string from lpData? [Solved: See below]
PD. lpData gets the value's content, not the value.
How do I avoid showing the RunMRU value without affecting the "for" and the other values and content?
EDIT 1: I could solve the "\1" question by adding this into the FOR:
int Quantity = strlen(lpData);
std::string original = lpData;
std::string result = original.substr(0, original.size() - 2);
std::string result = original.substr(0, Quantity - 2);
if (R != ERROR_NO_MORE_ITEMS)
{
cout << "\0" << lpValueName << ": " << (TCHAR*)result.c_str() << endl;
cout << "Numbers of characters: " << Quantity-2 << endl;
cout << "\n";
}
else
{
cout << "Error enumerating the values. Code: " << R << endl;
}
Now I just need to know how to avoid showing the MRUList value within the FOR.
char* dest = new char[strlen(lpData) - 2];
memcpy(dest, lpData, strlen(lpData) - 2)
//do stuff with dest..
delete[] dest;
Another way is to std::string it..
std::string dest = std::string(lpData);
dest.erase(std::find_last_of("\\1"), 2);
I think you may have not only \1. It is possible to have \2 or even \100, so my answer shows how to cut all that stuff from the end.
You need to substring you value. Try this:
size_t len = strlen(lpData);
for (int i = len - i; i <= 0; --i)
{
if (lpData == '\\')
{
lpData[i] = '\0';
break;
}
}
You may need some other procedure instead of strlen depending on setting, you can choose it from here. Probably wcslen.
How do I avoid showing the RunMRU value without affecting the "for"
and the other values and content?
It is more C solution then C++ but this way performance is better. Pure C++ solution would be connected with std::string and would take more clocks to get wanted result.
Also you may found this helpful.
I'm trying to retrieve a value of a key but i'm only getting the first char of the value..
can anyone help?
my code:
void dealWithRegistry()
{
HKEY regkey1;
char data[100];
DWORD datasize = sizeof (data) / sizeof (char);
LONG rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, ®key1);
if (rc != ERROR_SUCCESS)
{
cout << "there was a problem openning" << endl;
}
else
{
rc = RegGetValue (regkey1, NULL, L"AppData", RRF_RT_REG_SZ, NULL, (void*) data, &datasize);
if (rc != ERROR_SUCCESS)
{
cout << data << endl;
cout << "there was a problem getting the value" << endl;
}
}
cout << data << endl;
}
It is probably returning Unicode data and you are only printing the first character. A quick test of that would be to change the call to RegGetValueA.