18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/process_thread_interception.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/crosscall_client.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/ipc_tags.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_params.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_target.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_nt_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sharedmem_ipc_client.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/target_services.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_INTERCEPT NtExports g_nt;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Hooks NtOpenThread and proxy the call to the broker if it's trying to
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open a thread in the same process.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenThread(NtOpenThreadFunction orig_OpenThread,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PHANDLE thread, ACCESS_MASK desired_access,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   POBJECT_ATTRIBUTES object_attributes,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PCLIENT_ID client_id) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenThread(thread, desired_access, object_attributes,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    client_id);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!client_id)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 thread_id = 0;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool should_break = false;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We support only the calls for the current process
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (NULL != client_id->UniqueProcess)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        should_break = true;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Object attributes should be NULL or empty.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!should_break && NULL != object_attributes) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (0 != object_attributes->Attributes ||
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->ObjectName ||
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->RootDirectory ||
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->SecurityDescriptor ||
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->SecurityQualityOfService) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          should_break = true;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_id = static_cast<uint32>(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      reinterpret_cast<ULONG_PTR>(client_id->UniqueThread));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (should_break)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(thread, sizeof(HANDLE), WRITE))
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTOPENTHREAD_TAG, desired_access,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                thread_id, &answer);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The nt_status here is most likely STATUS_INVALID_CID because
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // in the broker we set the process id in the CID (client ID) param
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be the current process. If you try to open a thread from another
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // process you will get this INVALID_CID error. On the other hand, if you
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // try to open a thread in your own process, it should return success.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't want to return STATUS_INVALID_CID here, so we return the
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // return of the original open thread status, which is most likely
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // STATUS_ACCESS_DENIED.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write the output parameters.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *thread = answer.handle;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return answer.nt_status;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Hooks NtOpenProcess and proxy the call to the broker if it's trying to
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open the current process.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenProcess(NtOpenProcessFunction orig_OpenProcess,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PHANDLE process, ACCESS_MASK desired_access,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   POBJECT_ATTRIBUTES object_attributes,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PCLIENT_ID client_id) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenProcess(process, desired_access, object_attributes,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     client_id);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!client_id)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 process_id = 0;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool should_break = false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Object attributes should be NULL or empty.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!should_break && NULL != object_attributes) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (0 != object_attributes->Attributes ||
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->ObjectName ||
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->RootDirectory ||
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->SecurityDescriptor ||
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL != object_attributes->SecurityQualityOfService) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          should_break = true;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process_id = static_cast<uint32>(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      reinterpret_cast<ULONG_PTR>(client_id->UniqueProcess));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (should_break)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(process, sizeof(HANDLE), WRITE))
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESS_TAG, desired_access,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                process_id, &answer);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return answer.nt_status;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write the output parameters.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *process = answer.handle;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return answer.nt_status;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenProcessToken(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NtOpenProcessTokenFunction orig_OpenProcessToken, HANDLE process,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCESS_MASK desired_access, PHANDLE token) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenProcessToken(process, desired_access, token);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CURRENT_PROCESS != process)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(token, sizeof(HANDLE), WRITE))
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESSTOKEN_TAG, process,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                desired_access, &answer);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return answer.nt_status;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write the output parameters.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *token = answer.handle;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return answer.nt_status;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenProcessTokenEx(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NtOpenProcessTokenExFunction orig_OpenProcessTokenEx, HANDLE process,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCESS_MASK desired_access, ULONG handle_attributes, PHANDLE token) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenProcessTokenEx(process, desired_access,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            handle_attributes, token);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CURRENT_PROCESS != process)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(token, sizeof(HANDLE), WRITE))
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESSTOKENEX_TAG, process,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                desired_access, handle_attributes, &answer);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return answer.nt_status;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write the output parameters.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *token = answer.handle;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return answer.nt_status;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPCWSTR application_name, LPWSTR command_line,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSECURITY_ATTRIBUTES process_attributes,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSECURITY_ATTRIBUTES thread_attributes,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 BOOL inherit_handles, DWORD flags,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPVOID environment, LPCWSTR current_directory,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSTARTUPINFOW startup_info,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPPROCESS_INFORMATION process_information) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (orig_CreateProcessW(application_name, command_line, process_attributes,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          thread_attributes, inherit_handles, flags,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          environment, current_directory, startup_info,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          process_information)) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't trust that the IPC can work this early.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DWORD original_error = ::GetLastError();
2828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        WRITE))
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* cur_dir = NULL;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t current_directory[MAX_PATH];
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD result = ::GetCurrentDirectory(MAX_PATH, current_directory);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 != result && result < MAX_PATH)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_dir = current_directory;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InOutCountedBuffer proc_info(process_information,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sizeof(PROCESS_INFORMATION));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_CREATEPROCESSW_TAG, application_name,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                command_line, cur_dir, proc_info, &answer);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SetLastError(answer.win32_result);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_SUCCESS != answer.win32_result)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::SetLastError(original_error);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FALSE;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPCSTR application_name, LPSTR command_line,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSECURITY_ATTRIBUTES process_attributes,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSECURITY_ATTRIBUTES thread_attributes,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 BOOL inherit_handles, DWORD flags,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPVOID environment, LPCSTR current_directory,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPSTARTUPINFOA startup_info,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPPROCESS_INFORMATION process_information) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (orig_CreateProcessA(application_name, command_line, process_attributes,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          thread_attributes, inherit_handles, flags,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          environment, current_directory, startup_info,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          process_information)) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't trust that the IPC can work this early.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DWORD original_error = ::GetLastError();
3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        WRITE))
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Convert the input params to unicode.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING *cmd_unicode = NULL;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING *app_unicode = NULL;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command_line) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_unicode = AnsiToUnicode(command_line);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!cmd_unicode)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (application_name) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      app_unicode = AnsiToUnicode(application_name);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!app_unicode) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        operator delete(cmd_unicode, NT_ALLOC);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* cmd_line = cmd_unicode ? cmd_unicode->Buffer : NULL;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* app_name = app_unicode ? app_unicode->Buffer : NULL;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* cur_dir = NULL;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t current_directory[MAX_PATH];
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD result = ::GetCurrentDirectory(MAX_PATH, current_directory);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 != result && result < MAX_PATH)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_dir = current_directory;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InOutCountedBuffer proc_info(process_information,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sizeof(PROCESS_INFORMATION));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_CREATEPROCESSW_TAG, app_name,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                cmd_line, cur_dir, proc_info, &answer);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(cmd_unicode, NT_ALLOC);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(app_unicode, NT_ALLOC);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SetLastError(answer.win32_result);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_SUCCESS != answer.win32_result)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FALSE;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::SetLastError(original_error);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FALSE;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
404