Reading a process memory - c++

I'm trying to read the process memory of a console program using ReadProcessMemory() API function.
Updated Code:
HWND hWnd = FindWindow(NULL, "Read Memory Window");
DWORD ProcessId;
ProcessId = GetProcessId(hWnd);
GetWindowThreadProcessId(hWnd, &ProcessId);
HANDLE hProcess = OpenProcess(PROCESS_VM_READ,FALSE, ProcessId);
SIZE_T NumberOfBytesRead;
CHAR Buffer[128] = {0};
dwAddr = 0x0012FD6C; //address of array to get
BOOL sucess = ReadProcessMemory(hProcess, &dwAddr, &Buffer, 128, &NumberOfBytesRead);
I get null and garbage values as i run the program along with program to read the array.

your using a fixed address, that is generally a very bad idea, even more so now that windows vista and windows 7 use ASLR, making it unsafe for even fixed based modules(even without ASLR its unsafe, because the image can reallocated for various reasons).
also, that address looks very dodgy, how did you derive that address? and is it adjusted correctly as a virtual address and not a relative address?
finally and most importantly, you shouldn't be passing the address and buffer as you do, it should be passed like so:
BOOL sucess = ReadProcessMemory(hProcess, (LPVOID)dwAddr, &Buffer[0], 128, &NumberOfBytesRead);
or
BOOL sucess = ReadProcessMemory(hProcess, (LPVOID)dwAddr, Buffer, 128, &NumberOfBytesRead);

Related

How to fix "LPVOID: unknown size" error while using the CreateRemoteThread API?

I am trying create a tool for performing DLL-Injection by writing the the DLL in the Memory of a running process using VirtualAclloc() API and then finding the offset of the entrypoint and passing it to the CreateRemoteThread() API by adding the entry point offset to the base address of the VirtualAlloc function.
As I don't have any arguments that needs to be passed to lpStartAddress while calling CreateRemoteThread(), I initialized lpParameter as NULL.
LPVOID lpParameter = NULL;
...
...
thread_handle = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)(base_address + offset), lpParameter, 0, NULL);
While compiling the code I am getting the error :
LPVOID: Unknown Size" and the message "Expression must be a pointer to a complete object type.
Is there a way I can pass the value of lpParameter as NULL?
base_address + offset adds offset*sizeof *base_address bytes to the pointer base_address. But if the type of base_address is LPVOID then *base_address has no size, so this is an error. Have a look at the section on pointer arithmetic in your C++ book.
From the context I guess you should change base_address to be char* instead of LPVOID. Or you could add a cast like this (LPTHREAD_START_ROUTINE)((char*)base_address + offset).
In this case you need to follow the below process:
Get a handle to LoadLibraryA function in kernel32.dll
Allocate and Initialize memory in the address space of target process by using VirtualAllocEx
Write the path of the dll that you want to inject in the target processes address space by using WriteProcessMemory
Inject the dll by using CreateRemoteThread and pass the address of LoadLibraryA as the lpStartAddress
below is the example code:
char* dllPath = "C:\\testdll.dll";
int procID = 16092;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
if (!hProcess) {
printf("Error: Process not found.\n");
}
LPVOID lpvLoadLib = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA"); /*address of LoadLibraryA*/
if (!lpvLoadLib) {
printf("Error: LoadLibraryA not found.\n");
}
LPVOID lpBaseAddress = (LPVOID)VirtualAllocEx(hProcess, NULL, strlen(dllPath)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); /*Initialize and Allocate memory to zero in target process address space*/
if (!lpBaseAddress) {
printf("Error: Memory was not allocated.\n");
}
SIZE_T byteswritten;
int result = WriteProcessMemory(hProcess, lpBaseAddress, (LPCVOID)dllPath, strlen(dllPath)+1, &byteswritten); /*Write the path of dll to an area of memory in a specified process*/
if (result == 0) {
printf("Error: Could not write to process address space.\n");
}
HANDLE threadID = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpvLoadLib, lpBaseAddress, NULL, NULL); /*lpStartAddress = lpvLoadLib address of LoadLibraryA function*/
if (!threadID) {
printf("Error: Not able to create remote thread.\n");
}
else {
printf("Remote process created...!");
}
hope this helps

Stack Corruption With SetupDiXxx structures

I am having some trouble with the structures used to obtain device information. From what I understand it is somewhat tricky to set the cbSize correctly, and thus the API is writing data beyond where it is supposed to (causing the stack corruption). So far I have the following code:
GUID guid;
HidD_GetHidGuid(&guid);
HDEVINFO info;
info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVINFO_DATA DeviceInfoData;
memset(&DeviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
int deviceIndex = 0;
while (SetupDiEnumDeviceInfo(info, deviceIndex++, &DeviceInfoData))
{
SP_INTERFACE_DEVICE_DATA data;
data.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
int interfaceIndex = 0;
while (SetupDiEnumDeviceInterfaces(info, &DeviceInfoData, &guid, interfaceIndex++, &data))
{
//https://msdn.microsoft.com/en-us/library/windows/hardware/ff551120%28v=vs.85%29.aspx
//Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a NULLDeviceInterfaceDetailData pointer,
//a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize variable. In response to such a call, this function
//returns the required buffer size at RequiredSize and fails with GetLastError returning ERROR_INSUFFICIENT_BUFFER.
SP_DEVICE_INTERFACE_DETAIL_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
DWORD bufferSize = 0;
SetupDiGetDeviceInterfaceDetail(info, &data, NULL, 0, &bufferSize, nullptr);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
//Call the function again
SetupDiGetDeviceInterfaceDetail(info, &data, &interfaceData, bufferSize, NULL, &DeviceInfoData);
DWORD error = GetLastError();
if (error != ERROR_SUCCESS)
{
printf("Could not obtain device interface details. Error: %d \n", error);
}
}
}
The error which I get is:
Run-Time Check Failure #2 - Stack around the variable 'DeviceInfoData' was corrupted.
though I have seen SP_INTERFACE_DEVICE_DATA and SP_DEVICE_INTERFACE_DETAIL_DATA cause the same error
Any help is greatly appreciated!
It looks like your interfaceData buffer is too small.
Check the documentation for the DeviceInterfaceDetailData argument to SetupDiGetDeviceInterfaceDetail again.
If you want to get more info about driver development, I recommend the book USB Complete. I fixed the issue based on their explanation. The issue is as follows:
First, get the buffer size:
SetupDiGetDeviceInterfaceDetail(info, &data, NULL, 0, &bufferSize, nullptr);
Then, allocate the PSP_DEVICE_INTERFACE_DETAIL_DATA structure manually using malloc based on the size that was returned:
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceData;
interfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
notice the P in front of PSP_DEVICE_INTERFACE_DETAIL_DATA. This is Microsofts semantics for this API. It stands for pointer; something really easy to miss when looking at the documentation (if you also miss the ->)
The SetupDiGetDeviceInterfaceDetail function returns the size of the entire structure, so you need to allocate it to that size. I've seen examples that attempt to increment size until the error goes away. That approach is wrong... for alot of reasons. Obtain the size from SetupDiGetDeviceInterfaceDetail and then allocate the entire PSP_DEVICE_INTERFACE_DETAIL_DATA memory block based on that size. Don't forget to set cbSize to the size of the struct SP_DEVICE_INTERFACE_DETAIL_DATA
Once again, pay attention to the P in the naming conventions because it's easy to get the sizeof(PSP_DEVICE_INTERFACE_DETAIL_DATA) by mistake.

C++ return float

I create a API for a Game.
My Problem: I want to read a float value from the Memory.
Result (Cheat Engine) 100
My Result with the API: 0.00000
extern "C" __declspec(dllexport) float samp_health()
{
hwnd = FindWindow(NULL, L"MyGame");
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_VM_READ, false, pid);
float value = 0;
ReadProcessMemory(phandle, (float*)(PlayerPointer + HealthOffset), &value, 4, NULL);
CloseHandle(phandle);
return value;
}
What is wrong?
With this line,
HANDLE phandle = OpenProcess(PROCESS_VM_READ, false, pid);
you need to check for failure.
And in this following line,
ReadProcessMemory(phandle, (float*)(PlayerPointer + HealthOffset), &value, 4, NULL);
assuming the ReadProcessMemory works as roughly indicated by the arguments, the PlayerPointer needs to be a valid pointer in the process identified by phandle, and if the HealthOffset is an offset in bytes, then PlayerPointer needs to be a pointer to byte.
Most likely it's not.
Reading process memory is generally not a good way to communicate between processes.
Here are some alternatives:
Don't do process communication, do threads or whatever.
Use Windows COM technology.
Use Windows mailslots.
Use Windows window messages (e.g. WM_DATA).
Use sockets.
Use files.
Use pipes.
Almost anything, just not the direct access of process memory.
Summing up, the main problem is use of a too low level of abstraction.

Win 32 Writefile: Access Viloation and Error 1784

Two problems with the below code. To begin, I have been scouring this and various other forums for answers to my 1784 error code and everything I've tried has failed. Two of the threads I've checked on stackoverflow are WriteFile returning error 1784 and BlockWrite I/O Error 1784. I've checked some others on this forum but I'm not remembering exactly what the are right now.
I'm trying to save an array of structs to an empty binary file. The first problem is that I get an access violation if my size variable (nNumberOfBytesToWrite parameter) is anything less about 99000 bytes. That number jumps around. For awhile when I was testing it would have the access violation if it was 99,999 bytes but not 100,000 bytes. Of course, what I eventually want to do is set the size to the size of the entire array. The original code to handle that is now commented out so I can test with various sizes.
The second thing that happens (if I don't get an access violation) is I get error code 1784 and WriteFile fails every time. As other threads on this topic have stated, this is defined on MSDN as ERROR_INVALID_USER_BUFFER and the description is "The supplied user buffer is not valid for the requested operation." I've looked at MSDN's own example for opening files like this (http://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx) and have tried some variations based on their code, but nothing seems to work.
This problem is probably massively noob and I'm sure I'm overlooking something ridiculously simple, but if anyone has suggestions they'd be greatly appreciated.
case IDM_SAVE1:
{
HANDLE hFile = CreateFile("MineSave.mss", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
int test_buffer[] = {1,2,3,4,5,6,7,8,9,10};
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL bSuccess;
DWORD size = 100000; //DWORD size = (((sizeof(tile)) * tiles_total));
LPDWORD bytes_written = 0;
bSuccess = WriteFile(hFile, test_buffer, size, bytes_written, NULL);
if(bSuccess)
{
MessageBox(hwnd, "File saved successfully.", "Great Job!", MB_OK);
}
else
{
DWORD error = GetLastError();
MessageBox(hwnd, "Could not write to file.", "Error", MB_OK);
}
CloseHandle(hFile);
}
else
{
MessageBox(hwnd, "Could not create file.", "Error", MB_OK);
}
}
break;
Your buffer is the size of 10 ints, which is 40 bytes on Windows. You are trying to write 100,000 bytes from that buffer. That is undefined behaviour, a buffer overrun. Hence the access violation.
You must not pass a value greater than sizeof(test_buffer), i.e. 40, to the nNumberOfBytesToWrite parameter of WriteFile.
You'll need to write this file in a loop, writing 40 bytes at a time, until you have written as much as you need. Perhaps something like this:
BOOL bSuccess = TRUE;
DWORD bytesRemaining = 100000;
while (bSuccess && bytesRemaining>0)
{
DWORD bytesToWrite = std::min(sizeof(test_buffer), bytesRemaining);
DWORD bytesWritten;
bSuccess = WriteFile(hFile, test_buffer, bytesToWrite, &bytesWritten, NULL);
bytesRemaining -= bytesToWrite;
}
if (!bSuccess)
{
//handle error;
}
Writing 40 bytes at a time is pretty slow. You'll find it more efficient to write a few KB with each call to WriteFile.
Note that you aren't allowed to pass NULL to the lpNumberOfBytesWritten parameter if you also pass NULL to lpOverlapped, as you do here. From the documentation:
lpNumberOfBytesWritten [out, optional]
......
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
You must provide a buffer to receive the number of bytes written, either the lpNumberOfBytesWritten parameter must be non-NULL, or the lpOverlapped parameter must be non-NULL.
You are passing NULL for both, which is illegal and causes the access violation.

getting error code 998 Invalid access to memory location when trying to read from named pipe

I created a named pipe using WCF and C#, and a client to connect to it so that I know that it is working correctly. Now I'm trying to create a c++ client. So far I have been able to get the name of the pipe, connect to it, and write some data to it. When I try to read from it I'm getting error code 998 Invalid access to memory location. Here is the code I'm using:
HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, 2, NULL, OPEN_EXISTING, NULL, NULL);
BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
LPVOID buffer = 0;
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 10, &bytesRead, NULL);
I'm not sure what I'm doing wrong.
No memory has been allocated for buffer, it is currently a null pointer, and the code is requesting that 10 bytes of data be read into an array that does not exist. From ReadFile():
lpBuffer [out]
A pointer to the buffer that receives the data read from a file or device.
To rectify:
char buffer[10];