"ReadProcessMemory" how to get std::string? - c++

Programm_A
int main()
{
std::cout << "Process ID = " << GetCurrentProcessId() << "\n"; // Id my process (i get something like '37567')
std::string My_String = "JoJo"; // My string
std::cout << &My_String << std::endl; //here i get something like '0x0037ab7'
system("pause");
}
This program just outputs reference of string "JoJo" to console.
Programm_B
int main()
{
int id;
std::cin >> id;
DWORD ProcessId = id;
HANDLE ProcessHandle = OpenProcess(PROCESS_VM_READ, FALSE, ProcessId);
if (!ProcessHandle) {
std::cout << "Process is not found...\n";
return 0;
}
std::string r;
std::cin >> r; // this is me writing the link that I get in programs_A
DWORD address = std::strtoul(r.c_str(), NULL, 16);
std::string JoJo_string = " ";
ReadProcessMemory(ProcessHandle, (LPVOID)(address), &JoJo_string, sizeof(JoJo_string), 0); //here I want to get the JoJo_string value by reference from programm_A
std::cout << JoJo_string << std::endl;
}
The funny thing is that everything works fine with the "int" variable type. But std::string is not working. The exact value reads, but the program immediately gives an error:
[-- programm_B --]
[-- error --]

You can't easily read a std::string across process boundaries.
Different standard library implementations of std::string use different memory layouts for its data members. The std::string in your program may be using a different implementation than the program you are trying to read from.
But even if the two programs used the exact same implementation, it still wouldn't matter, because std::string is simply too complex to read with a single ReadProcessMemory() call. std::string uses dynamic memory for its character data, so one of its data members is a char* pointer to the data stored elsewhere in memory. Which is complicated by the fact that std::string might also implement a local Short-String Optimization buffer so short string values are stored directly in the std::string object itself to avoid dynamic memory allocations.
So, you would have to know the exact implementation of std::string being used by the target program in order to decipher its data members to discover where the character data is actually being stored, and in the case where SSO is not active then read the char* pointer, as well as the number of characters being pointed at (which itself is also determinate in an implementation-specific way), so you could then read the character data with another ReadProcessMemory() call.
In short, what you are attempting to do is a futile effort.

You most certainly CAN get a content of the std::string from another process. After all, the debuggers do that!
You need to execute data() and length() functions of that string and then read content of that memory. The important point is to halt execution of the second process while you are doing that, or that memory location can become invalid between your calls.

Related

Storing const char* gives me random characters

Okay so basically i have a struct like this
struct person{
const char* name;
const char* about_me;
const char* mom_name;
const char* age;
};
And then in order to make my code versatile i have
struct Person PersonAsArray[MAX_ARRAY - 1];
And then i have a file that reads in a bunch of stuff and eventually i parse it. but when i parse it i get a std::string so i gotta convert it to a const char* so heres some more of my code:
getline(file, line);
//break the line up into 2 parts (because in the file its "name=John")
//these two parts are called id and value
if(id == "name"){
const char* CCvalue = value.c_str();
cout << CCvalue << endl; // its fine here
PersonAsArray[i].name = CCvalue; //i is incremented each time i need a new struct
}
if(id == "age"){
PersonAsArray[i].age = atoi(value.c_str());
}
//and some more of this stuff... eventually i have
cout << PersonAsArray[0].name << endl;
cout << PersonAsArray[0].about_me << endl;
cout << PersonAsArray[0].mom_name << endl;
cout << PersonAsArray[0].age << endl;
but when i finally cout everything, i end up with something that looks like this. I'm just a little curious on whats going on and why its giving me symbols? and its not always the same symbols. Sometimes i get the smiley face, sometimes i dont even get the whole row of rectangles. I have no idea what im doing and its probably some major flaw in my coding. But this also happens when i do something like this
string hi = "hello"
for(i = 0; hi[i] != '\0'; i++){
char x = hi[i];
string done = "";
if(x == 'h') done += "abc";
if(x == 'e') done += "zxc";
if(x == 'l') done += "aer";
if(x == 'o') done += "hjg";
cout << done;
}
I think i remember getting these flower like shapes and i think i even saw chinese characters but again they were not consistent even if i didnt change anything in the program, if i ran it several times, i would see several different combination of symbols and sometimes no symbols would appear.
You did not read the documentation!
The value returned by std::string::c_str() does not live forever.
The pointer obtained from c_str() may be invalidated by:
Passing a non-const reference to the string to any standard library function, or
Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and rend().
The destructor is one such "non-const member function".
Once the pointer is invalidated, you cannot use it. When you try, you either get the data stored at some arbitrary place in memory (your computer's futile attempts to make sense of that data, as if it were text, are resulting in the flowers and Chinese characters you describe) or other unpredictable, bizarre symptoms.
Unfortunately you did not present a complete, minimal testcase so we have no idea how value really fits into your code, but it's clear that it does not survive intact between your "its fine here" and your problematic code.
Don't store the result of std::string::c_str() long-term. There's no need to, and it's rarely useful to.
tl;dr Make person store std::strings, not dangling pointers.
The problem is that you have something like
{
std::string value;
// fill value
PersonsAsArray[i].name = value.c_str();
}
Now, value is a local variable which gets destroyed upon exiting the scope in which it is declared. You store the pointer to its internal data to a .name but you are not copying it so after destruction it points to garbage.
You should have a std::string name field instead that const char*, that will handle copying and retaining the content by itself and its copy assignment operator or allocate memory for the const char* manually, for example through strdup.

Converting a Object's address into a char* or char array in C++

I am creating a simulated mobile network using named pipes for information transportation between processes. I had the idea of creating a frame class to hold the data I needed and to pass the address of that frame into the pipes. The only thing I cant figure out to save my life is how to convert the address of my frame into a character pointer in order to pass it into the write() function. This is an outline of what I have so far:
NFrame *frame = new NFrame;
// set frame information
char *f_address = (char*)(frame);
std::cout << f_address << std::cout;
whenever I call cout to verify the address all I get are unreadable characters. I've messed with reinterpret_cast and I run into the same situation.
What am I missing or am I even doing this right.
What you probably want is serialization. It is often preferable (for ease of debugging) to serialize in some textual format like JSON. You could use libraries like JsonCPP for that. See also s11n which is a binary serialization framework (but I recommend JSON).
You usually should not write the raw memory bytes of some complex C++ object, because they contain data which would be unreadable by most other programs and processes (e.g. internal pointers to your process; in another process running even the same program, they are likely to be different because of ASLR).
(You might write raw memory bytes if you are sure they are read by the same process; but even that could be erroneous for C++ programs)
If (e.g. for debugging purposes) you want to simply show the address of some heap allocated object, you might convert it to (void*) like:
std::cout << "frame#" << (void*)frame << std::endl;
but such addresses (often in hexa) are not very readable and of course don't tell aything about the internal state of your frame.
You could define (by overloading the output << operator) your own output << operator like
std::ostream& operator <<(std::ostream&, const NFrame&);
then code std::cout << (*frame) << std::endl
Of course, you can replace std::cout by some instance of std::ofstream to output into some file, or some instance of std::ostringstream to output into a string.
An address will have a lot of unprintable characters in it. What you probably want is to convert the address into raw bytes and then convert that into a hexadecimal string.
That's because cout 'thinks' you are passing it a string which is presented as char *.
Try this:
std::cout << reinterpret_cast<void*>(f_address) << std::endl;

What is the purpose of storing the content in memory before printing it?

I am new to C++ and currently using visual studio.
I see on many tutorials online that when reading from a file with ifstream, before we cout the contents when looping through each line, we write the contents of the current line to a char data[] var then cout the data.
Something like the following
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream f("D:\\file1.txt");
char a[80];
while(!f.eof())
{
f >> a;
cout << a << endl;
}
return(0);
}
What is the point of
char a[80];
...
f >> a;
cout << a << endl;
When we could just do
cout << f << endl;
And save declaring a char and wasting more lines of code?
The preferred method in C++ is:
#include<iostream>
#include<fstream>
int main()
{
std::ifstream f("D:\\file1.txt");
if( f )
{
std::string line;
while(getline(f, line) )
{
std::cout << line << endl;
}
}
return 0 ;
}
If you want to copy, or list files, use operating system commands. The operating system commands are more optimized for handling files. Also, they already exist and have been tested so you don't waste your time.
What is the purpose of storing the content in memory before printing it?
In your example, there isn't much of a point. The data being read from std::cin is being sent directly to std::cout to be displayed on the console. Generally, the only reasons you'd want to store the data in the program memory before printing it is if you want to modify the data or check properties of the data and take certain actions based on those properties.
It should be noted that while this is a common example, the use of while (!eof()) is the incorrect way to check the validity of the stream before reading data. This method checks the stream before the input is read, which can lead to undefined behavior if invalid data is read and subsequently used. The normal way to read data is to check the validity of the stream after performing the read. For example, in your program this would be changed to:
while (f >> a)
{
std::cout << a << std::endl;
}
After the read is performed, the stream will be converted to a boolean. It will return true or false depending on the validity of the stream. If the stream read the end-of-file (EOF) character then that would be a failed read and the stream will return false.
What is the point of
char a[80];
...
f >> a;
cout << a << endl;
when we could just do
cout << f << endl;
First, cout << f will not do what you expect. The stream insertion operator (operator<<()) is overloaded for certain types. f is of type std::ifstream - a type for which this operator is not overloaded. Pre-C++11 C++ IOStreams contained a conversion to void* so that they could be used in boolean contexts. The stream insertion operator is overloaded for pointers to void, so the output you would get is not something you'd expect. As of C++11 you'd get a compiler error that no operator overload could be found for that type.
There is, however, an overload for std::streambuf*, a pointer an IOStreams buffer. Each stream has a buffer that stores and maintains characters from the source or sink. The overload for this operator reads data from the buffer and sends it to its own buffer, so you can do something like this:
std::cout << f.rdbuf();
rdbuf() returns a pointer to the stream's buffer.
While this is an effective use of the stream's capabilities, the data is still being stored in the buffer of std::cout. Streams are buffered and data sent into the source or sink are consigned to a buffer where it waits until the buffer is flushed. You can use std::nounitbuf to unbuffer std::cout in order to write directly to the external device:
std::cout << std::nounitbuf
<< f.rdbuf();
For a simple example with a small file, buffering really isn't needed. If you have a very large file then buffering is very useful as the program doesn't have to make a system call for each character being inserted.

How to convert pid to const char pointer in c++?

I am trying to convert pid types to a const char pointer so that I can pass them in as an argument in a execlp function.
eg. execlp("/bin/ps", "-f", "--ppid", "9340,9345,9346,9342");
I know that you can convert a pid to a string eg. const std::string my_pid(str_pid.str());
And a string to a const char pointer eg. my_pid.c_str();
But how would you concatenate multiple pids into a const char pointer so I can run the execlp command with them?
ostringstream is probably what you want.
For instance,
std::ostringstream ostr;
for (int i=0; i<pids.count(); i++)
{
if (i > 0) ostr << ',';
ostr << pids[i];
}
execlp("/bin/ps", "-f", "--ppid", ostr.str().c_str());
You can concatenate all of your values together into a single std::string first, the pass the final std::string value to execlp(), eg:
std::string pids;
for (however many pids you have)
{
if (!pids.empty())
pids += ",";
pids += std::string(str_pid.str());
}
execlp("/bin/ps", "-f", "--ppid", pids.c_str());
A stringstream would be a good C++ way to do it.
std::stringstream myStream;
myStream << "a c string" << aStringObject << std::endl; // operate on the stream
std::string myNewString = myStream.str(); // create a string object
Treating the data as a stream is a fairly generic way to allow you to serialize and deserialize custom or builtin types. Custom types could include operator<< and operator>> to allow insertion and extraction respectively.
This approach also should have the advantage of speed over using temporary string objects and manipulating them. The stingstream (or any of its base classes) will employ a buffer under the covers. A loop with temporary strings will invoke several more constructors/allocations/destructors each iteration. This does depend on the underlying string representation as well. A copy on write (COW) string implementation would have fewer allocations and may only update a reference, but updating the work string will still require a new string.

Serializing struct containing char*

I'm getting an error with serializing a char* string error C2228: left of '.serialize' must have class/struct/union I could use a std::string and then get a const char* from it. but I require the char* string.
The error message says it all, there's no support in boost serialization to serialize pointers to primitive types.
You can do something like this in the store code:
int len = strlen(string) + 1;
ar & len;
ar & boost::serialization::make_binary_object(string, len);
and in the load code:
int len;
ar & len;
string = new char[len]; //Don't forget to deallocate the old string
ar & boost::serialization::make_binary_object(string, len);
There is no way to serialize pointer to something in boost::serialization (I suspect, there is no actual way to do that too). Pointer is just a memory address, these memory addresses are generally specific for instance of object, and, what's really important, this address doesn't contain information where to stop the serialization.
You can't just say to your serializer: "Hey, take something out from this pointer and serialize this something. I don't care what size does it have, just do it..."
First and the optimal solution for your problem is wrapping your char* using std::string or your own string implementation. The second would mean writing special serializing routine for char* and, I suspect, will generally do the same as the first method does.
Try this:
struct Example
{
int i;
char c;
char * text; // Prefer std::string to char *
void Serialize(std::ostream& output)
{
output << i << "\n";
output << c << "\n";
// Output the length of the text member,
// followed by the actual text.
size_t text_length = 0;
if (text)
(
text_length = strlen(text);
}
output << text_length << "\n";
output << text << "\n";
};
void Input(std::istream& input)
{
input >> i;
input.ignore(1000, '\n'); // Eat any characters after the integer.
input >> c;
input.ignore(1000, '\n');
// Read the size of the text data.
size_t text_length = 0;
input >> text_length;
input.ignore(1000, '\n');
delete[] text; // Destroy previous contents, if any.
text = NULL;
if (text_length)
{
text = new char[text_length];
input.read(text, text_length);
}
};
Since pointers are not portable, the data must be written instead.
The text is known as a variable length field. Variable length fields are commonly output (serialized) in two data structures: length followed by data OR data followed by terminal character. Specifying the length first allows usage of block reading. With the latter data structure, the data must be read one unit at a time until the terminal character is read. Note: the latter data structure also implies that the terminal character cannot be part of the set of data items.
Some important issue to think about for serialization:
1. Use a format that is platform independent, such as ASCII text for numbers.
2. If a platform method is not available or allowed, define the exact specification for numbers, including Endianness and maximum length.
3. For floating point numbers, the specification should treat the components of a floating point number as individual numbers that have to abide by the specification for a number (i.e. exponent, magnitude and mantissa).
4. Prefer fixed length records to variable length records.
5. Prefer serializing to a buffer. Users of the object can then create a buffer of one or more objects and write the buffer as one block (using one operation). Likewise for input.
6. Prefer using a database to serializing. Although this may not be possible for networking, try every effort to have a database manage the data. The database may be able to send the data over the network.