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?
Related
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
I'm working on a project which needed to create a child process and re-directed its input and output to the parent process.
I'm following this example on MSDN (link). Currently it works with debug build, but not release build. I can't figure it out why. Please help me
The coding of the child process as follow (very similar to the example):
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <string>
#include <Iepmapi.h>
#include <Wininet.h>
#include <vector>
#define BUFSIZE 4096
using namespace std;
vector<wstring> subStringByString(wstring input, wstring delimiter)
{
int pos = input.find(delimiter);
vector<wstring> arr;
while (pos != wstring::npos)
{
wstring token = input.substr(0, pos);
arr.push_back(token);
input = input.substr(pos + delimiter.size(), input.size());
pos = input.find(delimiter);
}
arr.push_back(input);
return arr;
}
int main(void)
{
WCHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL bSuccess;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (
(hStdout == INVALID_HANDLE_VALUE) ||
(hStdin == INVALID_HANDLE_VALUE)
)
ExitProcess(1);
// Send something to this process's stdout using printf.
printf("\n ** This is a message from the child process. ** \n");
// This simple algorithm uses the existence of the pipes to control execution.
// It relies on the pipe buffers to ensure that no data is lost.
// Larger applications would use more advanced process control.
int rc = 0;
for (;;)
{
// Read from standard input and stop on error or no data.
bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
wstring input = wstring(chBuf);
wstring delimiter = L" ";
vector<wstring> arr = subStringByString(input, delimiter);
int rc = 0;
if (!bSuccess || dwRead == 0)
break;
if (IESetProtectedModeCookie(arr[0].c_str(), arr[1].c_str(), arr[2].c_str(), INTERNET_COOKIE_THIRD_PARTY) != S_OK)
{
DWORD error = GetLastError();
rc = -27;
}
// Write to standard output and stop on error.
if (rc == 0 )
bSuccess = WriteFile(hStdout, L"0", dwRead, &dwWritten, NULL);
else
bSuccess = WriteFile(hStdout, L"-27", dwRead, &dwWritten, NULL);
if (!bSuccess)
break;
}
return 0;
}
Thanks,
Vinh
Parent process code:
std::wstring invoke(const std::wstring input)
{
if (!CreateChildProcess())
return L"error";
DWORD dwRead, dwWritten;
WCHAR chBuf[BUFSIZE] ;
const WCHAR* temp = input.c_str();
wcscpy(chBuf, temp);
BOOL bSuccess = FALSE;
for (;;)
{
bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
if (!bSuccess) break;
}
CloseHandle(g_hChildStd_IN_Wr);
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
for (;;)
{
bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if (!bSuccess) break;
bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);
if (!bSuccess) break;
}
//TerminateProcess(_processId, 0);
return std::wstring(&chBuf[0]);
}
bool CreateChildProcess(void)
{
SECURITY_ATTRIBUTES saAttr;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
return false;
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
{
cleanUpHandle();
return false;
}
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
{
cleanUpHandle();
return false;
}
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
{
cleanUpHandle();
return false;
}
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
bSuccess = OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE |
TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY |
TOKEN_ASSIGN_PRIMARY,
&hToken);
if (!bSuccess) {
return 0;
}
hNewToken = CreateLowLevelToken(hToken);
wa_wstring deploymentPath;
if (WAAPI_FAILED(ProcessUtils::getDeploymentPath(deploymentPath)))
{
return false;
}
wa_wstring path = deploymentPath + wa_wstring(PROCESS_PATH);
LPTSTR szCmdline = wstring_to_LPTSTR(path);
if (_processId != 0)
{
TerminateProcess(_processId, 0);
}
TCHAR szCmdline2[] = PROCESS_PATH;
bSuccess = CreateProcessAsUser(hNewToken, NULL, szCmdline2, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &siStartInfo, &piProcInfo);
DWORD error = GetLastError();
if (!bSuccess)
{
cleanUpHandle();
return false;
}
else {
_processId = piProcInfo.dwProcessId;
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
return true;
}
I found the problem.
In "debug build, the value of dwRead, dwWritten are trash value, however, the value of those in relase build are 0. Which cause the parent hang.
To fix this :
DWORD dwRead = -1, dwWritten = -1;
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;
In the following code the call to SetupDiEnumDeviceInfo() causes the subsequent CreateFile to return ERROR_SHARING_VIOLATION instead of opening the file. I was able to pinpoint the line by commenting out the other pieces of code until I hit one line that would cause the CreateFile to fail.
String SerialATDT::getComPortId()
{
#if 1
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
String comPort = "";
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_MODEM,
0, // Enumerator
0,
DIGCF_PRESENT );
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return "";
}
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
int offset = 0;
while ( SetupDiEnumDeviceInfo(hDevInfo, offset++, &DeviceInfoData) )
{
DWORD DataT;
#if 1
//
// Call function with null to begin with,
// then use the returned buffer size (doubled)
// to Alloc the buffer. Keep calling until
// success or an unknown failure.
//
// Double the returned buffersize to correct
// for underlying legacy CM functions that
// return an incorrect buffersize value on
// DBCS/MBCS systems.
//
while (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_FRIENDLYNAME,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
{
// Change the buffer size.
if (buffer) LocalFree(buffer);
// Double the size to avoid problems on
// W2k MBCS systems per KB 888609.
buffer = (LPTSTR)LocalAlloc(LPTR,buffersize * 2);
}
else
{
// Insert error handling here.
break;
}
}
// Look for identifying info in the name
if ( mComPortIdentifier.size() > 0 ) {
const char *temp = strstr(buffer, mComPortIdentifier.c_str());
if ( temp == 0 ) {
continue;
}
}
// Now find out the port number
DWORD nSize=0 ;
TCHAR buf[MAX_PATH];
if ( SetupDiGetDeviceInstanceId(hDevInfo, &DeviceInfoData, buf, MAX_PATH, &nSize) )
{
HKEY devKey = SetupDiOpenDevRegKey(hDevInfo, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
DWORD size = 0;
DWORD type;
RegQueryValueEx(devKey, TEXT("PortName"), NULL, NULL, NULL, & size);
BYTE* buff = new BYTE[size];
String result;
if( RegQueryValueEx(devKey, TEXT("PortName"), NULL, &type, buff, & size) == ERROR_SUCCESS ) {
comPort = (char*)buff;
if ( comPort.size() > 0 ) {
RegCloseKey(devKey);
break;
}
}
RegCloseKey(devKey);
delete [] buff;
}
#else
comPort = "COM44";
#endif
}
// Cleanup
SetupDiDestroyDeviceInfoList (hDevInfo);
if (buffer) {
LocalFree(buffer);
}
if ( GetLastError()!=NO_ERROR &&
GetLastError()!=ERROR_NO_MORE_ITEMS &&
GetLastError() != ERROR_INVALID_HANDLE )
{
TRACE_L("ATDT error after free %ld", GetLastError() );
// Insert error handling here.
return "";
}
return comPort;
#else
return "COM44";
#endif
}
bool SerialATDT::getComPort(HANDLE *hFile)
{
String comPort = getComPortId();
*hFile = INVALID_HANDLE_VALUE;
if ( comPort.size() > 0 ) {
String comPortStr;
comPortStr.Format("\\\\.\\%s", comPort.c_str());
*hFile = ::CreateFile( comPortStr.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( *hFile == INVALID_HANDLE_VALUE ) {
TRACE_L("AT file open error %ld", GetLastError());
}
}
return *hFile != INVALID_HANDLE_VALUE;
}
I have been looking but have not found a reason why the DeviceInfoData needs to be cleared (nor have I found a method to do it). Has anybody run into this before?
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)