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;
}
Related
This is all the source code for a program i'm trying to make, and I can't get WriteProcessMemory to work at all. It returns the correct messages, saying that everything went successfully, but nothing actually changes in the game. Does anyone know of a fix?
#include <iostream>
#include <Windows.h>
using namespace std;
// variables
int plcHold = 1;
string hlthLoop = "OFF";
string ammoLoop = "OFF";
DWORD pid;
DWORD playerAddr;
DWORD hlthOffs = 0xF8;
// main function
int main()
{
// finding pid, opening proc, finding player address
HWND hwnd = FindWindowA(NULL, "AssaultCube");
if(hwnd == NULL)
{
cout << "Error; Couldn't find window" << endl;
} else{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(pHandle == NULL)
{
cout << "Error; Couldn't open process" << endl;
} else{
ReadProcessMemory(pHandle, (LPCVOID)0x50F4F4, &playerAddr, sizeof(playerAddr), 0);
if(ReadProcessMemory != FALSE)
{
cout << "Health successfully read!" << endl;
} else{
cout << "Error code " << GetLastError << endl;
}
}
while(plcHold == 1){
cout << "========== *****'s Assault Cube Trainer ==========\n" << endl;
cout << "=============== Health Loop - " << hlthLoop << " ================" << endl;
Sleep(1500);
system("cls");
if(GetAsyncKeyState(0x5A))
{
cout << "Health successfully edited!" << endl;
WriteProcessMemory(pHandle, LPVOID(playerAddr + hlthOffs), 0, sizeof(999), 0);
CloseHandle(pHandle);
}
}
}
return 0;
}
You're passing a null pointer to WriteProcessMemory for the third (lpBuffer) parameter. You have to pass the address of the actual value, not the value itself. If you want to write an integer value, try this:
DWORD val = 0; // or 999?
WriteProcessMemory(
pHandle, static_cast<LPVOID>(playerAddr + hlthOffs),
&val, sizeof(val), 0);
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;
}
void main() {
PSID UserSID = NULL;
PSID GroupSID = NULL;
PSECURITY_DESCRIPTOR SD = NULL;
ACL *pDACL = new ACL ;
string input, ext = "";
wcout << "Enter the location : " << endl;
std::getline(cin, input);
LPCSTR file = input.c_str();
HANDLE hFile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_ACCESS_DENIED)
{
cout << "Access Denied : System Files" << endl;
return;
}
else if (GetLastError() == ERROR_PATH_NOT_FOUND)
{
cout << "Path Name Not Found" << endl;
return;
}
else if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
cout << "File Not Found" << endl;
return;
}
else
{
cout << GetLastError() << endl;
return;
}
}
ULONG Count = NULL;
PEXPLICIT_ACCESS_W *pExplicitEntries = new PEXPLICIT_ACCESS_W;
if (GetSecurityInfo(hFile,SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &SD) == ERROR_SUCCESS)
{
cout << "GetSecInfo Success " << pDACL->AceCount << endl;
cout << GetLastError() << endl;
}
if (GetExplicitEntriesFromAclW(pDACL, &Count, pExplicitEntries) == ERROR_SUCCESS)
{
cout << Count << endl;
cout << GetLastError() << endl;
}
if (pExplicitEntries[0]->Trustee.TrusteeForm == TRUSTEE_IS_SID)
{
TCHAR AccountBuff[80];
TCHAR DomainBuff[80];
DWORD AccountBufflength = 40;
DWORD DomainBufflength = 40;
PSID_NAME_USE peUse = new SID_NAME_USE;
PSID Sid = pExplicitEntries[0]->Trustee.ptstrName;
LookupAccountSidW(NULL, Sid, AccountBuff, &AccountBufflength, DomainBuff, &DomainBufflength, peUse);
wcout << AccountBuff << endl;
DWORD pAccessRights;
if (GetEffectiveRightsFromAclW(pDACL, &pExplicitEntries[0]->Trustee, &pAccessRights) == ERROR_SUCCESS)
{
DisplayAccessMask(pAccessRights);
}
}
}
Currently, the array index is 0, if i switch to other index like 1 or 2, it causes exception : Accessing location. Please Help, please someone give me solution to access all the trustee in the ACL and get the access permission and username of each trustee of a file
GetSecurityInfo gives me ACE count as 4 , but when it comes to the
GetExplicitEntriesFromAclW the Count value remains 0.
I can reproduce this issue when my test target file is an new created, for example, TXT file. Yes, GetSecurityInfo gives me ACE count as 4 , but when it comes to the GetExplicitEntriesFromAclW the Count value remains 0.
Use function to check the ACE type and found that all types are 0: ACCESS_MIN_MS_ACE_TYPE \ ACCESS_ALLOWED_ACE_TYPE.
if (GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &SD) == ERROR_SUCCESS)
{
cout << "GetSecInfo Success " << pDACL->AceCount << endl;
cout << GetLastError() << endl;
}
PACL pAcl = pDACL;
int aceNum = pDACL->AceCount;
for (int i = 0; i < aceNum; i++)
{
ACE_HEADER *aceAddr = NULL;
if (GetAce(pAcl, i, (void**)(&aceAddr)))
{
printf("ACE type: %d \n",aceAddr->AceType); ACCESS_ALLOWED_ACE_TYPE;
printf("ACE flags: %d \n", aceAddr->AceFlags);
printf("ACE size: %d \n", aceAddr->AceSize);
}
}
If you set deny write operation for current user like this:
Then ACE type 1 (ACCESS_DENIED_ACE_TYPE) appears. And the Count value returned from the GetExplicitEntriesFromAclW equals the number of entries whose ACE type is 1. See the following snapshot:
Looks like you are passing null EXPLICIT_ACCESS_W to GetExplicitEntriesFromAclW.
So try either:
EXPLICIT_ACCESS_W *pExplicitEntries=NULL;
EXPLICIT_ACCESS_W **pExplicitEntries2=&pExplicitEntries;
GetExplicitEntriesFromAclA(pacl,&countExplicitACL,pExplicitEntries2);
or:
EXPLICIT_ACCESS_W *pExplicitEntries =NULL;
GetExplicitEntriesFromAclA(pacl,&countExplicitACL,&pExplicitEntries2);
Both serve your purpose. Beware of NULL pointers.
I'm trying to read the contents of a DLL from memory for some academic research. Specifically, the NTDSA.DLL library for the purpose of mutating specific instructions to simulate programming errors to force the system to fail. The failure will then be recorded to train machine learning algorithms to predict future failures (this is an attempt to generalize previously published research seen here).
I'm getting what I believe to be the base address in virtual memory of the lsass.exe process (which loads the target DLL) through the process outlined here. I'm then calling ReadProcessMemory with an allocated buffer and the handle to lsass obtained by calling OpenProcess with 'PROCESS_ALL_ACCESS' set. The ReadProcessMemory returns with error code 299 80% of the time (partial read) with zero bytes read. My assumption is that the area I'm trying to access is in use when the call is made. Fortunately, it will occasionally return the number of bytes I'm requesting. Unfortunately, the data returned does not match what is on disk when compared to the static DLL in the System32 directory.
So the question is, is ReadProcessMemory doing something funny with the address that I give it, or is my virtual address wrong? Is there another way to figure out where that DLL gets loaded into memory? Any thoughts? Any help or suggestions would be greatly appreciated.
Adding Code:
// FaultInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <psapi.h>
#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <io.h>
#include <tchar.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
// Declarations
int pid = 0;
__int64* start_addr;
DWORD size_of_ntdsa;
DWORD aProcesses[1024], cbNeeded, cProcesses;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HMODULE hmods[1024];
unsigned int i;
// Get All pids
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)){
cout << "Failed to get all PIDs: " << GetLastError() << endl;
return -1;
}
// Find pid for lsass.exe
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
if (hProc != NULL) {
HMODULE hMod;
DWORD cbNeededMod;
if (EnumProcessModules(hProc, &hMod, sizeof(hMod), &cbNeededMod)) {
GetModuleBaseName(hProc, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
}
if (wstring(szProcessName).find(L"lsass.exe") != string::npos) {
pid = aProcesses[i];
}
CloseHandle(hProc);
}
}
}
cout << "lsass pid: " << pid << endl;
HANDLE h_lsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!h_lsass) {
cout << "Failed to open process (are you root?): " << GetLastError() << endl;
return -1;
}
// Get Process Image File Name
char filename[MAX_PATH];
if (GetProcessImageFileName(h_lsass, (LPTSTR)&filename, MAX_PATH) == 0) {
cout << "Failed to get image file name: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
// Enumerate modules within process
if (EnumProcessModules(h_lsass, hmods, sizeof(hmods), &cbNeeded)) {
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(h_lsass, hmods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
if (wstring(szModName).find(L"NTDSA.dll") != string::npos) {
_tprintf(TEXT("%s\n"), szModName);
MODULEINFO lModInfo = { 0 };
if (GetModuleInformation(h_lsass, hmods[i], &lModInfo, sizeof(lModInfo))){
cout << "\t Base Addr: " << lModInfo.lpBaseOfDll << endl;
cout << "\t Entry Point: " << lModInfo.EntryPoint << endl;
cout << "\t Size of image: " << lModInfo.SizeOfImage << endl;
start_addr = (__int64*)lModInfo.lpBaseOfDll;
size_of_ntdsa = lModInfo.SizeOfImage;
}
else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
} else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
}
else {
cout << "Failed to enum the modules: " << GetLastError() << endl;
}
// Ready to continue?
string cont = "";
cout << "Continue? [Y|n]: ";
getline(cin, cont);
if (cont.find("n") != string::npos || cont.find("N") != string::npos) {
CloseHandle(h_lsass);
return 0;
}
void* buf = malloc(size_of_ntdsa);
if (!buf) {
cout << "Failed to allocate space for memory contents: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
SIZE_T num_bytes_read = 0;
int count = 0;
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
cout << "Read success. Got " << num_bytes_read << " bytes: " << endl;
} else {
int error_code = GetLastError();
if (error_code == 299) {
cout << "Partial read. Got " << num_bytes_read << " bytes: " << endl;
} else {
cout << "Failed to read memory: " << GetLastError() << endl;
CloseHandle(h_lsass);
free(buf);
return -1;
}
}
if (num_bytes_read > 0) {
FILE *fp;
fopen_s(&fp, "C:\\ntdsa_new.dll", "w");
SIZE_T bytes_written = 0;
while (bytes_written < num_bytes_read) {
bytes_written += fwrite(buf, 1, num_bytes_read, fp);
}
fclose(fp);
cout << "Wrote " << bytes_written << " bytes." << endl;
}
CloseHandle(h_lsass);
free(buf);
return 0;
}
Code works as described minus my amateur mistake of sending the address of the variable I was using to store the address of the location in virtual memory of the target application. In above code, changed:
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
to
if (ReadProcessMemory(h_lsass, start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
Works like a charm. Thank you ssbssa for pointing out mistake, sorry for wasting anyone's time.
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.