#include <stdio.h>
#include <windows.h>
#pragma warning(disable : 4996)
int main(int argc, wchar_t** argv)
{
DWORD bytes_read;
WCHAR* buffer[4096];
LPWSTR str;
STARTUPINFO start_info = { 0 };
PROCESS_INFORMATION process_info = { 0 };
ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 4096, &bytes_read, NULL);
str = malloc(bytes_read);
memcpy(str, buffer, bytes_read);
// debug - stdout + file
wprintf(L"\nTrying to run -> \"%LS\"", str);
FILE *f = fopen("file.txt", "w");
fwprintf(f, L"%LS", str);
fclose(f);
BOOL result = CreateProcessW(
NULL,
str,
NULL,
NULL,
TRUE,
CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&start_info,
&process_info
);
if (!result) {
DWORD err = GetLastError();
WCHAR *errstr;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&errstr, 0, NULL
);
wprintf(L"\nError -> %ls", errstr);
return 1;
}
return 0;
}
Running it yields following
C:\Users\Admin\source\repos\ConsoleApplication1\Debug
λ php -r "echo \"C:\\Windows\\System32\\PING.EXE\0\";"|ConsoleApplication1.exe
Trying to run -> "C:\Windows\System32\PING.EXE"
Error -> The system cannot find the file specified.
So it seems it uses correct input. Also in file.txt there doesn't seem to be anything suspicious when viewed in hex editor
When hardcoding str like following instead of using stdin
wchar_t cmd[] = L"C:\\Windows\\System32\\PING.EXE";
It works.
What do I need to do in order to make CreateProcessW work with stdin input?
WCHAR* buffer[4096];
This will create an array of character strings. You just want one wide char buffer.
Use the L"%s"
format specifier for testing:
wprintf(L"%s\n", buffer)
If possible, pass the Unicode text as command line, example
php -r "echo \"Test...\0\";"|app.exe Unicode
The Unicode text can contain UTF16 character sets.
int main(void)
{
wprintf(L"GetCommandLineW %s\n", GetCommandLineW());
DWORD bytes_read = 0;
char buffer[4096] = { 0 };
ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer,
sizeof(buffer), &bytes_read, NULL);
int codepage = CP_UTF8;//or CP_ACP
int wlen = MultiByteToWideChar(codepage, 0, buffer, -1, 0, 0);
wchar_t *wstr = malloc(wlen * 2);
MultiByteToWideChar(codepage, 0, buffer, -1, wstr, wlen);
wprintf(L"pipe %s\n", wstr);
free(wstr);
return 0;
}