How would I read Memory into a wstring? - c++

I already tried using wchar_t and a for-loop to read the Memory wchar by wchar and it worked.
Working code:
int cl = 20;
std::wstring wstr;
wchar_t L;
for (int i = 0; i < cl; i++) {
ReadProcessMemory(ProcHandle, (unsigned char*)Address, &L, 2, NULL);
Address += 2;
wstr.push_back(L);
}
std::wcout << wstr << std::endl;
Now when I try using std::wstring and read directly into it, it fails for whatever reason.
int cl = 20;
std::wstring L;
L.resize(cl); // could use reserve?
ReadProcessMemory(ProcHandle, (unsigned char*)Address, &L, cl*2, NULL);
std::wcout << L << std::endl;
I figured I'd use (cl * 2) as size because wchar_t has 2 chars size.
I would expect it to print the wstring to wcout but instead it errors with something similar to Failed to read sequence
Note: I cannot use wchat_t[20] because I later want cl to be dynamic.
Edit: Forgot to say that I'm on std c++17

std::vector<wchar_t> is more suitable for your case.
&L is the address of the string object, not the string buffer. You wanna use &L[0], the address of the first wchar.

Related

How convert LPCWSTR to wchar_t*?

I require to convert a LPCWSTR data to wchar_t*. I tried a bunch of methods, and some work, but when I try to get their code page, they are showing different values.
Code overview:
std::string ChineseCharacter(LPCWSTR Data) //Data value: "丂\n"
{
CString sHexValue = "";
std::wstring sData(Data);
wchar_t* str1 = (wchar_t*)Data;
//wchar_t* str2 = (wchar_t*)_wcsdup(sData.c_str());
wchar_t* str3 = (wchar_t*)(L"丂\n"); //u4E02 -- CP 8140 ** CP is needed
for (int i = 0; i < 4; i++)
{
sHexValue2.Format("%02x", str1[i]);//-- 4E02 -- FAIL
//sHexValue2.Format("%02x", str2[i]);//-- 4E02 -- FAIL
sHexValue2.Format("%02x", str3[i]);//-- First loop: 81, second one: 40 -- OK
}
}
According to the watcher, the values are:
str1= L"丂\n"
str3= L"#\n"
My doubt is, how can I pass the value of Data to a wchar_t*, equal as when I hard-code the value?
Reference:
https://uic.io/en/charset/show/gb18030/
LPCWSTR is just an alias for const wchar_t*. To convert that to wchar_t*, you can use const_cast, eg:
wchar_t* str = const_cast<wchar_t*>(Data);
(just make sure you don't write anything to the memory that is pointed at).
However, nothing in the code you have shown requires the use of non-const wchar_t* (or std::wstring, either), so you can simply loop through Data directly, there is no need to convert LPCWSTR to wchar_t* at all, eg:
std::string ChineseCharacter(LPCWSTR Data)
{
CString sHexValue;
for (int i = 0; (i < 4) && (Data[i] != L'\0'); ++i)
{
sHexValue.Format("%02hx", static_cast<unsigned short>(Data[i]));
}
return static_cast<char*>(sHexValue);
}
Alternatively, using just standard C++:
std::string ChineseCharacter(const wchar_t *Data)
{
std::ostringstream sHexValue;
for (int i = 0; (i < 4) && (Data[i] != L'\0'); ++i)
{
sHexValue << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned short>(Data[i]);
}
return sHexValue.str();
}

C++ Unable to convert std::vector<BYTE> to a string or char array

I am currently working with the Registry using this GitHub library:
https://github.com/GiovanniDicanio/WinReg
I am trying to convert this vector<BYTE> to a char array or a string, to make a hash out of it with help of SHA-512. But I am stuck with converting it, I tried different methods. I don´t get any compiler errors, just the app crashes at runtime. I am using a DLL that I load into my process.
RegKey NetworkInterface_key(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}\\0001");
const std::vector<BYTE> InstallTimeStamp = NetworkInterface_key.GetBinaryValue(L"InstallTimeStamp");
MY SOLUTION:
Changed std::vector<BYTE> -> std::vector<unsigned char>
Used this methode:
template <typename T>
std::string to_hex(T data)
{
std::ostringstream result;
result << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast<int>(data);
return result.str();
}
std::string dump(const std::vector<unsigned char>& data)
{
if (data.empty()) return "";
auto size = data.size();
std::ostringstream result;
for(u32 i =0; i < size; i++)
{
result << "0x" + to_hex(data[i]);
if (i != size)
result << " ";
}
return result.str();
}
Credits: U. Bulle -> C++ Converting Vector<BYTE> to string where first vector byte is 0
You don't need that library, just do this:
HKEY key = 0;
BYTE timestamp[16] = { 0 };
LRESULT err = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}\\0001", 0, KEY_READ, &key);
if (err == 0)
{
DWORD dwType = 0;
DWORD dwSize = 16;
::RegQueryValueEx(key, L"InstallTimeStamp", NULL, &dwType, timestamp, &dwSize);
RegCloseKey(key);
}
As for converting those 16 bytes into "string". That doesn't make a lot of sense given that that those 16 bytes are binary data. You could do this:
std::string strTimestamp((char*)timestamp, 16);
But I suspect you just want a pointer to pass to a sha512 function that expects a char* data type. If that's the case, just do this:
const char* ts = (char*)timestamp;
Just remember the length of that array is fixed and is not a null terminated string. So your hash function should take a length parameter as well.
The RegKey::GetBinaryValue() method returns a std::vector<BYTE>. To convert that data to a char[] array, you don't really have to actually convert it at all, you can simply type-cast a pointer to the data instead:
const std::vector<BYTE> InstallTimeStamp = ...;
const char *pInstallTimeStamp = reinterpret_cast<const char*>(InstallTimeStamp.data());
But, if you want to convert the data to a std::string, then std::string has constructors that are appropriate for that purpose, eg:
const std::vector<BYTE> InstallTimeStamp = ...;
std::string sInstallTimeStamp(reinterpret_cast<const char*>(InstallTimeStamp.data()), InstallTimeStamp.size());
const std::vector<BYTE> InstallTimeStamp = ...;
std::string sInstallTimeStamp(InstallTimeStamp.begin(), InstallTimeStamp.end());
However, that being said, hashes operate on bytes, not on characters or strings, so you really should not need to convert the vector data to anything else at all, just hash its contents as-is. Unless you are using a hashing API that requires char/string input (if so, you should find a better hash API), in which case the above should suffice.

sprintf buffer issue, wrong assignment to char array

I got an issue with sprintf buffer.
As you can see in the code down below I'm saving with sprintf a char array to the buffer, so pFile can check if there's a file named like that in the folder. If it's found, the buffer value will be assigned to timecycles[numCycles], and numCycles will be increased. Example: timecycles[0] = "timecyc1.dat". It works well, and as you can see in the console output it recognizes that there are only timecyc1.dat and timecyc5.dat in the folder. But as long as I want to read timecycles with a for loop, both indexes have the value "timecyc9.dat", eventhough it should be "timecyc1.dat" for timecycles[0] and "timecyc5.dat" for timecycles1. Second thing is, how can I write the code so readTimecycles() returns char* timecycles, and I could just initialize it in the main function with char* timecycles[9] = readTimecycles() or anything like that?
Console output
#include <iostream>
#include <cstdio>
char* timecycles[9];
void readTimecycles()
{
char buffer[256];
int numCycles = 0;
FILE* pFile = NULL;
for (int i = 1; i < 10; i++)
{
sprintf(buffer, "timecyc%d.dat", i);
pFile = fopen(buffer, "r");
if (pFile != NULL)
{
timecycles[numCycles] = buffer;
numCycles++;
std::cout << buffer << std::endl; //to see if the buffer is correct
}
}
for (int i = 0; i < numCycles; i++)
{
std::cout << timecycles[i] << std::endl; //here's the issue with timecyc9.dat
}
}
int main()
{
readTimecycles();
return 0;
}
With the assignment
timecycles[numCycles] = buffer;
you make all pointers point to the same buffer, since you only have a single buffer.
Since you're programming in C++ you could easily solve your problem by using std::string instead.
If I would remake your code into something a little-more C++-ish and less C-ish, it could look something like
std::array<std::string, 9> readTimeCycles()
{
std::array<std::string, 9> timecycles;
for (size_t i = 0; i < timecycles.size(); ++i)
{
// Format the file-name
std::string filename = "timecyc" + std::to_string(i + 1) + ".dat";
std::ifstream file(filename);
if (file)
{
// File was opened okay
timecycles[i] = filename;
}
}
return timecycles;
}
References:
std::array
std::string
std::to_string
std::ifstream
The fundamental problem is that your notion of a string doesn't match what a 'char array' is in C++. In particular you think that because you assign timecycles[numCycles] = buffer; somehow the chars of the char array are copied. But in C++ all that is being copied is a pointer, so timecycles ends up with multiple pointers to the same buffer. And that's not to mention the problem you will have that when you exit the readTimecycles function. At that point you will have multiple pointers to a buffer which no longer exists as it gets destroyed when you exit the readTimecycles function.
The way to fix this is to use C++ code that does match your expectations. In particular a std::string will copy in the way you expect it to. Here's how you can change your code to use std::string
#include <string>
std::string timecycles[9];
timecycles[numCycles] = buffer; // now this really does copy a string

AscW equivalent from VB in C++

I am using the function AscW (in VB6) to convert a unicode character into the character code.
I would like to know if there is an equivalent to this function in C++.
For example, I would like to get the value 32 from the character " ".
I would like to do the following:
wstring wstringToLower(wstring u)
{
wstring s;
for (int i=0;i<u.size();i++)
{
wstring sChar;
sChar=u.substr(i,1);
int iChar=static_cast<int>(sChar);
int iNewChar=charCodeToLower(iChar);
wstring sNewChar;
sNewChar=wstring(iNewChar,1);
s+=sNewChar;
}
return s;
}
The error "No conversion function found for std::wstring to int" is raised in the line
int iChar=static_cast<int>(sChar);
Cast to int:
int main()
{
std::wstring u = L"abc";
std::wstring sChar = u.substr(1, 1);
for (int i = 0; i < sChar.size(); ++i)
std::cout << static_cast<int>(sChar[i]);
}

Environment Variables are in a char* how to get it to a std::string

I am retrieving the environment variables in win32 using GetEnvironmentStrings(). It returns a char*.
I want to search this string(char pointer) for a specific environmental variable (yes I know I can use GetEnvironmentVariable() but I am doing it this way because I also want to print all the environment variables on the console aswell - I am just fiddling around).
So I thought I would convert the char* to an std::string & use find on it (I know I can also use a c_string find function but I am more concerned about trying to copy a char* into a std::string). But the following code seems to not copy all of the char* into the std::string (it makes me think there is a \0 character in the char* but its not actually the end).
char* a = GetEnvironmentStrings();
string b = string(a, sizeof(a));
printf( "%s", b.c_str() ); // prints =::=
Is there a way to copy a char* into a std::string (I know I can use strcpy() to copy a const char* into a string but not a char*).
You do not want to use sizeof() in this context- you can just pass the value into the constructor. char* trivially becomes const char* and you don't want to use strcpy or printf either.
That's for conventional C-strings- however GetEnvironmentStrings() returns a bit of a strange format and you will probably need to insert it manually.
const char* a = GetEnvironmentStrings();
int prev = 0;
std::vector<std::string> env_strings;
for(int i = 0; ; i++) {
if (a[i] == '\0') {
env_strings.push_back(std::string(a + prev, a + i));
prev = i;
if (a[i + 1] == '\0') {
break;
}
}
}
for(int i = 0; i < env_strings.size(); i++) {
std::cout << env_strings[i] << "\n";
}
sizeof(a) in what you have above will return the size of char*, i.e. a pointer (32 or 64bits usually). You were looking for function strlen there. And it's not actually required at all:
std::string b(a);
should be enough to get the first environment variable pair.
The result of GetEnvironmentStrings() points to memory containing all environment strings. Similar to the solution of Puppy it will be put into a vector of string, where each string contains just one environment variable ("key=value")
std::vector<std::string> env_strings;
LPTCH a = GetEnvironmentStrings();
As example we will have 2 environment variables defined:
"A=ABC"
"X=XYZ"
LPTCH a will be:
A=ABC\0X=XYZ\0\0
Each variable is '\0' - terminated and finally the complete environment string (a) will be terminated with an additional '\0'.
strlen will return the size to the first occurrence of the termination character '\0'. The last string will always be empty.
while ((std::size_t len = strlen(a)) > 0)
{
env_strings.push_back(std::string(a, len));
a += len + 1;
}
Multi-byte character
For multi-byte characters it will work as well:
LPTCH a = GetEnvironmentStrings();
std::vector<std::wstring> env_strings;
while ((std::size_t len = wcslen(a)) > 0)
{
env_strings.push_back(std::wstring(a, len));
a += len + 1;
}
FreeEnvironmentStrings(a);
Does the following causes any problems?
char* a = GetEnvironmentStrings();
string b;
b=a;
printf( "%s", b.c_str() );
When you say:
string b = string(a, sizeof(a));
you are getting the size of a, which is a pointer and is probably 4. So you will get the first 4 characters. I'm not sure what you are really trying to do, but you should be able just to say:
string b( a );
char* a = ...;
string str(a);
string b;
b = a;
I assume you mean the Windows API GetEnvironmentStrings function. So, test the result against nullptr and perform simple assignment:
char* env = ::GetEnvironmentStrings();
if (0 != env)
{
std::string senv = env;
// use senv to find variables
}
else
{
// report problem or ignore
}