summaryrefslogtreecommitdiffstats
path: root/sandbox/sandbox_poc/sandbox.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/sandbox_poc/sandbox.cc')
-rw-r--r--sandbox/sandbox_poc/sandbox.cc207
1 files changed, 207 insertions, 0 deletions
diff --git a/sandbox/sandbox_poc/sandbox.cc b/sandbox/sandbox_poc/sandbox.cc
new file mode 100644
index 0000000..7ee9f91
--- /dev/null
+++ b/sandbox/sandbox_poc/sandbox.cc
@@ -0,0 +1,207 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <windows.h>
+#include <tchar.h>
+#include <shellapi.h>
+#include "sandbox/sandbox_poc/sandbox.h"
+#include "base/logging.h"
+#include "sandbox/sandbox_poc/main_ui_window.h"
+#include "sandbox/src/sandbox.h"
+#include "sandbox/src/sandbox_factory.h"
+
+// Prototype allowed for functions to be called in the POC
+typedef void(__cdecl *lpfnInit)(HANDLE);
+
+bool ParseCommandLine(wchar_t * command_line,
+ std::string * dll_name,
+ std::string * entry_point,
+ std::wstring * log_file) {
+ DCHECK(dll_name);
+ DCHECK(entry_point);
+ DCHECK(log_file);
+ if (!dll_name || !entry_point || !log_file)
+ return false;
+
+ LPWSTR *arg_list;
+ int arg_count;
+
+ // We expect the command line to contain: EntryPointName "DLLPath" "LogPath"
+ // NOTE: Double quotes are required, even if long path name not used
+ // NOTE: LogPath can be blank, but still requires the double quotes
+ arg_list = CommandLineToArgvW(command_line, &arg_count);
+ if (NULL == arg_list || arg_count < 4) {
+ return false;
+ }
+
+ std::wstring entry_point_wide = arg_list[1];
+ std::wstring dll_name_wide = arg_list[2];
+ *entry_point = std::string(entry_point_wide.begin(), entry_point_wide.end());
+ *dll_name = std::string(dll_name_wide.begin(), dll_name_wide.end());
+ *log_file = arg_list[3];
+
+ // Free memory allocated for CommandLineToArgvW arguments.
+ LocalFree(arg_list);
+
+ return true;
+}
+
+int APIENTRY _tWinMain(HINSTANCE instance, HINSTANCE, wchar_t* command_line,
+ int show_command) {
+ UNREFERENCED_PARAMETER(command_line);
+
+ sandbox::BrokerServices* broker_service =
+ sandbox::SandboxFactory::GetBrokerServices();
+ sandbox::ResultCode result;
+
+ // This application starts as the broker; an application with a UI that
+ // spawns an instance of itself (called a 'target') inside the sandbox.
+ // Before spawning a hidden instance of itself, the application will have
+ // asked the user which DLL the spawned instance should load and passes
+ // that as command line argument to the spawned instance.
+ //
+ // We check here to see if we can retrieve a pointer to the BrokerServices,
+ // which is not possible if we are running inside the sandbox under a
+ // restricted token so it also tells us which mode we are in. If we can
+ // retrieve the pointer, then we are the broker, otherwise we are the target
+ // that the broker launched.
+ if (NULL != broker_service) {
+ // Yes, we are the broker so we need to initialize and show the UI
+ if (0 != (result = broker_service->Init())) {
+ ::MessageBox(NULL, L"Failed to initialize the BrokerServices object",
+ L"Error during initialization", MB_ICONERROR);
+ return 1;
+ }
+
+ wchar_t exe_name[MAX_PATH];
+ if (0 == GetModuleFileName(NULL, exe_name, MAX_PATH - 1)) {
+ ::MessageBox(NULL, L"Failed to get name of current EXE",
+ L"Error during initialization", MB_ICONERROR);
+ return 1;
+ }
+
+ // The CreateMainWindowAndLoop() call will not return until the user closes
+ // the application window (or selects File\Exit).
+ MainUIWindow window;
+ window.CreateMainWindowAndLoop(instance,
+ exe_name,
+ show_command,
+ broker_service);
+
+
+ // Cannot exit until we have cleaned up after all the targets we have
+ // created
+ broker_service->WaitForAllTargets();
+ } else {
+ // This is an instance that has been spawned inside the sandbox by the
+ // broker, so we need to parse the command line to figure out which DLL to
+ // load and what entry point to call
+ sandbox::TargetServices* target_service
+ = sandbox::SandboxFactory::GetTargetServices();
+
+ if (NULL == target_service) {
+ // TODO(finnur): write the failure to the log file
+ // We cannot display messageboxes inside the sandbox unless access to
+ // the desktop handle has been granted to us, and we don't have a
+ // console window to write to. Therefore we need to have the broker
+ // grant us access to a handle to a logfile and write the error that
+ // occurred into the log before continuing
+ return -1;
+ }
+
+ // Debugging the spawned application can be tricky, because DebugBreak()
+ // and _asm int 3 cause the app to terminate (due to a flag in the job
+ // object), MessageBoxes() will not be displayed unless we have been granted
+ // that privilege and the target finishes its business so quickly we cannot
+ // attach to it quickly enough. Therefore, you can uncomment the
+ // following line and attach (w. msdev or windbg) as the target is sleeping
+
+ // Sleep(10000);
+
+ if (sandbox::SBOX_ALL_OK != (result = target_service->Init())) {
+ // TODO(finnur): write the initialization error to the log file
+ return -2;
+ }
+
+ // Parse the command line to find out what we need to call
+ std::string dll_name, entry_point;
+ std::wstring log_file;
+ if (!ParseCommandLine(GetCommandLineW(),
+ &dll_name,
+ &entry_point,
+ &log_file)) {
+ // TODO(finnur): write the failure to the log file
+ return -3;
+ }
+
+ // Open the pipe to transfert the log output
+ HANDLE pipe = ::CreateFile(log_file.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // Default security attributes.
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL); // No template
+
+ if (INVALID_HANDLE_VALUE == pipe) {
+ return -4;
+ }
+
+ // Initialization is finished, so we can enter lock-down mode
+ target_service->LowerToken();
+
+ // We now know what we should load, so load it
+ HMODULE dll_module = ::LoadLibraryA(dll_name.c_str());
+ if (dll_module == NULL) {
+ // TODO(finnur): write the failure to the log file
+ return -5;
+ }
+
+ lpfnInit init_function =
+ (lpfnInit) ::GetProcAddress(dll_module, entry_point.c_str());
+
+ if (!init_function) {
+ // TODO(finnur): write the failure to the log file
+ ::FreeLibrary(dll_module);
+ CloseHandle(pipe);
+ return -6;
+ }
+
+ // Transfer control to the entry point in the DLL requested
+ init_function(pipe);
+
+ CloseHandle(pipe);
+ Sleep(1000); // Give a change to the debug output to arrive before the
+ // end of the process
+
+ ::FreeLibrary(dll_module);
+ }
+
+ return 0;
+}