ReadProcessMemory always reads 0 - c++

I'm creating a cheat for educational purpose (on windows for now) on a small game. My error is so far is that ReadProcessMemory always reads 0.
LPCVOID addr = (LPCVOID *) 0x1228A93C; // TO-DO: c++ casts
int dest = 0;
SIZE_T read = 0;
bool error = ReadProcessMemory(process, addr, &dest, sizeof(int), &read);
if (!error) {
printf("I read %llu w/ %u at %p\r\n", read, dest, addr);
} else {
printf("This isn't working: %p / %llu\r\n", addr, read);
std::cerr << "err: " << std::to_string(::GetLastError()) << std::endl;
return (1);
}
There, I try to read the amount on money in the game. By using Cheat Engine, I get the value that changes everytime you use your money which is 0x1228A93C in the code snippet above. If I change the value pointed by this address in cheat engine, the money also change in game so I guess this is right address.
Nonetheless when I run this snippet, I get this output:
I read 0 w/ 0 at 0x1228a93c
which means it doesn't read.
Note: There is more code, in my program, above this one but this is basically finding the game window, create a snapshot of the game and find the exe module.

This is probably what you want:
LPCVOID addr = (LPCVOID *) 0x1228A93C; // TO-DO: c++ casts
int dest = 0;
SIZE_T read = 0;
if (ReadProcessMemory(process, addr, &dest, sizeof(int), &read))
{
printf("I read %llu w/ %u at %p\r\n", read, dest, addr);
} else {
auto lasterror = ::GetLastError(); // first thing to do: call GetLastError
printf("This isn't working: %p / %llu\r\n", addr, read);
std::cerr << "err: " << lasterror << std::endl; // std::to_string is useless here
}
In case of error the first thing to do is call GetLastError() because you don't know if cout will call SetLastError() or not.

Related

Creating a pseudo terminal in C++ that can be used by other programs

I have created a pseudo terminal in C++ using the following code:
int main(int, char const *[])
{
int master, slave;
char name[1024];
char mode[] = "0777"; //I know this isn't good, it is for testing at the moment
int access;
int e = openpty(&master, &slave, &name[0], 0, 0);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
if( 0 != unlockpt(slave) )
{
perror("Slave Error");
}
access = strtol(mode, 0, 8);
if( 0 > chmod(name, access) )
{
perror("Permission Error");
}
//std::cout << "Master: " << master << std::endl;
std::printf("Slave PTY: %s\n", name);
int r;
prompt = "login: ";
while(true)
{
std::cout << prompt << std::flush;
r = read(master, &name[0], sizeof(name)-1);
checkInput(name);
name[r] = '\0';
std::printf("%s", &name[0]);
std::printf("\n");
}
close(slave);
close(master);
return 0;
}
It works pretty well in the sense that from another terminal, I can do:
printf 'username' > /dev/pts/x
and it will appear and be processed as it should.
My question is: when I try to use screen, nothing appears on the screen terminal. Then when I type, it comes through to my slave 1 character at a time.
Does anyone know why this is? Or how I can fix it.
I can provide more detail if required.
Thank you :)
Because you're not flushing the buffer after you use printf.
As pauls answer already suggest you need to flush the buffer.
To do so you can use the tcflush function.
The first argument is the int of the file descriptor and the second can be one of the following:
TCIFLUSH Flushes input data that has been received by the system but
not read by an application.
TCOFLUSH Flushes output data that has been written by an application
but not sent to the terminal.
TCIOFLUSH Flushes both input and output data.
For more information see: https://www.ibm.com/docs/en/zos/2.3.0?topic=functions-tcflush-flush-input-output-terminal

Edited code using ReadProcessMemory has issues

asked a question Call CloseHandle on handle that is a function parameter?
After someone edited the code, I updated it to find the code no longer works as intended.
intptr_t readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes)
{
intptr_t memValue = 0;
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return memValue;
}
In the line
ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
The memValue wouldn't compile without (LPVOID) or (LPCVOID) casts, but with them the code no longer reads the memory (or writes in the case of the functions using WriteProcessMemory
Originally (and now I've changed it back in my little program) it uses a reference &memValue and works fine.
My question is:
Should this work?
Or is the edit correct and the rest of my program potentially wrong?
I can provide more code if needed, just not sure which bits and didn't want to clog up the screen more than I have... Also should I rollback the edit?
The third parameter of ReadProcessMemory() is a memory address in the calling process where the function writes the read data to. You are not passing a memory address, though. In the code shown in the third revision to the original question, you were type-casting the value of an uninitialized integer variable into a memory pointer. So the function would try to write to random memory. Now you have removed the type-cast, so the code should not even compile anymore.
Your readMem() function is not designed correctly. You need to change it so that either:
The caller allocates memory of the required size and then the function simply fills the memory:
bool readMem(HANDLE processHandle, intptr_t address, void *memValue, int sizeToReadBytes)
{
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return success;
}
intptr_t memValue = 0;
readMem(processHandle, address, &memValue, sizeof(memValue));
The function allocates memory and returns it to the caller:
void* readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes)
{
uint8_t memValue = new uint8_t[sizeToReadBytes];
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success) {
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
delete [] memValue;
memValue = NULL;
}
return memValue;
}
intptr_t *memValue = (intptr_t*) readMem(processHandle, address, sizeof(intptr_t));
...
delete [] memValue;
Or:
bool readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes, std:vector<uint8_t> &memValue)
{
memValue.resize(sizeToReadBytes);
bool success = ReadProcessMemory(processHandle, (LPVOID)address, &memValue[0], sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return success;
}
std::vector<uint8_t> buffer;
readMem(processHandle, address, sizeof(intptr_t), buffer);
intptr_t memValue = (intptr_t*) &buffer[0];

c++ it seems that variable doesn't " flush " with multi thread

is_master_ def:
volatile bool is_master_;
is_master_ value is set to true by another thread , but It seems that is_master_ value dosnt flush (it doesn't cout the FATAL ERROR HAS OCCURRED... ). If i add cout << "foo" <
void MasterSlaveSynchronize::validateSingleMaster(){
if(is_master_){
cout << "FATAL ERROR HAS OCCURRED BOTH MASTER";
if(!is_leader_master_){
cout << "CHOSE AS VICTIM IN MASTER-MATSER. SET THIS HOST AS SLAVE";
is_master_ = false;
}
}
}
The caller code:
while(1){
int n = recvfrom(sockId, buf, HEARBEAT_SIZE, 0, (struct sockaddr *) &from,
&length);
if (n < 0) {
REGISTER_ERROR("Failed to recieved hearbeat");
} else {
gettimeofday(&instance_->last_hearbeat_got_, NULL);
instance_->validateSingleMaster();
}
}
You wanted me to post my comment as an answer:
Maybe it does, but because you don't use a newline your output stream
doesn't flush.
This behaviour is explained reasonably well here:
Why does printf not flush after the call unless a newline is in the format string?

How do I call a WCF method from c++ using Named pipes?

UPDATE:
Looking through the protocol here, I can't figure out what goes into the Unsized Envelope Record. I can't find any examples online.
ORIGINAL:
I have the following WCF service
static void Main(string[] args)
{
var inst = new PlusFiver();
using (ServiceHost host = new ServiceHost(inst,
new Uri[] { new Uri("net.pipe://localhost") }))
{
host.AddServiceEndpoint(typeof(IPlusFive), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "PipePlusFive");
host.Open();
Console.WriteLine("Service is Available. Press enter to exit.");
Console.ReadLine();
host.Close();
}
}
[ServiceContract]
public interface IPlusFive
{
[OperationContract]
int PlusFive(int value);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PlusFiver : IPlusFive
{
public int PlusFive(int value)
{
Console.WriteLine("Adding 5 to " + value);
return value + 5;
}
}
I output the adding 5 line so I know if the server processed the
request or not.
I have a .NET client that I used to test this and everything works as
expected.
Now I want to make an unmanaged C++ client for this.
I figured out how to get the name of the pipe, and write to it.
I've downloaded the protocol from here
I can write to the pipe but I can't read to it. Whenever I try to read from it I get a ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended. error. If I replace the read with a write, the write is successful, so I don't think that the pipe is closed, at least not until I try to do a read.
Here is how I'm connecting to the pipe.
HANDLE OpenPipe(OLECHAR* bstrGuid)
{
wstring pipeName = L"\\\\.\\pipe\\";
wstring strGuid = bstrGuid;
pipeName.append(strGuid.substr(1,36));
wcout << "Pipe Name " << endl;
wcout << pipeName.c_str() << endl;
HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if(hPipe == INVALID_HANDLE_VALUE)
{
wcout << "failed to create pipe" << endl;
system("pause");
return NULL;
}
return hPipe;
}
this is how i'm creating the first message that I'm sending
std::list<wchar_t> GetFirstMessage()
{
std::list<wchar_t> message;
message.push_back(0x00);// version record
message.push_back(0x01);// major version
message.push_back(0x00);// minor version
message.push_back(0x01);// mode record
message.push_back(0x01);// singleton-unsized mode
message.push_back(0x02);// via record
wstring url = L"net.pipe://localhost/PipePlusFive";
message.push_back(url.length());// via length
for(int x= 0;x<url.length();x++)
{
message.push_back(url[x]); // via
}
message.push_back(0x03);
message.push_back(0x08);
return message;
}
This is how I'm writing it to the file.
int WriteMessage(HANDLE hPipe, LPVOID message, int size)
{
DWORD bytesWritten;
BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
wcout << "Bytes Written: " << bytesWritten << endl;
if(bWrite == false)
{
wcout << "fail"<<endl;
CloseHandle(hPipe);
system("pause");
return 1;
}
return 0;
}
list<wchar_t> full_message = GetFirstMessage();
int result = WriteMessage(hPipe, &full_message, full_message.size());
if (result == 1)
{ return 1;}
Here is how I'm writing the end message
wchar_t message = 12;
result = WriteMessage(hPipe, &message, 1);
if (result == 1)
{ return 1;}
here is how I'm trying to read the response
char buffer[10];
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 1, &bytesRead, NULL);
if(bRead == false)
{
wcout << "fail read"<<endl;
wcout << "error: " << GetLastError() << endl;
CloseHandle(hPipe);
system("pause");
return 1;
}
I'm new to c++, so I don't know if I'm not following the protocol correctly or making a stupid mistake in the way I'm trying to do this?
UPDATE:
The problem was that I was writing the pointer address to the named pipe instead of the contents of the list. I've fixed that And I'm now able to read the Preamble Ack Record. Now I have to figure out what needs to be sent for the next part of the protocol.
Check if this works for you
Try to open a named pipe. (CreateFile)
Set the read mode and the blocking mode of the specified named pipe. (SetNamedPipeHandleState)
Send a message to the pipe server and receive its response. (WriteFile, ReadFile)
Close the pipe. (CloseHandle)

ReadFile lpBuffer parameter

I am using ReadFile to read a simple string that I wrote to a file using WriteFile.
Have a simple string: "Test string, testing windows functions".
Used WriteFile to write that to a file.
Now I want to use ReadFile to confirm that it was written to the file. I need to compare what I read to the original string above. To Read from the file I have
DWORD dwBytesRead;
char buff[128];
if(!ReadFile(hFile, buff, 128, &dwBytesRead, NULL))
//Fail
The function returns true so it is reading from the file. The problem is buff is full of just ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ. I've never come across LPVOID before so I don't know if it is something there or what. Is there a way to do this string comparison?
EDIT: The code i use to write to the file is quite simple:
if(!WriteFile(hFile, sentence.c_str(), sentence.length(), &bytesWritten, NULL))
{
//FAIL
}
The file pointer needs rewound after the WriteFile() and before the ReadFile(). As it stands, ReadFile() does not fail but reads zero bytes thus buff is unchanged. As buff is uninitialised it contains junk. To rewind the file pointer to the beginning of the file use SetFilePointer():
#include <windows.h>
#include <iostream>
#include <string>
int main()
{
HANDLE hFile = CreateFile ("myfile.txt",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile)
{
std::string sentence("a test");
DWORD bytesWritten;
if (WriteFile(hFile,
sentence.c_str(),
sentence.length(),
&bytesWritten,
NULL))
{
if (INVALID_SET_FILE_POINTER != SetFilePointer(hFile,
0,
0,
FILE_BEGIN))
{
char buf[128] = { 0 }; /* Initialise 'buf'. */
DWORD bytesRead;
/* Read one less char into 'buf' to ensure null termination. */
if (ReadFile(hFile, buf, 127, &bytesRead, NULL))
{
std::cout << "[" << buf << "]\n";
}
else
{
std::cerr << "Failed to ReadFile: " <<
GetLastError() << "\n";
}
}
else
{
std::cerr << "Failed to SetFilePointer: " <<
GetLastError() << "\n";
}
}
else
{
std::cerr << "Failed to WriteFile: " << GetLastError() << "\n";
}
CloseHandle(hFile);
}
else
{
std::cerr << "Failed to open file: " << GetLastError() << "\n";
}
return 0;
}
The function returns true so it is reading from the file. The problem is buff is full of just ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ.
ReadFile only fills the buffer up to the value of dwBytesRead. If you're trying to work with a string, you'll have to null terminate it yourself after ReadFile returns:
buff [dwBytesRead] = 0;
You should not use 128 as the nNumberOfBytesToRead, since you can get out of bounds while printing the string (or otherwise considering buff as a 0-terminated string). Also check dwBytesRead if it really reads that many bytes, and 0-terminate the string as suggested by #James McLaughlin.