15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2010 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 <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tchar.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/sandbox.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/main_ui_window.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_factory.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prototype allowed for functions to be called in the POC 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void(__cdecl *lpfnInit)(HANDLE); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseCommandLine(wchar_t * command_line, 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string * dll_name, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string * entry_point, 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 * log_file) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(dll_name); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(entry_point); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(log_file); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dll_name || !entry_point || !log_file) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPWSTR *arg_list; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int arg_count; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We expect the command line to contain: EntryPointName "DLLPath" "LogPath" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Double quotes are required, even if long path name not used 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: LogPath can be blank, but still requires the double quotes 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arg_list = CommandLineToArgvW(command_line, &arg_count); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == arg_list || arg_count < 4) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 entry_point_wide = arg_list[1]; 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 dll_name_wide = arg_list[2]; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *entry_point = std::string(entry_point_wide.begin(), entry_point_wide.end()); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dll_name = std::string(dll_name_wide.begin(), dll_name_wide.end()); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *log_file = arg_list[3]; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free memory allocated for CommandLineToArgvW arguments. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(arg_list); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int APIENTRY _tWinMain(HINSTANCE instance, HINSTANCE, wchar_t* command_line, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int show_command) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNREFERENCED_PARAMETER(command_line); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::BrokerServices* broker_service = 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::SandboxFactory::GetBrokerServices(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::ResultCode result; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This application starts as the broker; an application with a UI that 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // spawns an instance of itself (called a 'target') inside the sandbox. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Before spawning a hidden instance of itself, the application will have 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // asked the user which DLL the spawned instance should load and passes 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that as command line argument to the spawned instance. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We check here to see if we can retrieve a pointer to the BrokerServices, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is not possible if we are running inside the sandbox under a 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // restricted token so it also tells us which mode we are in. If we can 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retrieve the pointer, then we are the broker, otherwise we are the target 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the broker launched. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != broker_service) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Yes, we are the broker so we need to initialize and show the UI 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 != (result = broker_service->Init())) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(NULL, L"Failed to initialize the BrokerServices object", 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Error during initialization", MB_ICONERROR); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t exe_name[MAX_PATH]; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == GetModuleFileName(NULL, exe_name, MAX_PATH - 1)) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(NULL, L"Failed to get name of current EXE", 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Error during initialization", MB_ICONERROR); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The CreateMainWindowAndLoop() call will not return until the user closes 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the application window (or selects File\Exit). 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MainUIWindow window; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.CreateMainWindowAndLoop(instance, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exe_name, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_command, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) broker_service); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cannot exit until we have cleaned up after all the targets we have 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) broker_service->WaitForAllTargets(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is an instance that has been spawned inside the sandbox by the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // broker, so we need to parse the command line to figure out which DLL to 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load and what entry point to call 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::TargetServices* target_service 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = sandbox::SandboxFactory::GetTargetServices(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == target_service) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(finnur): write the failure to the log file 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We cannot display messageboxes inside the sandbox unless access to 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the desktop handle has been granted to us, and we don't have a 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // console window to write to. Therefore we need to have the broker 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // grant us access to a handle to a logfile and write the error that 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // occurred into the log before continuing 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Debugging the spawned application can be tricky, because DebugBreak() 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and _asm int 3 cause the app to terminate (due to a flag in the job 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object), MessageBoxes() will not be displayed unless we have been granted 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that privilege and the target finishes its business so quickly we cannot 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attach to it quickly enough. Therefore, you can uncomment the 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // following line and attach (w. msdev or windbg) as the target is sleeping 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleep(10000); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sandbox::SBOX_ALL_OK != (result = target_service->Init())) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(finnur): write the initialization error to the log file 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -2; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the command line to find out what we need to call 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string dll_name, entry_point; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 log_file; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParseCommandLine(GetCommandLineW(), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dll_name, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &entry_point, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &log_file)) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(finnur): write the failure to the log file 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -3; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the pipe to transfert the log output 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE pipe = ::CreateFile(log_file.c_str(), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GENERIC_WRITE, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // Default security attributes. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CREATE_ALWAYS, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_ATTRIBUTE_NORMAL, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); // No template 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (INVALID_HANDLE_VALUE == pipe) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -4; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We now know what we should load, so load it 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE dll_module = ::LoadLibraryA(dll_name.c_str()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dll_module == NULL) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(finnur): write the failure to the log file 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -5; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialization is finished, so we can enter lock-down mode 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_service->LowerToken(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lpfnInit init_function = 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (lpfnInit) ::GetProcAddress(dll_module, entry_point.c_str()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!init_function) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(finnur): write the failure to the log file 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::FreeLibrary(dll_module); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pipe); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -6; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transfer control to the entry point in the DLL requested 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_function(pipe); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pipe); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(1000); // Give a change to the debug output to arrive before the 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end of the process 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::FreeLibrary(dll_module); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 183