Writing Memory to Process - c++

I'm trying to write a float value into a video game emulator called Dolphin. I have a spread sheet of memory addresses for a specific game I'd like to be able to change the values at those address. Dolphin has a debug setting and i'm able to look at the games memory on the fly but whenever I try to run my program the value at the memory address does not change
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
float newValue = 22;
HWND hWnd = FindWindow(0, "Dolphin 5.0-321");
if(hWnd == 0) {
cerr << "Cannot Find Window." << endl;
} else {
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if(!hProc) {
cerr << "Cannot Open Process." << endl;
} else {
int isSuccessful = WriteProcessMemory(hProc, (LPVOID)0x81118DF0, &newValue, (DWORD)sizeof(newValue), NULL);
if (isSuccessful) {
clog << "Process Memory Written." << endl;
} else {
cerr << "Cannot Write Process Memory." << endl;
}
CloseHandle(hProc);
}
}
return 0;
}

Dolphin in an emulator, if you're using it's debug function it may not be providing actual real memory addresses, but rather the addresses relative to the emulated system not your Windows operating system. Think of it kinda like a virtual machine, the dolphin emulator is running a guest operating system and you're writing to memory from the host Windows OS.
If you've located those addresses by reversing the game from the host OS then you can write to those addresses without much issue.
There is no guarantee that writing to the variables address will have the effect you're looking for, it's possible that it gets overwritten by some other code.
Lastly, if you have the correct address for the virtual memory of the dolphin process and you have tested that it changes correctly with a tool like Cheat Engine, the last problem that could arise is that you're not running your C++ project as administrator. Once doing so, it should work without issue.

Related

Can't figure out how to call IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES IOCTL on Windows - INVALID_PARAMETERS

Greetings!
I have come today to ask a question about invoking a very specific IOCTL on Windows. I have some amount of driver development experience, but my experience with file system drivers is relatively limited.
The Goal
I am developing a tool that manages volumes/physical disks/partitions. For the purpose I am attempting to learn to invoke many of the Windows file system data set management (DSM) IOCTLs. Currently I am learning how to use IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES which is documented at https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-ioctl_storage_manage_data_set_attributes?redirectedfrom=MSDN.
However, I have had to intuit how to set up the call to the IOCTL myself. The MSDN article does not give fully detailed instructions on how to set up the input buffer, and specifically what values of the inputs are strictly required. I have uncertainty about how to call the IOCTL that has lead to a bug I cannot debug easily.
In order to reduce my uncertainty about proper invocation of the IOCTL I worked off a tool MS released a few years ago and copied some of their code: https://github.com/microsoft/StorScore/blob/7cbe261a7cad74f3a4f758c2b8a35ca552ba8dde/src/StorageTool/src/_backup.c
My Code
At first I tried:
#include <windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <winnt.h>
#include <winternl.h>
#include <ntddstor.h>
int main(int argc, const char* argv[]) {
//My understanding is for this IOCTL I need to open the drive, not the object PartmgrControl device that the driver registers.
HANDLE hDevice = CreateFile(L"\\\\.\\Physicaldrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL);
int cf_error = 0;
cf_error = GetLastError();
if (hDevice == INVALID_HANDLE_VALUE) {
std::cout << "COULDN'T GET HANDLE";
return -1;
}
std::cout << "Device Handle error: " << cf_error << "\n";
std::cout << "Handle value: " << hDevice << "\n";
_DEVICE_MANAGE_DATA_SET_ATTRIBUTES attributes_struct;
LPDWORD BytesReturned = 0;
int inputbufferlength = 0;
inputbufferlength = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES) + sizeof(_DEVICE_DSM_OFFLOAD_WRITE_PARAMETERS) + sizeof(DEVICE_DATA_SET_RANGE);
PUCHAR inputbuffer = (PUCHAR)malloc(inputbufferlength);
PUCHAR outputbuffer = (PUCHAR)malloc(inputbufferlength);
//RtlZeroMemory(inputbuffer, inputBufferLength);
PDEVICE_MANAGE_DATA_SET_ATTRIBUTES dsmAttributes = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES)inputbuffer;
PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS offload_write_parameters = NULL;
dsmAttributes->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
dsmAttributes->Action = DeviceDsmAction_OffloadWrite;
dsmAttributes->Flags = 0;
dsmAttributes->ParameterBlockOffset = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
dsmAttributes->ParameterBlockLength = sizeof(DEVICE_DSM_OFFLOAD_WRITE_PARAMETERS);
offload_write_parameters = (PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS)((PUCHAR)dsmAttributes + dsmAttributes->ParameterBlockOffset);
offload_write_parameters->Flags = 0;
offload_write_parameters->TokenOffset = 0;
dsmAttributes->DataSetRangesOffset = dsmAttributes->ParameterBlockOffset + dsmAttributes->ParameterBlockLength;
dsmAttributes->DataSetRangesLength = sizeof(DEVICE_DATA_SET_RANGE);
PDEVICE_DATA_SET_RANGE lbaRange = NULL;
lbaRange = (PDEVICE_DATA_SET_RANGE)((PUCHAR)dsmAttributes + dsmAttributes->DataSetRangesOffset);
lbaRange->StartingOffset = 0; // not sure about this one for now
lbaRange->LengthInBytes = 256 * 1024 * 1024;
int status = DeviceIoControl(
hDevice, // handle to device
IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES, // dwIoControlCode
inputbuffer, // input buffer
inputbufferlength, // size of the input buffer
outputbuffer, // output buffer
inputbufferlength, // size of the input buffer - modified to be too small!
BytesReturned, // number of bytes returned
0 //(LPOVERLAPPED) &overlapped_struct // OVERLAPPED structure
);
DWORD error_num = GetLastError();
CloseHandle(hDevice);
std::cout << "STATUS IS: " << status << "\n";
std::cout << "ERROR IS: " << error_num;
return 0;
}
But this returned error 87 ERROR_INVALID_PARAMETER when attempting to call it.
My instinct was to debug the IOCTL by placing a breakpoint on partmgr!PartitionIoctlDsm - I was under the impression the targeted IOCTL was throwing the error. However my breakpoint was not being hit. So, then I moved on to placing a breakpoint on the IOCTL dispatch table itself
bp partmgr!PartitionDeviceControl
But that BP is never hit either. So, something else before my driver is throwing the error.
The Question(s)
How should I go about debugging this? How do I figure which driver is throwing the error?
What is the correct way to invoke this driver without throwing errors?
Why Am I getting this error?
Additional information
To be absolutely clear, I am dead set on using this particular IOCTL function. This is a learning exercise, and I am not interested in using alternative/easier to use functionality to implement the same effect. My curiosity lies in figuring out why the IO manager wont let me call the function.
I am running this code as admin.
I am running this code in a virtual machine.
I am debugging with windbg preview over a COM port.
Through some sleuthing I believe this is a filter driver, and that other drivers can intercept and handle this request.
Let me know if there is any other information I can provide.

Calling a function from another process

I apologize in advance for my English :D
How can I call a function from a process, knowing the pointer to it?
I tried this:
Process.cpp:
DWORD pid;
HWND hwnd;
HANDLE phandle;
void Attach() {
hwnd = FindWindow(NULL, L"GTA:SA:MP");
if (!hwnd) {
cout << "Process is not found" << endl;
system("pause");
}
else if (hwnd) {
cout << "Process was successfully loaded" << endl;
GetWindowThreadProcessId(hwnd, &pid);
phandle = OpenProcess(PROCESS_VM_READ, 0, pid);
}
else
{
cout << "Error 0x01" << endl;
system("pause");
}
}
void GameText(const char* szText, int iTime, signed int iStyle)
{
typedef void(__stdcall* GameText_t)(const char*, int, signed int);
GameText_t pGameText = (GameText_t)((char*)phandle + 0x69F2B0);
return pGameText(szText, iTime, iStyle);
}
main.cpp:
int main()
{
std::cout << "Hello World!\n";
Attach();
GameText("~r~Test!", 1000, 5);
}
And I get the following exception:
An exception was thrown at the address 0x006EF7B6 in wh_mta.exe:
0xC0000005: access violation during execution at 0x006EF7B6.
Why is this happening? How can I call a function by its pointer through HANDLE?
P.S
Reading an integer through HANDLE works great.
int Read_Int(int address) {
int value;
ReadProcessMemory(phandle, (void*)address, &value, sizeof(value), 0);
return value;
}
Maybe 30 years ago that would have worked :D :D :D
Processes can't access each other's memory… Every process has their own image of the memory, so address 0xWHATEVER in a process does not contain the same data as 0xWHATEVER in another process!
You need to make a library or use some inter process communication (IPC).
What you are doing is adding the pointer to the HANDLE of the process. You need the address of the process in it's virtual address space. To do so, use EnumProcessModules andGetModuleFileNameEx to find the filename of the module with the function you want. (Could be an EXE or a DLL.) EnumProcessModules returns an array of HMODULES which are just addresses of module in the specified process's virtual address space. So loop through the array, then cast the HMODULE that you need to a PBYTE. Then, add the function pointer to it, then try to execute.
Also, according your code, you are going to execute the function in YOUR program. That's fine, just make sure that if it needs to run in the target program, you'll need to use CreateRemoteThread to run it there.

Windows program entry point using EnumProcessModules returns unexpected value

I am running a simple app and trying to read a specific offset within it's memory using Window's PSAPI.
when I run my debugger, I get the real value of the memory address, and the relative one to my ".exe" entry point.
yet, when I run the following code, the base module I get as an entry point together with my offset yields a different address(it's wrong, and off by a few (hexa)demical points).
what might be the problem?
ReadMemory is a template for ReadProcessMemory
HWND WINDOW_HANDLE;
HANDLE PROC_HANDLE;
DWORD PROC_ID;
DWORD address;
SIZE_T bytesRead;
int InitReadMemory(const char* windowClass,const char* caption, DWORD addressOffset)
{
DWORD cbNeeded;
DWORD dwdResult;
HMODULE mainModule;
BOOL enumResult;
//Get the window handle
WINDOW_HANDLE = FindWindow(windowClass, NULL);
if(WINDOW_HANDLE == NULL)
{
//Window was not foud
return 10;
}
//Get the process ID
dwdResult = GetWindowThreadProcessId(WINDOW_HANDLE, &PROC_ID);
if(dwdResult==0)
{
//Getting Process ID failed
return 20;
}
//Open the process
PROC_HANDLE = OpenProcess(PROCESS_ALL_ACCESS, false, PROC_ID);
if(PROC_HANDLE==NULL)
{
//Process failed to open
return 30;
}
/*
*Get the Main Module-
*first entry in the returned HMODULE array from
*EnumProcessModules
*/
enumResult = EnumProcessModules(PROC_HANDLE, &mainModule, sizeof(HMODULE), &cbNeeded);
if(enumResult != 0)
{
//Failed enumerating process modules
return 40;
}
//offset the requested memory address from the application's base address
address = (DWORD)((UINT_PTR)mainModule + addressOffset);
#ifdef DEBUG
using namespace std;
char filenameBuffer[64]="";
string number;
stringstream stristream;
stristream << address;
stristream >> number;
cout << number << "\r\n" << endl;
GetModuleFileNameEx(PROC_HANDLE, mainModule , filenameBuffer, 256);
cout << (byte)ReadMemory<byte>() << "\r\n" << number << "\r\n" << filenameBuffer << endl;
system("PAUSE");
#endif
return 1;}
thank you in advance :)
P.S. I'm mostly just looking for pointers ...
bah dum tsss
Update:
apparently, checking for GetLastError value, EnumProcessModules prompts a 299 error code after it is done. and debugging shows that mainModule holds nothing... yet EnumProcessModules returns 0 as in "no errors".
yesterday, I managed to get it AND get GetModuleFileName to work propery(same code, only added GetLastError).
Apparently, my problem was that I was running the tests with the snippet
enumResult = EnumProcessModules(PROC_HANDLE, &mainModule, sizeof(HMODULE), &cbNeeded)
if(enumResult != 0)
{
//Failed enumerating process modules
return 40;
}
and a successful run of EnumProcessModules yields a nonzero result! (thus causing me some confusion and faulted my whole debugging process)
after I figured this detail out, I ran some old tests again and found out that my target process is 64 bit, while I was running a 32 bit application.
changed to 64bit and now it works like a charm

I2C error when using the Windows Monitor Configuration Functions

I'm attempting to get/set the brightness level of the monitor through the Windows API. I've tried both the Low-Level Monitor Configuration Functions and the High-Level Monitor Configuration Functions, but they both seem to be breaking in the same place. In both cases I have no problem getting the HMONITOR handle and getting the physical monitor handle from the HMONITOR, but once I try to query the DDC/CI capabilities, I get an error saying "An error occurred while transmitting data to the device on the I2C bus."
The particular functions that cause this error are GetMonitorCapabilities for the high-level functions and GetCapabilitiesStringLength for the low-level functions. They both cause the same error.
This leads me to believe that maybe my monitor doesn't support DDC/CI, but I know my laptop's monitor brightness can be changed through the control panel, so it must be controlled through software somehow. Also I can successfully use the WMI classes in a PowerShell script to get/set the brightness as described on this page. Most things I've read suggest that most modern laptop screens do support DDC/CI.
Is there any way to find out what is causing this error or to get more information about it? I'm currently working in C++ in Visual Studio 2013 on Windows 7. I could probably use WMI in my C++ program if I can't get this current method working, but I thought I would ask here first.
Here's the code I currently have:
#include "stdafx.h"
#include <windows.h>
#include <highlevelmonitorconfigurationapi.h>
#include <lowlevelmonitorconfigurationapi.h>
#include <physicalmonitorenumerationapi.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD minBrightness, curBrightness, maxBrightness;
HWND curWin = GetConsoleWindow();
if (curWin == NULL) {
std::cout << "Problem getting a handle to the window." << std::endl;
return 1;
}
// Call MonitorFromWindow to get the HMONITOR handle
HMONITOR curMon = MonitorFromWindow(curWin, MONITOR_DEFAULTTONULL);
if (curMon == NULL) {
std::cout << "Problem getting the display monitor" << std::endl;
return 1;
}
// Call GetNumberOfPhysicalMonitorsFromHMONITOR to get the needed array size
DWORD monitorCount;
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(curMon, &monitorCount)) {
std::cout << "Problem getting the number of physical monitors" << std::endl;
return 1;
}
// Call GetPhysicalMonitorsFromHMONITOR to get a handle to the physical monitor
LPPHYSICAL_MONITOR physicalMonitors = (LPPHYSICAL_MONITOR)malloc(monitorCount*sizeof(PHYSICAL_MONITOR));
if (physicalMonitors == NULL) {
std::cout << "Unable to malloc the physical monitor array." << std::endl;
return 1;
}
if (!GetPhysicalMonitorsFromHMONITOR(curMon, monitorCount, physicalMonitors)) {
std::cout << "Problem getting the physical monitors." << std::endl;
return 1;
}
std::cout << "Num Monitors: " << monitorCount << std::endl; // This prints '1' as expected.
wprintf(L"%s\n", physicalMonitors[0].szPhysicalMonitorDescription); // This prints "Generic PnP Monitor" as expected
// Call GetMonitorCapabilities to find out which functions it supports
DWORD monCaps;
DWORD monColorTemps;
// The following function call fails with the error "An error occurred while transmitting data to the device on the I2C bus."
if (!GetMonitorCapabilities(physicalMonitors[0].hPhysicalMonitor, &monCaps, &monColorTemps)) {
std::cout << "Problem getting the monitor's capabilities." << std::endl;
DWORD errNum = GetLastError();
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
LPVOID buffer;
FormatMessage(flags, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, NULL);
wprintf(L"%s\n", buffer);
return 1;
}
// Same error when I use GetCapabilitiesStringLength(...) here.
// More code that is currently never reached...
return 0;
}
Edit: Also I should note that physicalMonitors[0].hPhysicalMonitor is 0, even though the monitor count and text description are valid and the GetPhysicalMonitorsFromHMONITOR function returns successfully. Any thoughts on why this might be?
This is a "wonky hardware" problem, the I2C bus it talks about is the logical interconnect between the video adapter and the display monitor. Primarily useful for plug & play. Underlying error code is 0xC01E0582, STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA. It is generated by a the DxgkDdiI2CTransmitDataToDisplay() helper function in the video miniport driver. It is the vendor's video driver job to configure it, providing the functions that tickle the bus and to implement the IOCTL underlying GetMonitorCapabilities().
Clearly you are device driver land here, there isn't anything you can do about this failure in your C++ program. You can randomly spin the wheel of fortune by looking for a driver update from the video adapter manufacturer. But non-zero odds that the monitor is at fault here. Try another one first.
I know its bad time to reply but i thought you should know.
The problem you are facing is because of the DDC/CI disabled on your monitor so you should go to the monitor settings and check if DDC/CI is disabled and if it is, then you have to enable it and run your code again. It would work. If you were not able to find DDC/CI option ( some of the monitor have a separate button for enabling/disabling the DDC/CI like the Benq's T71W monitor has a separate down arrow button to enable/disable DDC/CI ) then you should refer to your monitor's manual or contact the manufacturer.
Hope that helps. and sorry for late reply.
Best of luck. :)
As I read the original question, the poster wanted to control a laptop display using DDC/CI. Laptop displays do not support DDC/CI. They provide a stripped down I2C bus sufficient to read the EDID at slave address x50, but that's it.

Createprocess and 0xc0000142 error

i have the following test code:
#define CMDLINE ".\\dummyFolder\\dummyProc.exe op1 op2 op3"
int main(int argc, char **argv) {
STARTUPINFO info;
info.cb = sizeof(STARTUPINFO);
info.lpReserved = NULL;
info.cbReserved2 = 0;
info.lpReserved2 = NULL;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES procAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
SECURITY_ATTRIBUTES threadAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
bool handlersInheritable = true;
char cmdLine2[sizeof(CMDLINE)];
strcpy(cmdLine2, CMDLINE);
char AppName[sizeof(".\\dummyFolder\\dummyProc.exe")];
strcpy(AppName, ".\\dummyFolder\\dummyProc.exe");
if (CreateProcess(AppName, cmdLine2, &procAttr, &threadAttr,
handlersInheritable, 0, NULL, NULL, &info, &processInfo)) {
//::WaitForMultipleObjects(procQty, handlers, waitForAll, waitInterval);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
CloseHandle(info.hStdError);
CloseHandle(info.hStdInput);
CloseHandle(info.hStdOutput);
} else {
std::cout << "Returned: " << GetLastError() << std::endl;
}
std::cout << "Exiting main process" << std::endl;
return 0;
}
This is just a test code for creating processes in windows. The problem is that when i launch "dummyProc.exe" i get a 0xc0000142 error.
The process dummyProc.exe runs fine from the command line, but not from within the code.
Here's the dummyProc code if it helps:
int main(int argc, char **argv) {
std::cout << "Working!!!!" << std::endl << "Receivedi: " << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return 0;
}
So, any ideas?
The most obvious thing that char cmdLine2[sizeof(CMDLINE)]; declares a string of length equal to your machine's pointer size. You need to use strlen(CMDLINE)+1 instead. Likewise for appName.
Note that the first parameter to CreateProcess does not need to be writeable. Just pass the string literal directly to it. No need for appName variable.
As for lpCommandLine which does need to be writeable it's easiest to do it like this:
char cmdline[] = "op1 op2 op3";
That gives you a writeable buffer. Note that you do not need to repeat the executable file name.
Another problem is that you have not initialized all the parameters to CreateProcess. For example the STARTUPINFO struct has 19 fields and you initialize only 3. You should initialize all your structs to 0 and then fill out any fields you need to be non-zero. Like this:
STARTUPINFO info = { 0 };
Do this for all the structs you pass.
You can, and should, pass NULL for the lpProcessAttributes and lpThreadAttributes parameters.
This answer is to relate another cause for 0xc0000142 - placed here (even though another answer was accepted for this question) because there is very little useful information on the intertubes about this error - and a shocking lack of any useful information on the subject from Microsoft - and so someone's internet search may get them here. (Well, mine did.)
So: You can get The application was unable to start correctly (0xc0000142) on starting a process written in C++ where you access though a null pointer in a constructor of a static object. (In my case it was in an initializer of a constructor of a static object.)
Your hint to this will be an event in the application log (event id 1000 source "Application Error") which has lines similar to the following:
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x0000000000000000
0xc0000005 is access violation, of course, and the offset of 0 (actually anything less than 0x10000 is a reference through a null pointer.
Anyway, the surprising thing (to me) is that evaluating statics happens before the debugger can attach (!!) so launching it with ImageFileExecutionOptions set or even directly within Visual Studio doesn't let you debug this thing!!
(And then of course you won't find 0xc0000142 in any Microsoft documentation whatsoever. Well done, NT team!)