File i/o garbled - c++

The data between these two functions is becoming garbled. Inspecting the variables on each side show that the data is definitely different. The message size signal does work. It's the second read/write function that has the problem.
Here is my write function and its counter read function:
string Pipe::RecvCompressedMessage()
{
int message_size = 0;
DWORD dwBytesRead = 0;
string buf, data;
byte size_in[sizeof(int)];
if (!ReadFile(_h, &message_size, sizeof(int), &dwBytesRead, NULL))
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
Close();
return "";
}
if (message_size < 0)
return "";
buf.resize(message_size);
int total_bytes_read = 0;
while(total_bytes_read < message_size)
{
if (!ReadFile(_h, (LPVOID) &buf, message_size - total_bytes_read, &dwBytesRead, NULL))
{
int err = GetLastError();
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
Close();
return "";
}
data.append(buf);
total_bytes_read += dwBytesRead;
}
std::string decompressed;
boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::bzip2_decompressor());
out.push(boost::iostreams::back_inserter(decompressed));
boost::iostreams::copy(boost::make_iterator_range(buf), out);
return decompressed;
}
void Pipe::SendCompressedMessage(string message)
{
std::string compressed;
boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::bzip2_compressor());
out.push(boost::iostreams::back_inserter(compressed));
boost::iostreams::copy(boost::make_iterator_range(message), out);
DWORD dwBytesWritten;
int message_size = compressed.length();
if (WriteFile(_h, &message_size, sizeof(int), &dwBytesWritten, NULL) == 0)
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
Close();
return;
}
if (WriteFile(_h, (LPVOID *) &compressed, message_size, &dwBytesWritten, NULL) == 0)
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
Close();
return;
}
}

string buf, data;
...
if (!ReadFile(_h, (LPVOID) &buf, message_size - total_bytes_read, &dwBytesRead, NULL))
You pass pointer to string object as lpBuffer to ReadFile. Replace string with vector<char>:
vector<char> buf;
...
buf.resize(message_size - total_bytes_read);
if (!ReadFile(_h, &buf[0], message_size - total_bytes_read, &dwBytesRead, NULL))

You are writing a std::string instead a char *:
if (WriteFile(_h, (LPVOID *) (compressed.c_str()), message_size, &dwBytesWritten, NULL) == 0)

Related

Converting char to wchar_t

I'm trying to modify this function https://stackoverflow.com/a/35658917/19324589
from CStringA (i have no idea what data type is it) to std::wstring
char buf[1024] to wstring buf
'original' function:
char buf[1024];
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
buf[dwRead] = 0;
strResult += buf;
my attempt:
when i modify buf from char to wstring, it stores only garbage after the ReadFile line.
std::wstring strResult;
// ...
std::wstring buf(1024, '\0');
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf.data(), min((buf.size() * sizeof(wchar_t)), dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
strResult += buf;
I end up doing:
bool bProcessEnded = false;
std::string result;
for (; !bProcessEnded;)
{
// Give some timeslice (50 ms), so we won't waste 100% CPU.
bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;
// Even if process exited - we continue reading, if
// there is some data available over pipe.
for (;;)
{
char buf[1024];
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf, min((sizeof(buf) - 1), dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
buf[dwRead] = 0;
result += buf;
}
} //for
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return to_wstring(result);
In my use case buf is returning a data like already connected to 127.0.0.1:5555
I would like to understand what i'm doing wrong?

How can I read a vector of structures in a mapped-file?

I have 2 programs, one gets all processes information using Windows API and stores them in a vector of structure like this:
struct Info{
int pid,ppid;
char exeName[256];
}
I keep back_pushing structure in vector when i populate a structure with data.
Now, I've tried to use memcpy() to memorize data in mapped-file but I can't read it properly in the second program. Can you help me to figure out how to read data properly?
Code program 1:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include <vector>
struct InfoProces {
DWORD pid;
DWORD ppid;
char exeName[256];
};
int main(){
HANDLE hProcesses;
PROCESSENTRY32 pe32;
hProcesses = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if (hProcesses == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot failed. err = %d", GetLastError());
return -1;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcesses, &pe32)) {
printf("Process32First failed. err = %d", GetLastError());
CloseHandle(hProcesses);
return -1;
}
HANDLE hdata = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024 * 1024, "data");
if (hdata == NULL) {
printf("Can't create a file mapping. err = %d", GetLastError());
return -1;
}
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapping file. err = %d", GetLastError());
return -1;
}
do {
InfoProces pi;
pi.pid = pe32.th32ProcessID;
pi.ppid = pe32.th32ParentProcessID;
strcpy(pi.exeName, pe32.szExeFile);
} while (Process32Next(hProcesses, &pe32));
getchar();
CloseHandle(hProcesses);
return 0;
Code program 2:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <vector>
#include <stdio.h>
struct InfoProces {
DWORD pid;
DWORD ppid;
char exeName[256];
};
int main()
{
HANDLE hdata = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "data");
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapped file. err = %d", GetLastError());
return -1;
}
std::vector<InfoProces>processes;
memcpy(&processes,pdata,sizeof(data));
for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);
return 0;
}
As the comment pointed out, you have got the starting address of the mapped view(pdata), You can only use the pdata for memory sharing, but not any stack address of the process.
Try to copy the memory of InfoProces to the pdata in program 1:
memcpy(pdata, &pi, sizeof(InfoProces));
In addition, in program 2, you did not set the size for the vector, and you should replace &processes with processes.data(). You also need to know the size of the array you added in program 1:
std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);
Following code works for me.
Program 1:(Record the count of InfoProces and save it to a DWORD in the beginning of pdata)
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapping file. err = %d", GetLastError());
return -1;
}
unsigned char* begin = pdata;
//offset a size of DWORD;
DWORD count = 0;
pdata += sizeof(DWORD);
do {
InfoProces pi;
pi.pid = pe32.th32ProcessID;
pi.ppid = pe32.th32ParentProcessID;
strcpy(pi.exeName, pe32.szExeFile);
memcpy(pdata, &pi, sizeof(InfoProces));
pdata += sizeof(InfoProces);
count++;
} while (Process32Next(hProcesses, &pe32));
memcpy(begin, &count, sizeof(DWORD));
getchar();
UnmapViewOfFile(begin);
CloseHandle(hdata);
CloseHandle(hProcesses);
...
Program 2:
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapped file. err = %d", GetLastError());
return -1;
}
unsigned char* begin = pdata;
DWORD count = 0;
memcpy(&count, pdata, sizeof(DWORD));
pdata += sizeof(DWORD);
std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);
for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);
UnmapViewOfFile(begin);
CloseHandle(hdata);
...
Finally, do not forget to close the handle and unmap address.

WriteFile returns invalid handle

I am attempting to use Windows WriteFile API as follows:
class FileWriter
{
public:
FileWriter(const std::string & path);
~FileWriter();
bool write(unsigned char * buffer, int num_bytes, unsigned __int64 offset);
private:
HANDLE file_h;
};
The implementation is simple as:
FileWriter::FileWriter(const std::string & path)
{
file_h = CreateFileA(path.c_str(), GENERIC_WRITE,
FILE_SHARE_READ, 0, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
if (file_h == INVALID_HANDLE_VALUE) {
throw std::runtime_error("Could not open the output file");
}
}
FileWriter::~FileWriter()
{
if (file_h != INVALID_HANDLE_VALUE) {
CloseHandle(file_h);
}
}
bool FileWriter::write(unsigned char * buffer, int num_bytes,
unsigned __int64 offset)
{
if (file_h != INVALID_HANDLE_VALUE && buffer) {
OVERLAPPED overlapped;
overlapped.Offset = offset & 0xFFFFFFFF;
overlapped.OffsetHigh = offset >> 32;
BOOL e = WriteFile(file_h, buffer, num_bytes,
0, &overlapped);
DWORD c = GetLastError();
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, c, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
if (e == FALSE && c == ERROR_IO_PENDING) {
return true;
}
else {
if ((e == TRUE) && (c == ERROR_SUCCESS))
return true;
}
}
return false;
}
This always fails with The handle is invalid error. However, the file handle is always valid. I even check for it. So, I am not sure what I am doing wrong.

How can i see contents of buffer and compare with dll file?

I try to write dll injector with nativeApi. For this reason, i wrote this code. NtReadFile function reads something but i cant see anything except for the first value of FileReadBuffer. Also, i dont know anything about how does dll look into buffer.
(1)How can i compare buffer and dll file?
(2)How can i be sure the code runs correct.
(3)And please tell me my mistake in the code.
bool Injector::initiationDll(const std::string& dllPath)
{
if (!isDllExist(dllPath))
{
printf("Dll not found!\n");
return false;
}
else
{
printf("LibraryPath: %s\n", dllPath);
NTSTATUS status; HANDLE lFile;
OBJECT_ATTRIBUTES objAttribs = { 0 }; UNICODE_STRING unicodeString;
std::string dllPathWithprefix = "\\??\\" + dllPath;
std::wstring wString = std::wstring(dllPathWithprefix.begin(), dllPathWithprefix.end()); PCWSTR toPcwstr = wString.c_str();
RtlInitUnicodeString(&unicodeString, toPcwstr);
InitializeObjectAttributes(&objAttribs, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
objAttribs.Attributes = 0;
const int allocSize = 2048;
LARGE_INTEGER largeInteger;
largeInteger.QuadPart = allocSize;
IO_STATUS_BLOCK ioStatusBlock;
status = NtCreateFile(
&lFile,
GENERIC_READ | FILE_READ_DATA | SYNCHRONIZE,
&objAttribs,
&ioStatusBlock,
&largeInteger,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(status)) {
printf("CreateFile failed..\n");
return false;
}
else {
printf("Library Handle : %p\n", lFile);
DWORD fileSize = getDllSize(dllPath);
if (fileSize == 0)
{
printf("File size is zero.\n");
return false;
}
else
{
printf("File size : %d byte.\n", fileSize);
PVOID FileReadBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!FileReadBuffer)
{
printf("\nError: Unable to allocate memory(%d)\n", GetLastError());
status = NtClose(lFile);
return false;
}
else {
printf("Allocate %d byte for buffer.\n", fileSize);
status = NtReadFile(
lFile,
NULL,
NULL,
NULL,
&ioStatusBlock,
FileReadBuffer,
sizeof(FileReadBuffer),
0, // ByteOffset
NULL);
if (!NT_SUCCESS(status))
{
printf("Unable to read the dll... : %d\n", GetLastError());
return false;
}
else {
status = NtClose(lFile);
for (int i = 0; i < sizeof(fileSize); i++)
{
//wprintf(L"%p : %s\n", FileReadBuffer, FileReadBuffer);
}
}
}
}
}
}
}
status = NtReadFile(
lFile,
NULL,
NULL,
NULL,
&ioStatusBlock,
FileReadBuffer,
sizeof(FileReadBuffer), // !!!!!
0, // ByteOffset
NULL);
so you read sizeof(FileReadBuffer) - 4 or 8 bytes only. i view you use my advice from here

CryptDecrypt() Failing to decrypt some blocks C++

I'm currently working on a simple encryption/decryption system in C++ using the Windows API.
I believe I've been successful at getting CryptEncrypt() to work (AES_128) for encrypting a file.
But when I Use CryptDecrypt() to decrypt the file, the first 16 bytes are corrupted and then after 4000 bytes (which is the size of the chunks I'm pulling from ReadFile() and encrypting) is another chunk of corrupted bytes and so on. If I try to decrypt a file with a total length less than 4000 bytes, the decryption works perfectly.
I'm very confused about why this is happening. There are no errors at all.
Here is a snippet of my code (I have CryptEncrypt() and CryptDecrypt() right after each other to save me exporting the key and to make the testing faster):
DWORD bytesRead;
DWORD bytesWritten;
DWORD pointer = 0;
unsigned int blockSize = 4000;
void *fileBuffer = new unsigned char[4106];
bool EOF = false;
do
{
SetFilePointer(hFileOrginal,pointer,0,0);
ReadFile(hFileOrginal,fileBuffer,blockSize,&bytesRead,NULL);
if(bytesRead<blockSize)
{
EOF=true;
}
CryptEncrypt(aesKey,NULL,EOF,0,(BYTE *)fileBuffer,&bytesRead,(blockSize+16));
CryptDecrypt(aesKey,NULL,EOF,0,(BYTE *)fileBuffer,&bytesRead);
WriteFile(hTempFile,fileBuffer,bytesRead,&bytesWritten,NULL);
pointer +=bytesRead;
}
while(!EOF);
delete[] fileBuffer;
I would really appreciate any suggestions about whats going wrong.
EDIT: On a 4704 bytes file I got the following using breakpoints.
First ReadFile bytesread 4000
First CryptEncrypt bytesRead 4000
First CryptDecrypt bytesRead 4000
Second ReadFile bytesread 704
Second CryptEncrypt bytesread 720
Second CryptDecrupt bytesread 704
Everything seems good with that yet I still get a problem.
I'm using the enhanced crypto api (With verifycontext) with a generated a single AES key with the CRYPT_EXPORTABLE property
You are not doing any error handling at all. All of the API functions you are calling have return values and error codes, none of which you are checking.
You are also not managing bytesRead correctly. CryptEncrypt() modifies the variable you pass to it, which then affects your call to CreateDecrypt(), which also modifies it, and that then affects subsequent calls to SetFilePointer(), which you should not be calling in your loop to begin with. You are not validating that you have as many bytes as you are expecting, or that bytesRead ends up back at the original value that ReadFile() returned, so you may end up skipping bytes in the source file.
Try something more like this instead:
bool ReadFromFile(HANDLE hFile, void *Buffer, DWORD BufSize, DWORD *BytesRead)
{
if (BytesRead)
*BytesRead = 0;
LPBYTE pBuffer = (LPBYTE) Buffer;
DWORD dwRead;
while (BufSize > 0)
{
if (!ReadFile(hFile, pBuffer, BufSize, &dwRead, NULL))
return false;
if (dwRead == 0)
break;
pBuffer += dwRead;
BufSize -= dwRead;
if (BytesRead)
*BytesRead += dwRead;
}
return true;
}
bool WriteToFile(HANDLE hFile, void *Buffer, DWORD BufSize)
{
LPBYTE pBuffer = (LPBYTE) Buffer;
DWORD dwWritten;
while (BufSize > 0)
{
if (!WriteFile(hFile, pBuffer, BufSize, &dwWritten, NULL))
return false;
pBuffer += dwWritten;
BufSize -= dwWritten;
}
return true;
}
DWORD bytesRead;
const UINT blockSize = 4000;
LPBYTE fileBuffer = new BYTE[blockSize+16];
bool EOF;
if (SetFilePointer(hFileOrginal, 0, NULL, FILE_BEGIN) != 0)
{
errorCode = GetLastError();
...
}
else
{
do
{
if (!ReadFromFile(hFileOrginal, fileBuffer, blockSize, &bytesRead))
{
errorCode = GetLastError();
...
break;
}
EOF = (bytesRead < blockSize);
bytesEncrypted = bytesRead;
if (!CryptEncrypt(aesKey, NULL, EOF, 0, fileBuffer, &bytesEncrypted, blockSize+16))
{
errorCode = GetLastError();
...
break;
}
bytesDecrypted = bytesEncrypted;
if (!CryptDecrypt(aesKey, NULL, EOF, 0, fileBuffer, &bytesDecrypted))
{
errorCode = GetLastError();
...
break;
}
if (!WriteToFile(hTempFile, fileBuffer, bytesDecrypted))
{
errorCode = GetLastError();
...
break;
}
if (bytesDecrypted != bytesRead)
{
...
break;
}
}
while (!EOF);
}
delete[] fileBuffer;