Changeset 3179


Ignore:
Timestamp:
Mar 22, 2018, 8:50:04 PM (7 years ago)
Author:
bird
Message:

kmk_redirect,winchildren: WOW64 standard handle injection fixes.

Location:
trunk/src
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/redirect.c

    r3173 r3179  
    4040# include <process.h>
    4141#endif
    42 #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
     42#ifdef KBUILD_OS_WINDOWS
    4343# include <Windows.h>
    44 # include <Winternl.h>
    4544#endif
    4645#if defined(_MSC_VER)
     
    6766#include "err.h"
    6867#include "kbuild_version.h"
     68#ifdef KBUILD_OS_WINDOWS
     69# include "nt/nt_child_inject_standard_handles.h"
     70#endif
    6971#if defined(__gnu_hurd__) && !defined(kmk_builtin_redirect) /* need constant */
    7072# undef GET_PATH_MAX
     
    791793}
    792794
     795
    793796/**
    794797 * Alternative approach on windows that use CreateProcess and doesn't require
     
    805808 * @param   phProcess           Where to return process handle.
    806809 */
    807 static kRedirectCreateProcessWindows(const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars,
    808                                      const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, HANDLE *phProcess)
     810static int kRedirectCreateProcessWindows(const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars,
     811                                         const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, HANDLE *phProcess)
    809812{
    810     static NTSTATUS (NTAPI *s_pfnNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG) = NULL;
    811813    size_t cbArgs;
    812814    char  *pszCmdLine;
     
    816818    int    i;
    817819    int    rc;
    818 
    819     /*
    820      * Determin host bitness and APIs while we can still easily return.
    821      */
    822 #if K_ARCH_BITS == 32
    823     BOOL   f64BitHost = TRUE;
    824     if (!IsWow64Process(GetCurrentProcess(), &f64BitHost))
    825         return errx(9, "IsWow64Process failed: %u", GetLastError());
    826 #elif K_ARCH_BITS == 64
    827     BOOL const f64BitHost = TRUE;
    828 #else
    829 # error "K_ARCH_BITS is bad/missing"
    830 #endif
    831     if (cOrders > 0 && !s_pfnNtQueryInformationProcess)
    832     {
    833         *(FARPROC *)&s_pfnNtQueryInformationProcess = GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQueryInformationProcess");
    834         if (!s_pfnNtQueryInformationProcess)
    835             return errx(9, "NtQueryInformationProcess not found!");
    836     }
    837820
    838821    /*
     
    962945                                   FALSE /*fInheritHandles*/, CREATE_SUSPENDED, pszzEnv, pszCwd, &StartupInfo, &ProcInfo))
    963946                {
    964                     /*
    965                      * Figure out where we need to write the handles.
    966                      */
    967                     ULONG                     cbActual1 = 0;
    968                     PROCESS_BASIC_INFORMATION BasicInfo = { 0, 0, };
    969                     NTSTATUS rcNt = s_pfnNtQueryInformationProcess(ProcInfo.hProcess, ProcessBasicInformation,
    970                                                                    &BasicInfo, sizeof(BasicInfo), &cbActual1);
    971                     if (NT_SUCCESS(rcNt))
    972                     {
    973                         BOOL const   f32BitPeb  = !f64BitHost;
    974                         ULONG  const cbChildPtr = f32BitPeb ? 4 : 8;
    975                         PVOID        pvSrcInPeb = (char *)BasicInfo.PebBaseAddress + (f32BitPeb ? 0x10 : 0x20);
    976                         char *       pbDst      = 0;
    977                         SIZE_T       cbActual2  = 0;
    978                         if (ReadProcessMemory(ProcInfo.hProcess, pvSrcInPeb, &pbDst, cbChildPtr, &cbActual2))
    979                         {
    980                             union
    981                             {
    982                                 KU32 au32[3];
    983                                 KU64 au64[3];
    984                             } uBuf;
    985                             memset(&uBuf, 0, sizeof(uBuf));
    986                             pbDst += f32BitPeb ? 0x18 : 0x20;
    987                             if (   (afReplace[0] && afReplace[1] && afReplace[2])
    988                                 || ReadProcessMemory(ProcInfo.hProcess, pbDst, &uBuf, cbChildPtr * 3, &cbActual2))
    989                             {
    990                                 for (i = 0; i < 3; i++)
    991                                     if (afReplace[i])
    992                                     {
    993                                         HANDLE hInChild = INVALID_HANDLE_VALUE;
    994                                         if (   ahChild[i] == NULL /* just closed*/
    995                                             || DuplicateHandle(GetCurrentProcess(), ahChild[i], ProcInfo.hProcess, &hInChild,
    996                                                                0, TRUE /*fInheriable*/, DUPLICATE_SAME_ACCESS))
    997                                         {
    998                                             if (f32BitPeb)
    999                                                 uBuf.au32[i] = (KU32)(uintptr_t)hInChild;
    1000                                             else
    1001                                                 uBuf.au64[i] = (uintptr_t)hInChild;
    1002                                         }
    1003                                         else
    1004                                             rc = errx(10, "Error duplicating %p into the child: %u", ahChild[i], GetLastError());
    1005                                     }
    1006                                 if (    rc == 0
    1007                                     && !WriteProcessMemory(ProcInfo.hProcess, pbDst, &uBuf, cbChildPtr * 3, &cbActual2))
    1008                                     rc = errx(10, "Error writing standard handles at %p LB %u in the child: %u",
    1009                                               pbDst, cbChildPtr * 3, GetLastError());
    1010                             }
    1011                             else
    1012                                 rc = errx(10, "Error reading %p LB %u from the child: %u",
    1013                                           pbDst, cbChildPtr * 3, GetLastError());
    1014                         }
    1015                         else
    1016                             rc = errx(10, "Error reading %p LB %u from the child: %u", pvSrcInPeb, cbChildPtr);
    1017                     }
    1018                     else
    1019                         rc = errx(10, "NtQueryInformationProcess failed: %#x", rcNt);
    1020 
    1021                     /* Resume the bugger... */
    1022                     if (   rc == 0
    1023                         && !ResumeThread(ProcInfo.hThread))
     947                    /* Inject the handles and try make it start executing. */
     948                    char szErrMsg[128];
     949                    rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg));
     950                    if (rc)
     951                        rc = errx(10, "%s", szErrMsg);
     952                    else if (!ResumeThread(ProcInfo.hThread))
    1024953                        rc = errx(10, "ResumeThread failed: %u", GetLastError());
    1025954
    1026                     /* .. or kill it. */
     955                    /* Kill it if any of that fails. */
    1027956                    if (rc != 0)
    1028957                        TerminateProcess(ProcInfo.hProcess, rc);
  • trunk/src/kmk/w32/winchildren.c

    r3173 r3179  
    7979#include <assert.h>
    8080#include <process.h>
     81#include <intrin.h>
     82
     83#include "nt/nt_child_inject_standard_handles.h"
    8184
    8285
     
    328331
    329332
     333#if K_ARCH_BITS == 32 && !defined(_InterlockedCompareExchangePointer)
     334/** _InterlockedCompareExchangePointer is missing? (VS2010) */
     335K_INLINE void *_InterlockedCompareExchangePointer(void * volatile *ppvDst, void *pvNew, void *pvOld)
     336{
     337    return (void *)_InterlockedCompareExchange((long volatile *)ppvDst, (intptr_t)pvNew, (intptr_t)pvOld);
     338}
     339#endif
     340
    330341
    331342/**
     
    698709        if (fHaveHandles)
    699710        {
    700             /*
    701              * Get the PEB address and figure out the child process bit count.
    702              */
    703             ULONG                     cbActual1 = 0;
    704             PROCESS_BASIC_INFORMATION BasicInfo = { 0, 0, };
    705             NTSTATUS rcNt = g_pfnNtQueryInformationProcess(ProcInfo.hProcess, ProcessBasicInformation,
    706                                                            &BasicInfo, sizeof(BasicInfo), &cbActual1);
    707             if (NT_SUCCESS(rcNt))
    708             {
    709                 /*
    710                  * Read the user process parameter pointer from the PEB.
    711                  *
    712                  * Note! Seems WOW64 processes starts out with a 64-bit PEB and
    713                  *       process parameter block.
    714                  */
    715                 BOOL const   f32BitPeb  = !g_f64BitHost;
    716                 ULONG  const cbChildPtr = f32BitPeb ? 4 : 8;
    717                 PVOID        pvSrcInPeb = (char *)BasicInfo.PebBaseAddress + (f32BitPeb ? 0x10 : 0x20);
    718                 char *       pbDst      = 0;
    719                 SIZE_T       cbActual2  = 0;
    720                 if (ReadProcessMemory(ProcInfo.hProcess, pvSrcInPeb, &pbDst, cbChildPtr, &cbActual2))
    721                 {
    722                     /*
    723                      * Duplicate the handles into the child.
    724                      */
    725                     union
    726                     {
    727                         ULONGLONG   au64Bit[2];
    728                         ULONG       au32Bit[2];
    729                     } WriteBuf;
    730                     ULONG  idx = 0;
    731                     HANDLE hChildStdOut = INVALID_HANDLE_VALUE;
    732                     HANDLE hChildStdErr = INVALID_HANDLE_VALUE;
    733 
    734                     pbDst += (f32BitPeb ? 0x1c : 0x28);
    735                     if (pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE)
    736                     {
    737                         if (DuplicateHandle(GetCurrentProcess(), pChild->u.Process.hStdOut, ProcInfo.hProcess,
    738                                             &hChildStdOut, 0, TRUE /*fInheritable*/, DUPLICATE_SAME_ACCESS))
    739                         {
    740                             if (f32BitPeb)
    741                                 WriteBuf.au32Bit[idx++] = (DWORD)(uintptr_t)hChildStdOut;
    742                             else
    743                                 WriteBuf.au64Bit[idx++] = (uintptr_t)hChildStdOut;
    744                         }
    745                         else
    746                         {
    747                             dwErr = GetLastError();
    748                             fprintf(stderr, "Failed to duplicate %p (stdout) into the child: %u\n",
    749                                     pChild->u.Process.hStdOut, dwErr);
    750                         }
    751                     }
    752                     else
    753                         pbDst += cbChildPtr;
    754 
    755                     if (pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE)
    756                     {
    757                         if (DuplicateHandle(GetCurrentProcess(), pChild->u.Process.hStdErr, ProcInfo.hProcess,
    758                                             &hChildStdErr, 0, TRUE /*fInheritable*/, DUPLICATE_SAME_ACCESS))
    759                         {
    760                             if (f32BitPeb)
    761                                 WriteBuf.au32Bit[idx++] = (DWORD)(uintptr_t)hChildStdOut;
    762                             else
    763                                 WriteBuf.au64Bit[idx++] = (uintptr_t)hChildStdOut;
    764                         }
    765                         else
    766                         {
    767                             dwErr = GetLastError();
    768                             fprintf(stderr, "Failed to duplicate %p (stderr) into the child: %u\n",
    769                                     pChild->u.Process.hStdOut, dwErr);
    770                         }
    771                     }
    772 
    773                     /*
    774                      * Finally write the handle values into the child.
    775                      */
    776                     if (   idx > 0
    777                         && !WriteProcessMemory(ProcInfo.hProcess, pbDst, &WriteBuf, idx * cbChildPtr, &cbActual2))
    778                     {
    779                         dwErr = GetLastError();
    780                         fprintf(stderr, "Failed to write %p LB %u into child: %u\n", pbDst, idx * cbChildPtr, dwErr);
    781                     }
    782                 }
    783                 else
    784                 {
    785                     dwErr = GetLastError();
    786                     fprintf(stderr, "Failed to read %p LB %u from the child: %u\n", pvSrcInPeb, cbChildPtr, dwErr);
    787                 }
    788             }
    789             else
    790             {
    791                 fprintf(stderr, "NtQueryInformationProcess failed on child: %#x\n", rcNt);
    792                 dwErr = (DWORD)rcNt;
    793             }
     711            char    szErrMsg[128];
     712            BOOL    afReplace[3] =
     713            { FALSE, pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE, pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE };
     714            HANDLE  ahChild[3] =
     715            { NULL,  pChild->u.Process.hStdOut,                         pChild->u.Process.hStdErr  };
     716
     717            dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg));
     718            if (dwErr != 0)
     719                fprintf(stderr, "%s\n", szErrMsg);
    794720        }
    795721
  • trunk/src/lib/Makefile.kmk

    r3114 r3179  
    5555       nt/ntunlink.c \
    5656       nt/ntutimes.c \
     57       nt/nt_child_inject_standard_handles.c \
    5758       nt/fts-nt.c \
    5859       nt/kFsCache.c \
Note: See TracChangeset for help on using the changeset viewer.