Wizard
Wizard

Reputation: 1663

Passing an anonymous PIPE HANDLE to Child Process

I am wanting to pass an anonymous Pipe HANDLE to a Child Process. This answer seems to explain it well for C++, however I am wanting to do this in C.

Do I convert the handle into an integer? Or do I pass the memory address of the HANDLE to the child process, and then make another HANDLE pointing to that?

For example:

Parent:

    BOOL bCreatePipe, bReadFile;
    HANDLE hRead = NULL;
    HANDLE hWrite = NULL;
    SECURITY_ATTRIBUTES lpPipeAttributes;
    lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
    lpPipeAttributes.lpSecurityDescriptor = NULL;
    lpPipeAttributes.bInheritHandle = TRUE;

    // Create pipe file descriptors for parent and child
    bCreatePipe = CreatePipe(&hRead, &hWrite, &lpPipeAttributes, (DWORD)BUFFER_SIZE);
    if (bCreatePipe == FALSE) {
        printf("[-]Error creating IPC pipe : %d", GetLastError());
        exit(-1);
    }

    // Create command line arguments for child process
    snprintf(child_cmd, CMD_LINE_SIZE, "%d", &hWrite);

    // Create child process to handle request
    if ( !CreateProcess(
         "C:\\Users\\Child.exe",        // No module name (use command line)
         child_cmd,      // Command line
         NULL,           // Process handle not inheritable
         NULL,           // Thread handle not inheritable
         TRUE,           // Set handle inheritance to TRUE (for pipe)
         0,              // No creation flags
         NULL,           // Use parent's environment block
         NULL,           // Use parent's starting directory
         &si,            // Pointer to STARTUPINFO structure
         &pi)            // Pointer to PROCESS_INFORMATION structure
         )
    {
        printf("[-]CreateProcess failed : %d\n", GetLastError());
        exit(-1);
    }

Child:

// Set variables to arguments passed by parent 
HANDLE hWrite = atoi(argv[0]);

Upvotes: 1

Views: 2057

Answers (1)

RbMm
RbMm

Reputation: 33804

yes, this is ok pass HANDLE by value. in practice currently your code will be work ok. however need remember that HANDLE is 64-bit size on 64-bit system - so not fit in int which is 32-bit size (now user mode handle values in practice fit to 32bit). so need use say %I64x format to encode handle value and _atoi64 or _wcstoi64 to decode.

for example in parent:

WCHAR child_cmd[32];
swprintf(child_cmd, L"<%I64x>", (ULONG64)(ULONG_PTR)hWrite);

and in child:

HANDLE hWrite = 0;
if (PWSTR sz = wcschr(GetCommandLineW(), '<'))
{
    hWrite = (HANDLE)(ULONG_PTR)_wcstoi64(sz + 1, &sz, 16);
    if (*sz != '>')
    {
        hWrite = 0;
    }
}

as separate note - use CreatePipe not the best choice - this api very bad design, say one handle only for write, another only for read, can not select asynchronous I/O, can not make one handle inherit and another not (as need in this case) - better use CreateNamedPipeW + CreateFileW for create pipe pair. or this way if you want no name on pipe (work from win7)

Upvotes: 1

Related Questions