'C++ on Windows: Pipe to stdin not properly transferring data + ReadFile stucks when reading from pipe

I tried to create a pwntools-like program for windows. I implemented a send and recv to send data to stdin of a and to receive data from stdout. I did that using pipes.

#include <iostream>
#include <cstdio>
#include <windows.h>

void spawn();
void pwn_send(CONST CHAR chBuf[]);
CHAR* pwn_recv(SIZE_T sz);
CHAR* pwn_recv();

HANDLE stdout_write = NULL;
HANDLE stdout_read = NULL;
HANDLE stdin_write = NULL;
HANDLE stdin_read = NULL;

int main() {
    SECURITY_ATTRIBUTES saAttr;

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    if(!CreatePipe(&stdout_read, &stdout_write, &saAttr, 0)) return -1;
    if(!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) return -1;
    if(!CreatePipe(&stdin_read, &stdin_write, &saAttr, 0)) return -1;
    if(!SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0)) return -1;

    spawn();

    CHAR chBuf[] = "mkdir C:\\Users\\comma\\Desktop\\x\r\n";
    pwn_send(chBuf);

    std::cout << pwn_recv(20) << std::endl;

    return 0;
}

void spawn() {
    TCHAR cmd[] = TEXT("cmd.exe");
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.hStdError = stdout_write;
    si.hStdOutput = stdout_write;
    si.hStdInput = stdin_read;
    si.dwFlags |= STARTF_USESTDHANDLES;
    ZeroMemory(&pi, sizeof(pi));

    if(!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) exit(-1);
    return;
}

void pwn_send(CONST CHAR chBuf[]) {
    DWORD dwRead = 0, dwWritten = 0;
    BOOL bSuccess = FALSE;

    while(1) {
        bSuccess = WriteFile(stdin_write, chBuf, strlen(chBuf), &dwWritten, NULL);
        if (bSuccess) break;
    }

    CloseHandle(stdin_write);
    return;
}

CHAR* pwn_recv(SIZE_T sz) {
    HANDLE hHeap = GetProcessHeap();
    DWORD dwRead = 0, dwWritten = 0;
    BOOL bSuccess = FALSE;

    CHAR* chBuf = (CHAR*)HeapAlloc(hHeap, 0, sz+1);

    while (1) {
        std::cout << "XXX" << std::endl;
        bSuccess = ReadFile(stdout_read, chBuf, sz, &dwRead, NULL);
        std::cout << "YYY" << std::endl;
        if (bSuccess) break;
    }

    return chBuf;
}

CHAR* pwn_recv() {
    HANDLE hHeap = GetProcessHeap();
    DWORD dwRead = 0, dwWritten = 0;
    BOOL bSuccess = FALSE;

    CHAR* chBuf = (CHAR*)HeapAlloc(hHeap, 0, 0x1000);

    while (1) {
        bSuccess = ReadFile(stdout_read, chBuf, 0x1000, &dwWritten, NULL);
        if (bSuccess) break;
    }

    return chBuf;
}

So the first issue here is that the program I started with spawn(cmd.exe) doesn't properly receive the command I send to stdin. No folder is created anywhere. CreateProcess succeeds. Receiving output doesn't work either, because ReadFile seems to stuck. XXX is displayed in the console, butYYY never. Any ideas?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source