summaryrefslogtreecommitdiff
path: root/sandbox/win/sandbox_poc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/win/sandbox_poc')
-rw-r--r--sandbox/win/sandbox_poc/main_ui_window.cc670
-rw-r--r--sandbox/win/sandbox_poc/main_ui_window.h194
-rw-r--r--sandbox/win/sandbox_poc/pocdll/exports.h89
-rw-r--r--sandbox/win/sandbox_poc/pocdll/fs.cc54
-rw-r--r--sandbox/win/sandbox_poc/pocdll/handles.cc186
-rw-r--r--sandbox/win/sandbox_poc/pocdll/invasive.cc196
-rw-r--r--sandbox/win/sandbox_poc/pocdll/network.cc66
-rw-r--r--sandbox/win/sandbox_poc/pocdll/pocdll.cc27
-rw-r--r--sandbox/win/sandbox_poc/pocdll/pocdll.vcproj218
-rw-r--r--sandbox/win/sandbox_poc/pocdll/processes_and_threads.cc102
-rw-r--r--sandbox/win/sandbox_poc/pocdll/registry.cc49
-rw-r--r--sandbox/win/sandbox_poc/pocdll/spyware.cc68
-rw-r--r--sandbox/win/sandbox_poc/pocdll/utils.h65
-rw-r--r--sandbox/win/sandbox_poc/resource.h30
-rw-r--r--sandbox/win/sandbox_poc/sandbox.cc182
-rw-r--r--sandbox/win/sandbox_poc/sandbox.h10
-rw-r--r--sandbox/win/sandbox_poc/sandbox.icobin0 -> 1078 bytes
-rw-r--r--sandbox/win/sandbox_poc/sandbox.rc136
-rw-r--r--sandbox/win/sandbox_poc/sandbox_poc.vcproj202
19 files changed, 2544 insertions, 0 deletions
diff --git a/sandbox/win/sandbox_poc/main_ui_window.cc b/sandbox/win/sandbox_poc/main_ui_window.cc
new file mode 100644
index 0000000000..6c5d17727a
--- /dev/null
+++ b/sandbox/win/sandbox_poc/main_ui_window.cc
@@ -0,0 +1,670 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <CommCtrl.h>
+#include <commdlg.h>
+#include <stdarg.h>
+#include <time.h>
+#include <windowsx.h>
+#include <atlbase.h>
+#include <atlsecurity.h>
+#include <algorithm>
+#include <sstream>
+
+#include "sandbox/win/sandbox_poc/main_ui_window.h"
+#include "base/logging.h"
+#include "sandbox/win/sandbox_poc/resource.h"
+#include "sandbox/win/src/acl.h"
+#include "sandbox/win/src/sandbox.h"
+#include "sandbox/win/src/win_utils.h"
+
+HWND MainUIWindow::list_view_ = NULL;
+
+const wchar_t MainUIWindow::kDefaultDll_[] = L"\\POCDLL.dll";
+const wchar_t MainUIWindow::kDefaultEntryPoint_[] = L"Run";
+const wchar_t MainUIWindow::kDefaultLogFile_[] = L"";
+
+MainUIWindow::MainUIWindow()
+ : instance_handle_(NULL),
+ spawn_target_(L""),
+ dll_path_(L""),
+ entry_point_(L""),
+ broker_(NULL) {
+}
+
+MainUIWindow::~MainUIWindow() {
+}
+
+unsigned int MainUIWindow::CreateMainWindowAndLoop(
+ HINSTANCE instance,
+ wchar_t* command_line,
+ int show_command,
+ sandbox::BrokerServices* broker) {
+ DCHECK(instance);
+ DCHECK(command_line);
+ DCHECK(broker);
+
+ instance_handle_ = instance;
+ spawn_target_ = command_line;
+ broker_ = broker;
+
+ // We'll use spawn_target_ later for creating a child process, but
+ // CreateProcess doesn't like double quotes, so we remove them along with
+ // tabs and spaces from the start and end of the string
+ const wchar_t *trim_removal = L" \r\t\"";
+ spawn_target_.erase(0, spawn_target_.find_first_not_of(trim_removal));
+ spawn_target_.erase(spawn_target_.find_last_not_of(trim_removal) + 1);
+
+ WNDCLASSEX window_class = {0};
+ window_class.cbSize = sizeof(WNDCLASSEX);
+ window_class.style = CS_HREDRAW | CS_VREDRAW;
+ window_class.lpfnWndProc = MainUIWindow::WndProc;
+ window_class.cbClsExtra = 0;
+ window_class.cbWndExtra = 0;
+ window_class.hInstance = instance;
+ window_class.hIcon =
+ ::LoadIcon(instance, MAKEINTRESOURCE(IDI_SANDBOX));
+ window_class.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ window_class.hbrBackground = GetStockBrush(WHITE_BRUSH);
+ window_class.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_MAIN_UI);
+ window_class.lpszClassName = L"sandbox_ui_1";
+ window_class.hIconSm = NULL;
+
+ INITCOMMONCONTROLSEX controls = {
+ sizeof(INITCOMMONCONTROLSEX),
+ ICC_STANDARD_CLASSES | ICC_LISTVIEW_CLASSES
+ };
+ ::InitCommonControlsEx(&controls);
+
+ if (!::RegisterClassEx(&window_class))
+ return ::GetLastError();
+
+ // Create a main window of size 600x400
+ HWND window = ::CreateWindowW(window_class.lpszClassName,
+ L"", // window name
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, // x
+ CW_USEDEFAULT, // y
+ 600, // width
+ 400, // height
+ NULL, // parent
+ NULL, // NULL = use class menu
+ instance,
+ 0); // lpParam
+
+ if (NULL == window)
+ return ::GetLastError();
+
+ ::SetWindowLongPtr(window,
+ GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(this));
+
+ ::SetWindowText(window, L"Sandbox Proof of Concept");
+
+ ::ShowWindow(window, show_command);
+
+ MSG message;
+ // Now lets start the message pump retrieving messages for any window that
+ // belongs to the current thread
+ while (::GetMessage(&message, NULL, 0, 0)) {
+ ::TranslateMessage(&message);
+ ::DispatchMessage(&message);
+ }
+
+ return 0;
+}
+
+LRESULT CALLBACK MainUIWindow::WndProc(HWND window,
+ UINT message_id,
+ WPARAM wparam,
+ LPARAM lparam) {
+ MainUIWindow* host = FromWindow(window);
+
+ #define HANDLE_MSG(hwnd, message, fn) \
+ case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
+
+ switch (message_id) {
+ case WM_CREATE:
+ // 'host' is not yet available when we get the WM_CREATE message
+ return HANDLE_WM_CREATE(window, wparam, lparam, OnCreate);
+ case WM_DESTROY:
+ return HANDLE_WM_DESTROY(window, wparam, lparam, host->OnDestroy);
+ case WM_SIZE:
+ return HANDLE_WM_SIZE(window, wparam, lparam, host->OnSize);
+ case WM_COMMAND: {
+ // Look at which menu item was clicked on (or which accelerator)
+ int id = LOWORD(wparam);
+ switch (id) {
+ case ID_FILE_EXIT:
+ host->OnFileExit();
+ break;
+ case ID_COMMANDS_SPAWNTARGET:
+ host->OnCommandsLaunch(window);
+ break;
+ default:
+ // Some other menu item or accelerator
+ break;
+ }
+
+ return ERROR_SUCCESS;
+ }
+
+ default:
+ // Some other WM_message, let it pass to DefWndProc
+ break;
+ }
+
+ return DefWindowProc(window, message_id, wparam, lparam);
+}
+
+INT_PTR CALLBACK MainUIWindow::SpawnTargetWndProc(HWND dialog,
+ UINT message_id,
+ WPARAM wparam,
+ LPARAM lparam) {
+ UNREFERENCED_PARAMETER(lparam);
+
+ // Grab a reference to the main UI window (from the window handle)
+ MainUIWindow* host = FromWindow(GetParent(dialog));
+ DCHECK(host);
+
+ switch (message_id) {
+ case WM_INITDIALOG: {
+ // Initialize the window text for DLL name edit box
+ HWND edit_box_dll_name = ::GetDlgItem(dialog, IDC_DLL_NAME);
+ wchar_t current_dir[MAX_PATH];
+ if (GetCurrentDirectory(MAX_PATH, current_dir)) {
+ base::string16 dll_path = base::string16(current_dir) +
+ base::string16(kDefaultDll_);
+ ::SetWindowText(edit_box_dll_name, dll_path.c_str());
+ }
+
+ // Initialize the window text for Entry Point edit box
+ HWND edit_box_entry_point = ::GetDlgItem(dialog, IDC_ENTRY_POINT);
+ ::SetWindowText(edit_box_entry_point, kDefaultEntryPoint_);
+
+ // Initialize the window text for Log File edit box
+ HWND edit_box_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE);
+ ::SetWindowText(edit_box_log_file, kDefaultLogFile_);
+
+ return static_cast<INT_PTR>(TRUE);
+ }
+ case WM_COMMAND:
+ // If the user presses the OK button (Launch)
+ if (LOWORD(wparam) == IDOK) {
+ if (host->OnLaunchDll(dialog)) {
+ if (host->SpawnTarget()) {
+ ::EndDialog(dialog, LOWORD(wparam));
+ }
+ }
+ return static_cast<INT_PTR>(TRUE);
+ } else if (LOWORD(wparam) == IDCANCEL) {
+ // If the user presses the Cancel button
+ ::EndDialog(dialog, LOWORD(wparam));
+ return static_cast<INT_PTR>(TRUE);
+ } else if (LOWORD(wparam) == IDC_BROWSE_DLL) {
+ // If the user presses the Browse button to look for a DLL
+ base::string16 dll_path = host->OnShowBrowseForDllDlg(dialog);
+ if (dll_path.length() > 0) {
+ // Initialize the window text for Log File edit box
+ HWND edit_box_dll_path = ::GetDlgItem(dialog, IDC_DLL_NAME);
+ ::SetWindowText(edit_box_dll_path, dll_path.c_str());
+ }
+ return static_cast<INT_PTR>(TRUE);
+ } else if (LOWORD(wparam) == IDC_BROWSE_LOG) {
+ // If the user presses the Browse button to look for a log file
+ base::string16 log_path = host->OnShowBrowseForLogFileDlg(dialog);
+ if (log_path.length() > 0) {
+ // Initialize the window text for Log File edit box
+ HWND edit_box_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE);
+ ::SetWindowText(edit_box_log_file, log_path.c_str());
+ }
+ return static_cast<INT_PTR>(TRUE);
+ }
+
+ break;
+ }
+
+ return static_cast<INT_PTR>(FALSE);
+}
+
+MainUIWindow* MainUIWindow::FromWindow(HWND main_window) {
+ // We store a 'this' pointer using SetWindowLong in CreateMainWindowAndLoop
+ // so that we can retrieve it with this function later. This prevents us
+ // from having to define all the message handling functions (that we refer to
+ // in the window proc) as static
+ ::GetWindowLongPtr(main_window, GWLP_USERDATA);
+ return reinterpret_cast<MainUIWindow*>(
+ ::GetWindowLongPtr(main_window, GWLP_USERDATA));
+}
+
+BOOL MainUIWindow::OnCreate(HWND parent_window, LPCREATESTRUCT) {
+ // Create the listview that will the main app UI
+ list_view_ = ::CreateWindow(WC_LISTVIEW, // Class name
+ L"", // Window name
+ WS_CHILD | WS_VISIBLE | LVS_REPORT |
+ LVS_NOCOLUMNHEADER | WS_BORDER,
+ 0, // x
+ 0, // y
+ 0, // width
+ 0, // height
+ parent_window, // parent
+ NULL, // menu
+ ::GetModuleHandle(NULL),
+ 0); // lpParam
+
+ DCHECK(list_view_);
+ if (!list_view_)
+ return FALSE;
+
+ LVCOLUMN list_view_column = {0};
+ list_view_column.mask = LVCF_FMT | LVCF_WIDTH ;
+ list_view_column.fmt = LVCFMT_LEFT;
+ list_view_column.cx = 10000; // Maximum size of an entry in the list view.
+ ListView_InsertColumn(list_view_, 0, &list_view_column);
+
+ // Set list view to show green font on black background
+ ListView_SetBkColor(list_view_, CLR_NONE);
+ ListView_SetTextColor(list_view_, RGB(0x0, 0x0, 0x0));
+ ListView_SetTextBkColor(list_view_, CLR_NONE);
+
+ return TRUE;
+}
+
+void MainUIWindow::OnDestroy(HWND window) {
+ UNREFERENCED_PARAMETER(window);
+
+ // Post a quit message because our application is over when the
+ // user closes this window.
+ ::PostQuitMessage(0);
+}
+
+void MainUIWindow::OnSize(HWND window, UINT state, int cx, int cy) {
+ UNREFERENCED_PARAMETER(window);
+ UNREFERENCED_PARAMETER(state);
+
+ // If we have a valid inner child, resize it to cover the entire
+ // client area of the main UI window.
+ if (list_view_) {
+ ::MoveWindow(list_view_,
+ 0, // x
+ 0, // y
+ cx, // width
+ cy, // height
+ TRUE); // repaint
+ }
+}
+
+void MainUIWindow::OnPaint(HWND window) {
+ PAINTSTRUCT paintstruct;
+ ::BeginPaint(window, &paintstruct);
+ // add painting code here if required
+ ::EndPaint(window, &paintstruct);
+}
+
+void MainUIWindow::OnFileExit() {
+ ::PostQuitMessage(0);
+}
+
+void MainUIWindow::OnCommandsLaunch(HWND window) {
+ // User wants to see the Select DLL dialog box
+ ::DialogBox(instance_handle_,
+ MAKEINTRESOURCE(IDD_LAUNCH_DLL),
+ window,
+ SpawnTargetWndProc);
+}
+
+bool MainUIWindow::OnLaunchDll(HWND dialog) {
+ HWND edit_box_dll_name = ::GetDlgItem(dialog, IDC_DLL_NAME);
+ HWND edit_box_entry_point = ::GetDlgItem(dialog, IDC_ENTRY_POINT);
+ HWND edit_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE);
+
+ wchar_t dll_path[MAX_PATH];
+ wchar_t entry_point[MAX_PATH];
+ wchar_t log_file[MAX_PATH];
+
+ int dll_name_len = ::GetWindowText(edit_box_dll_name, dll_path, MAX_PATH);
+ int entry_point_len = ::GetWindowText(edit_box_entry_point,
+ entry_point, MAX_PATH);
+ // Log file is optional (can be blank)
+ ::GetWindowText(edit_log_file, log_file, MAX_PATH);
+
+ if (0 >= dll_name_len) {
+ ::MessageBox(dialog,
+ L"Please specify a DLL for the target to load",
+ L"No DLL specified",
+ MB_ICONERROR);
+ return false;
+ }
+
+ if (GetFileAttributes(dll_path) == INVALID_FILE_ATTRIBUTES) {
+ ::MessageBox(dialog,
+ L"DLL specified was not found",
+ L"DLL not found",
+ MB_ICONERROR);
+ return false;
+ }
+
+ if (0 >= entry_point_len) {
+ ::MessageBox(dialog,
+ L"Please specify an entry point for the DLL",
+ L"No entry point specified",
+ MB_ICONERROR);
+ return false;
+ }
+
+ // store these values in the member variables for use in SpawnTarget
+ log_file_ = base::string16(L"\"") + log_file + base::string16(L"\"");
+ dll_path_ = dll_path;
+ entry_point_ = entry_point;
+
+ return true;
+}
+
+DWORD WINAPI MainUIWindow::ListenPipeThunk(void *param) {
+ return reinterpret_cast<MainUIWindow*>(param)->ListenPipe();
+}
+
+DWORD WINAPI MainUIWindow::WaitForTargetThunk(void *param) {
+ return reinterpret_cast<MainUIWindow*>(param)->WaitForTarget();
+}
+
+// Thread waiting for the target application to die. It displays
+// a message in the list view when it happens.
+DWORD MainUIWindow::WaitForTarget() {
+ WaitForSingleObject(target_.hProcess, INFINITE);
+
+ DWORD exit_code = 0;
+ if (!GetExitCodeProcess(target_.hProcess, &exit_code)) {
+ exit_code = 0xFFFF; // Default exit code
+ }
+
+ ::CloseHandle(target_.hProcess);
+ ::CloseHandle(target_.hThread);
+
+ AddDebugMessage(L"Targed exited with return code %d", exit_code);
+ return 0;
+}
+
+// Thread waiting for messages on the log pipe. It displays the messages
+// in the listview.
+DWORD MainUIWindow::ListenPipe() {
+ HANDLE logfile_handle = NULL;
+ ATL::CString file_to_open = log_file_.c_str();
+ file_to_open.Remove(L'\"');
+ if (file_to_open.GetLength()) {
+ logfile_handle = ::CreateFile(file_to_open.GetBuffer(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // Default security attributes
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL); // No template
+ if (INVALID_HANDLE_VALUE == logfile_handle) {
+ AddDebugMessage(L"Failed to open \"%ls\" for logging. Error %d",
+ file_to_open.GetBuffer(), ::GetLastError());
+ logfile_handle = NULL;
+ }
+ }
+
+ const int kSizeBuffer = 1024;
+ BYTE read_buffer[kSizeBuffer] = {0};
+ ATL::CStringA read_buffer_global;
+ ATL::CStringA string_to_print;
+
+ DWORD last_error = 0;
+ while(last_error == ERROR_SUCCESS || last_error == ERROR_PIPE_LISTENING ||
+ last_error == ERROR_NO_DATA)
+ {
+ DWORD read_data_length;
+ if (::ReadFile(pipe_handle_,
+ read_buffer,
+ kSizeBuffer - 1, // Max read size
+ &read_data_length,
+ NULL)) { // Not overlapped
+ if (logfile_handle) {
+ DWORD write_data_length;
+ ::WriteFile(logfile_handle,
+ read_buffer,
+ read_data_length,
+ &write_data_length,
+ FALSE); // Not overlapped
+ }
+
+ // Append the new buffer to the current buffer
+ read_buffer[read_data_length] = NULL;
+ read_buffer_global += reinterpret_cast<char *>(read_buffer);
+ read_buffer_global.Remove(10); // Remove the CRs
+
+ // If we completed a new line, output it
+ int endline = read_buffer_global.Find(13); // search for LF
+ while (-1 != endline) {
+ string_to_print = read_buffer_global;
+ string_to_print.Delete(endline, string_to_print.GetLength());
+ read_buffer_global.Delete(0, endline);
+
+ // print the line (with the ending LF)
+ OutputDebugStringA(string_to_print.GetBuffer());
+
+ // Remove the ending LF
+ read_buffer_global.Delete(0, 1);
+
+ // Add the line to the log
+ AddDebugMessage(L"%S", string_to_print.GetBuffer());
+
+ endline = read_buffer_global.Find(13);
+ }
+ last_error = ERROR_SUCCESS;
+ } else {
+ last_error = GetLastError();
+ Sleep(100);
+ }
+ }
+
+ if (read_buffer_global.GetLength()) {
+ AddDebugMessage(L"%S", read_buffer_global.GetBuffer());
+ }
+
+ CloseHandle(pipe_handle_);
+
+ if (logfile_handle) {
+ CloseHandle(logfile_handle);
+ }
+
+ return 0;
+}
+
+bool MainUIWindow::SpawnTarget() {
+ // Generate the pipe name
+ GUID random_id;
+ CoCreateGuid(&random_id);
+
+ wchar_t log_pipe[MAX_PATH] = {0};
+ wnsprintf(log_pipe, MAX_PATH - 1,
+ L"\\\\.\\pipe\\sbox_pipe_log_%lu_%lu_%lu_%lu",
+ random_id.Data1,
+ random_id.Data2,
+ random_id.Data3,
+ random_id.Data4);
+
+ // We concatenate the four strings, add three spaces and a zero termination
+ // We use the resulting string as a param to CreateProcess (in SpawnTarget)
+ // Documented maximum for command line in CreateProcess is 32K (msdn)
+ size_t size_call = spawn_target_.length() + entry_point_.length() +
+ dll_path_.length() + wcslen(log_pipe) + 6;
+ if (32 * 1024 < (size_call * sizeof(wchar_t))) {
+ AddDebugMessage(L"The length of the arguments exceeded 32K. "
+ L"Aborting operation.");
+ return false;
+ }
+
+ wchar_t * arguments = new wchar_t[size_call];
+ wnsprintf(arguments, static_cast<int>(size_call), L"%ls %ls \"%ls\" %ls",
+ spawn_target_.c_str(), entry_point_.c_str(),
+ dll_path_.c_str(), log_pipe);
+
+ arguments[size_call - 1] = L'\0';
+
+ sandbox::TargetPolicy* policy = broker_->CreatePolicy();
+ policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
+ policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+ sandbox::USER_LOCKDOWN);
+ policy->SetAlternateDesktop(true);
+ policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+
+ // Set the rule to allow the POC dll to be loaded by the target. Note that
+ // the rule allows 'all access' to the DLL, which could mean that the target
+ // could modify the DLL on disk.
+ policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY, dll_path_.c_str());
+
+ sandbox::ResultCode result = broker_->SpawnTarget(spawn_target_.c_str(),
+ arguments, policy,
+ &target_);
+
+ policy->Release();
+ policy = NULL;
+
+ bool return_value = false;
+ if (sandbox::SBOX_ALL_OK != result) {
+ AddDebugMessage(
+ L"Failed to spawn target %ls w/args (%ls), sandbox error code: %d",
+ spawn_target_.c_str(), arguments, result);
+ return_value = false;
+ } else {
+
+ DWORD thread_id;
+ ::CreateThread(NULL, // Default security attributes
+ NULL, // Default stack size
+ &MainUIWindow::WaitForTargetThunk,
+ this,
+ 0, // No flags
+ &thread_id);
+
+ pipe_handle_ = ::CreateNamedPipe(log_pipe,
+ PIPE_ACCESS_INBOUND | WRITE_DAC,
+ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
+ 1, // Number of instances.
+ 512, // Out buffer size.
+ 512, // In buffer size.
+ NMPWAIT_USE_DEFAULT_WAIT,
+ NULL); // Default security descriptor
+
+ if (INVALID_HANDLE_VALUE == pipe_handle_)
+ AddDebugMessage(L"Failed to create pipe. Error %d", ::GetLastError());
+
+ if (!sandbox::AddKnownSidToObject(pipe_handle_, SE_KERNEL_OBJECT,
+ WinWorldSid, GRANT_ACCESS,
+ FILE_ALL_ACCESS))
+ AddDebugMessage(L"Failed to set security on pipe. Error %d",
+ ::GetLastError());
+
+ ::CreateThread(NULL, // Default security attributes
+ NULL, // Default stack size
+ &MainUIWindow::ListenPipeThunk,
+ this,
+ 0, // No flags
+ &thread_id);
+
+ ::ResumeThread(target_.hThread);
+
+ AddDebugMessage(L"Successfully spawned target w/args (%ls)", arguments);
+ return_value = true;
+ }
+
+ delete[] arguments;
+ return return_value;
+}
+
+base::string16 MainUIWindow::OnShowBrowseForDllDlg(HWND owner) {
+ wchar_t filename[MAX_PATH];
+ wcscpy_s(filename, MAX_PATH, L"");
+
+ OPENFILENAMEW file_info = {0};
+ file_info.lStructSize = sizeof(file_info);
+ file_info.hwndOwner = owner;
+ file_info.lpstrFile = filename;
+ file_info.nMaxFile = MAX_PATH;
+ file_info.lpstrFilter = L"DLL files (*.dll)\0*.dll\0All files\0*.*\0\0\0";
+
+ file_info.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
+
+ if (GetOpenFileName(&file_info)) {
+ return file_info.lpstrFile;
+ }
+
+ return L"";
+}
+
+base::string16 MainUIWindow::OnShowBrowseForLogFileDlg(HWND owner) {
+ wchar_t filename[MAX_PATH];
+ wcscpy_s(filename, MAX_PATH, L"");
+
+ OPENFILENAMEW file_info = {0};
+ file_info.lStructSize = sizeof(file_info);
+ file_info.hwndOwner = owner;
+ file_info.lpstrFile = filename;
+ file_info.nMaxFile = MAX_PATH;
+ file_info.lpstrFilter = L"Log file (*.txt)\0*.txt\0All files\0*.*\0\0\0";
+
+ file_info.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
+
+ if (GetSaveFileName(&file_info)) {
+ return file_info.lpstrFile;
+ }
+
+ return L"";
+}
+
+void MainUIWindow::AddDebugMessage(const wchar_t* format, ...) {
+ DCHECK(format);
+ if (!format)
+ return;
+
+ const int kMaxDebugBuffSize = 1024;
+
+ va_list arg_list;
+ va_start(arg_list, format);
+
+ wchar_t text[kMaxDebugBuffSize + 1];
+ vswprintf_s(text, kMaxDebugBuffSize, format, arg_list);
+ text[kMaxDebugBuffSize] = L'\0';
+
+ InsertLineInListView(text);
+}
+
+
+void MainUIWindow::InsertLineInListView(wchar_t* debug_message) {
+ DCHECK(debug_message);
+ if (!debug_message)
+ return;
+
+ // Prepend the time to the message
+ const int kSizeTime = 100;
+ size_t size_message_with_time = wcslen(debug_message) + kSizeTime;
+ wchar_t * message_time = new wchar_t[size_message_with_time];
+
+ time_t time_temp;
+ time_temp = time(NULL);
+
+ struct tm time = {0};
+ localtime_s(&time, &time_temp);
+
+ size_t return_code;
+ return_code = wcsftime(message_time, kSizeTime, L"[%H:%M:%S] ", &time);
+
+ wcscat_s(message_time, size_message_with_time, debug_message);
+
+ // We add the debug message to the top of the listview
+ LVITEM item;
+ item.iItem = ListView_GetItemCount(list_view_);
+ item.iSubItem = 0;
+ item.mask = LVIF_TEXT | LVIF_PARAM;
+ item.pszText = message_time;
+ item.lParam = 0;
+
+ ListView_InsertItem(list_view_, &item);
+
+ delete[] message_time;
+}
diff --git a/sandbox/win/sandbox_poc/main_ui_window.h b/sandbox/win/sandbox_poc/main_ui_window.h
new file mode 100644
index 0000000000..84fb9861c9
--- /dev/null
+++ b/sandbox/win/sandbox_poc/main_ui_window.h
@@ -0,0 +1,194 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__
+#define SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+
+namespace sandbox {
+class BrokerServices;
+enum ResultCode;
+}
+
+// Header file for the MainUIWindow, a simple window with a menu bar that
+// can pop up a dialog (accessible through the menu bar), to specify a path and
+// filename of any DLL to load and choose an entry point of his/her choice
+// (note: only entry points with no parameters are expected to work).
+//
+// The purpose of this is to be able to spawn an EXE inside a SandBox, have it
+// load a DLL and call the entry point on it to test how it behaves inside the
+// sandbox. This is useful for developer debugging and for security testing.
+//
+// The MainUIWindow also has a listview that displays debugging information to
+// the user.
+//
+// Sample usage:
+//
+// MainUIWindow window;
+// unsigned int ret = window.CreateMainWindowAndLoop(
+// handle_to_current_instance,
+// ::GetCommandLineW(),
+// show_command,
+// broker);
+//
+// The CreateMainWindowAndLoop() contains a message loop that ends when the
+// user closes the MainUIWindow.
+
+// This class encapsulates the Main UI window for the broker application.
+// It simply shows a menu that gives the user the ability (through a dialog) to
+// specify a DLL and what entry point to call in the DLL.
+class MainUIWindow {
+ public:
+ MainUIWindow();
+ ~MainUIWindow();
+
+ // Creates the main window, displays it and starts the message pump. This
+ // call will not return until user closes the main UI window that appears
+ // as a result. Arguments 'instance', 'command_line' and 'show_cmd' can be
+ // passed in directly from winmain. The 'broker' argument is a pointer to a
+ // BrokerService that will launch a new EXE inside the sandbox and load the
+ // DLL of the user's choice.
+ unsigned int CreateMainWindowAndLoop(HINSTANCE instance,
+ wchar_t* command_line,
+ int show_command,
+ sandbox::BrokerServices* broker);
+
+ private:
+ // The default value DLL name to add to the edit box.
+ static const wchar_t kDefaultDll_[];
+
+ // The default value to show in the entry point.
+ static const wchar_t kDefaultEntryPoint_[];
+
+ // The default value to show in the log file.
+ static const wchar_t kDefaultLogFile_[];
+
+ // Handles the messages sent to the main UI window. The return value is the
+ // result of the message processing and depends on the message.
+ static LRESULT CALLBACK WndProc(HWND window,
+ UINT message_id,
+ WPARAM wparam,
+ LPARAM lparam);
+
+ // Handles the messages sent to the SpawnTarget dialog. The return value is
+ // the result of the message processing and depends on the message.
+ static INT_PTR CALLBACK SpawnTargetWndProc(HWND dialog,
+ UINT message_id,
+ WPARAM wparam,
+ LPARAM lparam);
+
+ // Retrieves a pointer to the MainWindow from a value stored along with the
+ // window handle (passed in as hwnd). Return value is a pointer to the
+ // MainUIWindow previously stored with SetWindowLong() during WM_CREATE.
+ static MainUIWindow* FromWindow(HWND main_window);
+
+ // Handles the WM_CREATE message for the main UI window. Returns TRUE on
+ // success.
+ static BOOL OnCreate(HWND parent_window, LPCREATESTRUCT);
+
+ // Handles the WM_DESTROY message for the main UI window.
+ void OnDestroy(HWND window);
+
+ // Handles the WM_SIZE message for the main UI window.
+ void OnSize(HWND window, UINT state, int cx, int cy);
+
+ // Handles the WM_PAINT message for the main UI window.
+ void OnPaint(HWND window);
+
+ // Handles the menu command File \ Exit for the main UI window.
+ void OnFileExit();
+
+ // Handles the menu command Commands \ Launch for the main UI window.
+ void OnCommandsLaunch(HWND window);
+
+ // Handles the Launch button in the SpawnTarget dialog (normally clicked
+ // after selecting DLL and entry point). OnLaunchDll will retrieve the
+ // values entered by the user and store it in the members of the class.
+ // Returns true if user selected a non-zero values for DLL filename
+ // (possibly including path also) and entry point.
+ bool OnLaunchDll(HWND dialog);
+
+ // Spawns a target EXE inside the sandbox (with the help of the
+ // BrokerServices passed in to CreateMainWindowAndLoop), and passes to it
+ // (as command line arguments) the DLL path and the entry point function
+ // name. The EXE is expected to parse the command line and load the DLL.
+ // NOTE: The broker does not know if the target EXE successfully loaded the
+ // DLL, for that you have to rely on the EXE providing a log.
+ // Returns true if the broker reports that it was successful in creating
+ // the target and false if not.
+ bool SpawnTarget();
+
+ // Shows a standard File Open dialog and returns the DLL filename selected or
+ // blank string if the user cancelled (or an error occurred).
+ base::string16 OnShowBrowseForDllDlg(HWND owner);
+
+ // Shows a standard Save As dialog and returns the log filename selected or
+ // blank string if the user cancelled (or an error occurred).
+ base::string16 OnShowBrowseForLogFileDlg(HWND owner);
+
+ // Formats a message using the supplied format string and prints it in the
+ // listview in the main UI window. Passing a NULL param in 'fmt' results in
+ // no action being performed. Maximum message length is 1K.
+ void AddDebugMessage(const wchar_t* format, ...);
+
+ // Assists AddDebugMessage in displaying a message in the ListView. It
+ // simply wraps ListView_InsertItem to insert a debugging message to the
+ // top of the list view. Passing a NULL param in 'fmt' results in no action
+ // being performed.
+ void InsertLineInListView(wchar_t* debug_message);
+
+ // Calls ListenPipe using the class instance received in parameter. This is
+ // used to create new threads executing ListenPipe
+ static DWORD WINAPI ListenPipeThunk(void *param);
+
+ // Calls WaitForTargetThunk using the class instance received in parameter
+ // This is used to create new threads executing WaitForTarget.
+ static DWORD WINAPI WaitForTargetThunk(void *param);
+
+ // Listens on a pipe and output the data received to a file and to the UI.
+ DWORD ListenPipe();
+
+ // Waits for the target to dies and display a message in the UI.
+ DWORD WaitForTarget();
+
+ // The BrokerServices will be used to spawn an EXE in a sandbox and ask
+ // it to load a DLL.
+ sandbox::BrokerServices* broker_;
+
+ // Contains the information about the running target.
+ PROCESS_INFORMATION target_;
+
+ // This is essentially a command line to a target executable that the
+ // broker will spawn and ask to load the DLL.
+ base::string16 spawn_target_;
+
+ // A handle to the current instance of the app. Passed in to this class
+ // through CreateMainWindowAndLoop.
+ HINSTANCE instance_handle_;
+
+ // A path to the DLL that the target should load once it executes.
+ base::string16 dll_path_;
+
+ // The name of the entry point the target should call after it loads the DLL.
+ base::string16 entry_point_;
+
+ // The name of the log file to use.
+ base::string16 log_file_;
+
+ // This is a static handle to the list view that fills up the entire main
+ // UI window. The list view is used to display debugging information to the
+ // user.
+ static HWND list_view_;
+
+ // Pipe used to communicate the logs between the target and the broker.
+ HANDLE pipe_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(MainUIWindow);
+};
+
+#endif // SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__
diff --git a/sandbox/win/sandbox_poc/pocdll/exports.h b/sandbox/win/sandbox_poc/pocdll/exports.h
new file mode 100644
index 0000000000..66a07d6b78
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/exports.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SANDBOX_POC_POCDLL_EXPORTS_H__
+#define SANDBOX_SANDBOX_POC_POCDLL_EXPORTS_H__
+
+#include <windows.h>
+
+#ifdef POCDLL_EXPORTS
+#define POCDLL_API __declspec(dllexport) __cdecl
+#else
+#define POCDLL_API __declspec(dllimport) __cdecl
+#endif
+
+extern "C" {
+// Tries to open several known system path and outputs
+// the result.
+// "log" is the handle of the log file.
+void POCDLL_API TestFileSystem(HANDLE log);
+
+// Tries to find all handles open in the process and prints the name of the
+// resource references by the handle along with the access right.
+// "log" is the handle of the log file.
+void POCDLL_API TestGetHandle(HANDLE log);
+
+// Creates a lot of threads until it cannot create more. The goal of this
+// function is to determine if it's possible to crash the machine when we
+// flood the machine with new threads
+// "log" is the handle of the log file.
+void POCDLL_API TestThreadBombing(HANDLE log);
+
+// Takes all cpu of the machine. For each processor on the machine we assign
+// a thread. This thread will compute a mathematical expression over and over
+// to take all cpu.
+// "log" is the handle of the log file.
+// Note: here we are using the affinity to find out how many processors are on
+// the machine and to force a thread to run only on a given processor.
+void POCDLL_API TestTakeAllCpu(HANDLE log);
+
+// Creates memory in the heap until it fails 5 times in a row and prints the
+// amount of memory created. This function is used to find out if it's possible
+// to take all memory on the machine and crash the system.
+// "log" is the handle of the log file.
+void POCDLL_API TestUseAllMemory(HANDLE log);
+
+// Creates millions of kernel objects. This function is used to find out if it's
+// possible to crash the system if we create too many kernel objects and if we
+// hold too many handles. All those kernel objects are unnamed.
+// "log" is the handle of the log file.
+void POCDLL_API TestCreateObjects(HANDLE log);
+
+// Receives a hwnd and tries to close it. This is the callback for EnumWindows.
+// It will be called for each window(hwnd) on the system.
+// "log" is the handle of the log file.
+// Always returns TRUE to tell the system that we want to continue the
+// enumeration.
+void POCDLL_API TestCloseHWND(HANDLE log);
+
+// Tries to listen on the port 88.
+// "log" is the handle of the log file.
+void POCDLL_API TestNetworkListen(HANDLE log);
+
+// Lists all processes on the system and tries to open them
+// "log" is the handle of the log file.
+void POCDLL_API TestProcesses(HANDLE log);
+
+// Lists all threads on the system and tries to open them
+// "log" is the handle of the log file.
+void POCDLL_API TestThreads(HANDLE log);
+
+// Tries to open some known system registry key and outputs the result.
+// "log" is the handle of the log file.
+void POCDLL_API TestRegistry(HANDLE log);
+
+// Records all keystrokes typed for 15 seconds and then display them.
+// "log" is the handle of the log file.
+void POCDLL_API TestSpyKeys(HANDLE log);
+
+// Tries to read pixels on the monitor and output if the operation
+// failes or succeeded.
+// "log" is the handle of the log file.
+void POCDLL_API TestSpyScreen(HANDLE log);
+
+// Runs all tests except those who are invasive
+void POCDLL_API Run(HANDLE log);
+}
+
+#endif // SANDBOX_SANDBOX_POC_POCDLL_EXPORTS_H__
diff --git a/sandbox/win/sandbox_poc/pocdll/fs.cc b/sandbox/win/sandbox_poc/pocdll/fs.cc
new file mode 100644
index 0000000000..40596af6dd
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/fs.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify the security of the file system.
+
+// Tries to open a file and outputs the result.
+// "path" can contain environment variables.
+// "output" is the stream for the logging.
+void TryOpenFile(const wchar_t *path, FILE *output) {
+ wchar_t path_expanded[MAX_PATH] = {0};
+ DWORD size = ::ExpandEnvironmentStrings(path, path_expanded, MAX_PATH - 1);
+ if (!size) {
+ fprintf(output, "[ERROR] Cannot expand \"%S\". Error %ld.\r\n", path,
+ ::GetLastError());
+ }
+
+ HANDLE file;
+ file = ::CreateFile(path_expanded,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, // No security attributes
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL); // No template
+
+ if (file && INVALID_HANDLE_VALUE != file) {
+ fprintf(output, "[GRANTED] Opening file \"%S\". Handle 0x%p\r\n", path,
+ file);
+ ::CloseHandle(file);
+ } else {
+ fprintf(output, "[BLOCKED] Opening file \"%S\". Error %ld.\r\n", path,
+ ::GetLastError());
+ }
+}
+
+void POCDLL_API TestFileSystem(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ TryOpenFile(L"%SystemDrive%", output);
+ TryOpenFile(L"%SystemRoot%", output);
+ TryOpenFile(L"%ProgramFiles%", output);
+ TryOpenFile(L"%SystemRoot%\\System32", output);
+ TryOpenFile(L"%SystemRoot%\\explorer.exe", output);
+ TryOpenFile(L"%SystemRoot%\\Cursors\\arrow_i.cur", output);
+ TryOpenFile(L"%AllUsersProfile%", output);
+ TryOpenFile(L"%UserProfile%", output);
+ TryOpenFile(L"%Temp%", output);
+ TryOpenFile(L"%AppData%", output);
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/handles.cc b/sandbox/win/sandbox_poc/pocdll/handles.cc
new file mode 100644
index 0000000000..a12d433411
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/handles.cc
@@ -0,0 +1,186 @@
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+#include "sandbox/win/tools/finder/ntundoc.h"
+
+// This file contains the tests used to verify the security of handles in
+// the process
+
+NTQUERYOBJECT NtQueryObject;
+NTQUERYINFORMATIONFILE NtQueryInformationFile;
+NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
+
+void POCDLL_API TestGetHandle(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ // Initialize the NTAPI functions we need
+ HMODULE ntdll_handle = ::GetModuleHandle(L"ntdll.dll");
+ if (!ntdll_handle) {
+ fprintf(output, "[ERROR] Cannot load ntdll.dll. Error %ld\r\n",
+ ::GetLastError());
+ return;
+ }
+
+ NtQueryObject = reinterpret_cast<NTQUERYOBJECT>(
+ GetProcAddress(ntdll_handle, "NtQueryObject"));
+ NtQueryInformationFile = reinterpret_cast<NTQUERYINFORMATIONFILE>(
+ GetProcAddress(ntdll_handle, "NtQueryInformationFile"));
+ NtQuerySystemInformation = reinterpret_cast<NTQUERYSYSTEMINFORMATION>(
+ GetProcAddress(ntdll_handle, "NtQuerySystemInformation"));
+
+ if (!NtQueryObject || !NtQueryInformationFile || !NtQuerySystemInformation) {
+ fprintf(output, "[ERROR] Cannot load all NT functions. Error %ld\r\n",
+ ::GetLastError());
+ return;
+ }
+
+ // Get the number of handles on the system
+ DWORD buffer_size = 0;
+ SYSTEM_HANDLE_INFORMATION_EX temp_info;
+ NTSTATUS status = NtQuerySystemInformation(
+ SystemHandleInformation, &temp_info, sizeof(temp_info),
+ &buffer_size);
+ if (!buffer_size) {
+ fprintf(output, "[ERROR] Get the number of handles. Error 0x%lX\r\n",
+ status);
+ return;
+ }
+
+ SYSTEM_HANDLE_INFORMATION_EX *system_handles =
+ reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(new BYTE[buffer_size]);
+
+ status = NtQuerySystemInformation(SystemHandleInformation, system_handles,
+ buffer_size, &buffer_size);
+ if (STATUS_SUCCESS != status) {
+ fprintf(output, "[ERROR] Failed to get the handle list. Error 0x%lX\r\n",
+ status);
+ delete [] system_handles;
+ return;
+ }
+
+ for (ULONG i = 0; i < system_handles->NumberOfHandles; ++i) {
+ USHORT h = system_handles->Information[i].Handle;
+ if (system_handles->Information[i].ProcessId != ::GetCurrentProcessId())
+ continue;
+
+ OBJECT_NAME_INFORMATION *name = NULL;
+ ULONG name_size = 0;
+ // Query the name information a first time to get the size of the name.
+ status = NtQueryObject(reinterpret_cast<HANDLE>(h),
+ ObjectNameInformation,
+ name,
+ name_size,
+ &name_size);
+
+ if (name_size) {
+ name = reinterpret_cast<OBJECT_NAME_INFORMATION *>(new BYTE[name_size]);
+
+ // Query the name information a second time to get the name of the
+ // object referenced by the handle.
+ status = NtQueryObject(reinterpret_cast<HANDLE>(h),
+ ObjectNameInformation,
+ name,
+ name_size,
+ &name_size);
+ }
+
+ PUBLIC_OBJECT_TYPE_INFORMATION *type = NULL;
+ ULONG type_size = 0;
+
+ // Query the object to get the size of the object type name.
+ status = NtQueryObject(reinterpret_cast<HANDLE>(h),
+ ObjectTypeInformation,
+ type,
+ type_size,
+ &type_size);
+ if (type_size) {
+ type = reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION *>(
+ new BYTE[type_size]);
+
+ // Query the type information a second time to get the object type
+ // name.
+ status = NtQueryObject(reinterpret_cast<HANDLE>(h),
+ ObjectTypeInformation,
+ type,
+ type_size,
+ &type_size);
+ }
+
+ // NtQueryObject cannot return the name for a file. In this case we
+ // need to ask NtQueryInformationFile
+ FILE_NAME_INFORMATION *file_name = NULL;
+ if (type && wcsncmp(L"File", type->TypeName.Buffer,
+ (type->TypeName.Length /
+ sizeof(type->TypeName.Buffer[0]))) == 0) {
+ // This function does not return the size of the buffer. We need to
+ // iterate and always increase the buffer size until the function
+ // succeeds. (Or at least does not fail with STATUS_BUFFER_OVERFLOW)
+ ULONG size_file = MAX_PATH;
+ IO_STATUS_BLOCK status_block = {0};
+ do {
+ // Delete the previous buffer create. The buffer was too small
+ if (file_name) {
+ delete[] reinterpret_cast<BYTE*>(file_name);
+ file_name = NULL;
+ }
+
+ // Increase the buffer and do the call agan
+ size_file += MAX_PATH;
+ file_name = reinterpret_cast<FILE_NAME_INFORMATION *>(
+ new BYTE[size_file]);
+ status = NtQueryInformationFile(reinterpret_cast<HANDLE>(h),
+ &status_block,
+ file_name,
+ size_file,
+ FileNameInformation);
+ } while (status == STATUS_BUFFER_OVERFLOW);
+
+ if (STATUS_SUCCESS != status) {
+ if (file_name) {
+ delete[] file_name;
+ file_name = NULL;
+ }
+ }
+ }
+
+ if (file_name) {
+ UNICODE_STRING file_name_string;
+ file_name_string.Buffer = file_name->FileName;
+ file_name_string.Length = (USHORT)file_name->FileNameLength;
+ file_name_string.MaximumLength = (USHORT)file_name->FileNameLength;
+ fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8lX "
+ "Type: %-13wZ Path: %wZ\r\n",
+ h,
+ system_handles->Information[i].GrantedAccess,
+ type ? &type->TypeName : NULL,
+ &file_name_string);
+ } else {
+ fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8lX "
+ "Type: %-13wZ Path: %wZ\r\n",
+ h,
+ system_handles->Information[i].GrantedAccess,
+ type ? &type->TypeName : NULL,
+ name ? &name->ObjectName : NULL);
+ }
+
+ if (type) {
+ delete[] type;
+ }
+
+ if (file_name) {
+ delete[] file_name;
+ }
+
+ if (name) {
+ delete [] name;
+ }
+ }
+
+ if (system_handles) {
+ delete [] system_handles;
+ }
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/invasive.cc b/sandbox/win/sandbox_poc/pocdll/invasive.cc
new file mode 100644
index 0000000000..9ee13b0cb9
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/invasive.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <malloc.h>
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify if it's possible to DOS or crash
+// the machine. All tests that can impact the stability of the machine should
+// be in this file.
+
+// Sleeps forever. this function is used to be the
+// entry point for the threads created by the thread bombing function.
+// This function never returns.
+DWORD WINAPI MyThreadBombimgFunction(void *param) {
+ UNREFERENCED_PARAMETER(param);
+ Sleep(INFINITE);
+ return 0;
+}
+
+void POCDLL_API TestThreadBombing(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ // we stop after 5 errors in a row
+ int number_errors = 0;
+ for (int i = 0; i < 100000; ++i) {
+ DWORD tid;
+ // Create the thread and leak the handle.
+ HANDLE thread = ::CreateThread(NULL, // Default security attributes
+ NULL, // Stack size
+ MyThreadBombimgFunction,
+ NULL, // Parameter
+ 0, // No creation flags
+ &tid);
+ if (thread) {
+ fprintf(output, "[GRANTED] Creating thread with tid 0x%lX\r\n", tid);
+ ::CloseHandle(thread);
+ number_errors = 0;
+ } else {
+ fprintf(output, "[BLOCKED] Creating thread. Error %ld\r\n",
+ ::GetLastError());
+ number_errors++;
+ }
+
+ if (number_errors >= 5) {
+ break;
+ }
+ }
+}
+
+
+// Executes a complex mathematical operation forever in a loop. This function
+// is used as entry point for the threads created by TestTakeAllCpu. It it
+// designed to take all CPU on the processor where the thread is running.
+// The return value is always 0.
+DWORD WINAPI TakeAllCpu(void *param) {
+ UNREFERENCED_PARAMETER(param);
+ int cpt = 0;
+ for (;;) {
+ cpt += 2;
+ cpt /= 2;
+ cpt *= cpt;
+ cpt = cpt % 100;
+ cpt = cpt | (cpt * cpt);
+ }
+}
+
+void POCDLL_API TestTakeAllCpu(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ DWORD_PTR process_mask = 0;
+ DWORD_PTR system_mask = 0;
+ if (::GetProcessAffinityMask(::GetCurrentProcess(),
+ &process_mask,
+ &system_mask)) {
+ DWORD_PTR affinity_mask = 1;
+
+ while (system_mask) {
+ DWORD tid = 0;
+
+ HANDLE thread = ::CreateThread(NULL, // Default security attributes.
+ NULL, // Stack size.
+ TakeAllCpu,
+ NULL, // Parameter.
+ 0, // No creation flags.
+ &tid);
+ ::SetThreadAffinityMask(thread, affinity_mask);
+
+ if (::SetThreadPriority(thread, REALTIME_PRIORITY_CLASS)) {
+ fprintf(output, "[GRANTED] Set thread(%ld) priority to Realtime\r\n",
+ tid);
+ } else {
+ fprintf(output, "[BLOCKED] Set thread(%ld) priority to Realtime\r\n",
+ tid);
+ }
+
+ ::CloseHandle(thread);
+
+ affinity_mask = affinity_mask << 1;
+ system_mask = system_mask >> 1;
+ }
+ } else {
+ fprintf(output, "[ERROR] Cannot get affinity mask. Error %ld\r\n",
+ ::GetLastError());
+ }
+}
+
+void POCDLL_API TestUseAllMemory(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ int number_errors = 0;
+ unsigned long memory_size = 0;
+ for (;;) {
+ DWORD *ptr_to_leak = reinterpret_cast<DWORD *>(malloc(1024*256));
+ if (ptr_to_leak) {
+ memory_size += (256);
+ number_errors = 0;
+ } else {
+ number_errors++;
+ }
+
+ // check if we have more than 5 errors in a row. If so, quit.
+ if (number_errors >= 5) {
+ fprintf(output, "[INFO] Created %lu kb of memory\r\n", memory_size);
+ return;
+ }
+
+ Sleep(5); // 5ms to be able to see the progression easily with taskmgr.
+ }
+}
+
+void POCDLL_API TestCreateObjects(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ int mutexes = 0;
+ int jobs = 0;
+ int events = 0;
+ for (int i = 0; i < 1000000; ++i) {
+ if (::CreateMutex(NULL, // Default security attributes.
+ TRUE, // We are the initial owner.
+ NULL)) { // No name.
+ mutexes++;
+ }
+
+ if (::CreateJobObject(NULL, // Default security attributes.
+ NULL)) { // No name.
+ jobs++;
+ }
+
+ if (::CreateEvent(NULL, // Default security attributes.
+ TRUE, // Manual Reset.
+ TRUE, // Object is signaled.
+ NULL)) { // No name.
+ events++;
+ }
+ }
+
+ fprintf(output, "[GRANTED] Created %d mutexes, %d jobs and %d events for "
+ "a total of %d objects out of 3 000 000\r\n", mutexes, jobs,
+ events, mutexes + jobs + events);
+}
+
+BOOL CALLBACK EnumWindowCallback(HWND hwnd, LPARAM output) {
+ DWORD pid;
+ ::GetWindowThreadProcessId(hwnd, &pid);
+ if (pid != ::GetCurrentProcessId()) {
+ wchar_t window_title[100 + 1] = {0};
+ ::GetWindowText(hwnd, window_title, 100);
+ fprintf(reinterpret_cast<FILE*>(output),
+ "[GRANTED] Found window 0x%p with title %S\r\n",
+ hwnd,
+ window_title);
+ ::CloseWindow(hwnd);
+ }
+
+ return TRUE;
+}
+
+// Enumerates all the windows on the system and call the function to try to
+// close them. The goal of this function is to try to kill the system by
+// closing all windows.
+// "output" is the stream used for logging.
+void POCDLL_API TestCloseHWND(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ ::EnumWindows(EnumWindowCallback, PtrToLong(output));
+ // TODO(nsylvain): find a way to know when the enum is finished
+ // before returning.
+ ::Sleep(3000);
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/network.cc b/sandbox/win/sandbox_poc/pocdll/network.cc
new file mode 100644
index 0000000000..56ab5aefb0
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/network.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify the security of the network.
+
+void POCDLL_API TestNetworkListen(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+#if DONT_WANT_INTERCEPTIONS_JUST_WANT_NETWORK
+ // Initialize Winsock
+ WSADATA wsa_data;
+ int result = ::WSAStartup(MAKEWORD(2, 2), &wsa_data);
+ if (result != NO_ERROR) {
+ fprintf(output, "[ERROR] Cannot initialize winsock. Error%d\r\n", result);
+ return;
+ }
+
+ // Create a SOCKET for listening for
+ // incoming connection requests.
+ SOCKET listen_socket;
+ listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listen_socket == INVALID_SOCKET) {
+ fprintf(output, "[ERROR] Failed to create socket. Error %ld\r\n",
+ ::WSAGetLastError());
+ ::WSACleanup();
+ return;
+ }
+
+ // The sockaddr_in structure specifies the address family,
+ // IP address, and port for the socket that is being bound.
+ sockaddr_in service;
+ service.sin_family = AF_INET;
+ service.sin_addr.s_addr = inet_addr("127.0.0.1");
+ service.sin_port = htons(88);
+
+ if (bind(listen_socket, reinterpret_cast<SOCKADDR*>(&service),
+ sizeof(service)) == SOCKET_ERROR) {
+ fprintf(output, "[BLOCKED] Bind socket on port 88. Error %ld\r\n",
+ ::WSAGetLastError());
+ closesocket(listen_socket);
+ ::WSACleanup();
+ return;
+ }
+
+ // Listen for incoming connection requests
+ // on the created socket
+ if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
+ fprintf(output, "[BLOCKED] Listen socket on port 88. Error %ld\r\n",
+ ::WSAGetLastError());
+
+ } else {
+ fprintf(output, "[GRANTED] Listen socket on port 88.\r\n",
+ ::WSAGetLastError());
+ }
+
+ ::WSACleanup();
+ return;
+#else // DONT_WANT_INTERCEPTIONS_JUST_WANT_NETWORK
+ // Just print out that this test is not running.
+ fprintf(output, "[ERROR] No network tests.\r\n");
+#endif // DONT_WANT_INTERCEPTIONS_JUST_WANT_NETWORK
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/pocdll.cc b/sandbox/win/sandbox_poc/pocdll/pocdll.cc
new file mode 100644
index 0000000000..e058f58b82
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/pocdll.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+BOOL APIENTRY DllMain(HMODULE module,
+ DWORD reason_for_call,
+ LPVOID reserved) {
+ UNREFERENCED_PARAMETER(module);
+ UNREFERENCED_PARAMETER(reason_for_call);
+ UNREFERENCED_PARAMETER(reserved);
+ return TRUE;
+}
+
+void POCDLL_API Run(HANDLE log) {
+ TestFileSystem(log);
+ TestRegistry(log);
+ TestNetworkListen(log);
+ TestSpyScreen(log);
+ TestSpyKeys(log);
+ TestThreads(log);
+ TestProcesses(log);
+ TestGetHandle(log);
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/pocdll.vcproj b/sandbox/win/sandbox_poc/pocdll/pocdll.vcproj
new file mode 100644
index 0000000000..8e4e31fc6a
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/pocdll.vcproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="pocdll"
+ ProjectGUID="{AE5BFB87-850E-4454-B01D-58E7D8BAC224}"
+ RootNamespace="pocdll"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="POCDLL_EXPORTS"
+ UsePrecompiledHeader="2"
+ ForcedIncludeFiles="stdafx.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ ModuleDefinitionFile=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="POCDLL_EXPORTS"
+ UsePrecompiledHeader="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ ModuleDefinitionFile=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\exports.h"
+ >
+ </File>
+ <File
+ RelativePath=".\fs.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\handles.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\invasive.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\network.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\pocdll.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\processes_and_threads.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\registry.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\spyware.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sandbox/win/sandbox_poc/pocdll/processes_and_threads.cc b/sandbox/win/sandbox_poc/pocdll/processes_and_threads.cc
new file mode 100644
index 0000000000..03e12ba522
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/processes_and_threads.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <Tlhelp32.h>
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify the security of threads and
+// processes.
+
+void POCDLL_API TestProcesses(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
+ if (INVALID_HANDLE_VALUE == snapshot) {
+ fprintf(output, "[BLOCKED] Cannot list all processes on the system. "
+ "Error %ld\r\n", ::GetLastError());
+ return;
+ }
+
+ PROCESSENTRY32 process_entry = {0};
+ process_entry.dwSize = sizeof(PROCESSENTRY32);
+
+ BOOL result = ::Process32First(snapshot, &process_entry);
+
+ while (result) {
+ HANDLE process = ::OpenProcess(PROCESS_VM_READ,
+ FALSE, // Do not inherit handle.
+ process_entry.th32ProcessID);
+ if (NULL == process) {
+ fprintf(output, "[BLOCKED] Found process %S:%ld but cannot open it. "
+ "Error %ld\r\n",
+ process_entry.szExeFile,
+ process_entry.th32ProcessID,
+ ::GetLastError());
+ } else {
+ fprintf(output, "[GRANTED] Found process %S:%ld and open succeeded.\r\n",
+ process_entry.szExeFile, process_entry.th32ProcessID);
+ ::CloseHandle(process);
+ }
+
+ result = ::Process32Next(snapshot, &process_entry);
+ }
+
+ DWORD err_code = ::GetLastError();
+ if (ERROR_NO_MORE_FILES != err_code) {
+ fprintf(output, "[ERROR] Error %ld while looking at the processes on "
+ "the system\r\n", err_code);
+ }
+
+ ::CloseHandle(snapshot);
+}
+
+void POCDLL_API TestThreads(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL);
+ if (INVALID_HANDLE_VALUE == snapshot) {
+ fprintf(output, "[BLOCKED] Cannot list all threads on the system. "
+ "Error %ld\r\n", ::GetLastError());
+ return;
+ }
+
+ THREADENTRY32 thread_entry = {0};
+ thread_entry.dwSize = sizeof(THREADENTRY32);
+
+ BOOL result = ::Thread32First(snapshot, &thread_entry);
+ int nb_success = 0;
+ int nb_failure = 0;
+
+ while (result) {
+ HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
+ FALSE, // Do not inherit handles.
+ thread_entry.th32ThreadID);
+ if (NULL == thread) {
+ nb_failure++;
+ } else {
+ nb_success++;
+ fprintf(output, "[GRANTED] Found thread %ld:%ld and able to open it.\r\n",
+ thread_entry.th32OwnerProcessID,
+ thread_entry.th32ThreadID);
+ ::CloseHandle(thread);
+ }
+
+ result = Thread32Next(snapshot, &thread_entry);
+ }
+
+ DWORD err_code = ::GetLastError();
+ if (ERROR_NO_MORE_FILES != err_code) {
+ fprintf(output, "[ERROR] Error %ld while looking at the processes on "
+ "the system\r\n", err_code);
+ }
+
+ fprintf(output, "[INFO] Found %d threads. Able to open %d of them\r\n",
+ nb_success + nb_failure, nb_success);
+
+ ::CloseHandle(snapshot);
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/registry.cc b/sandbox/win/sandbox_poc/pocdll/registry.cc
new file mode 100644
index 0000000000..5784db65d0
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/registry.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify the security of the registry.
+
+// Tries to open the key hive\path and outputs the result.
+// "output" is the stream used for logging.
+void TryOpenKey(const HKEY hive,
+ const wchar_t* hive_name,
+ const wchar_t* path,
+ FILE* output) {
+ HKEY key;
+ LONG err_code = ::RegOpenKeyEx(hive,
+ path,
+ 0, // Reserved, must be 0.
+ MAXIMUM_ALLOWED,
+ &key);
+ if (ERROR_SUCCESS == err_code) {
+ fprintf(output,
+ "[GRANTED] Opening key \"%S\\%S\". Handle 0x%p\r\n",
+ hive_name,
+ path,
+ key);
+ ::RegCloseKey(key);
+ } else {
+ fprintf(output,
+ "[BLOCKED] Opening key \"%S\\%S\". Error %ld\r\n",
+ hive_name,
+ path,
+ err_code);
+ }
+}
+
+void POCDLL_API TestRegistry(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ TryOpenKey(HKEY_LOCAL_MACHINE, L"HKEY_LOCAL_MACHINE", NULL, output);
+ TryOpenKey(HKEY_CURRENT_USER, L"HKEY_CURRENT_USER", NULL, output);
+ TryOpenKey(HKEY_USERS, L"HKEY_USERS", NULL, output);
+ TryOpenKey(HKEY_LOCAL_MACHINE,
+ L"HKEY_LOCAL_MACHINE",
+ L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
+ output);
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/spyware.cc b/sandbox/win/sandbox_poc/pocdll/spyware.cc
new file mode 100644
index 0000000000..cf0bd4177f
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/spyware.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/strings/string16.h"
+#include "sandbox/win/sandbox_poc/pocdll/exports.h"
+#include "sandbox/win/sandbox_poc/pocdll/utils.h"
+
+// This file contains the tests used to verify the security of the system by
+// using some spying techniques.
+
+void POCDLL_API TestSpyKeys(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ if (RegisterHotKey(NULL, 1, 0, 0x42)) {
+ fprintf(output, "[GRANTED] successfully registered hotkey\r\n");
+ UnregisterHotKey(NULL, 1);
+ } else {
+ fprintf(output, "[BLOCKED] Failed to register hotkey. Error = %ld\r\n",
+ ::GetLastError());
+ }
+
+ fprintf(output, "[INFO] Logging keystrokes for 15 seconds\r\n");
+ fflush(output);
+ base::string16 logged;
+ DWORD tick = ::GetTickCount() + 15000;
+ while (tick > ::GetTickCount()) {
+ for (int i = 0; i < 256; ++i) {
+ if (::GetAsyncKeyState(i) & 1) {
+ if (i >= VK_SPACE && i <= 0x5A /*VK_Z*/) {
+ logged.append(1, static_cast<wchar_t>(i));
+ } else {
+ logged.append(1, '?');
+ }
+ }
+ }
+ }
+
+ if (logged.size()) {
+ fprintf(output, "[GRANTED] Spyed keystrokes \"%S\"\r\n",
+ logged.c_str());
+ } else {
+ fprintf(output, "[BLOCKED] Spyed keystrokes \"(null)\"\r\n");
+ }
+}
+
+void POCDLL_API TestSpyScreen(HANDLE log) {
+ HandleToFile handle2file;
+ FILE *output = handle2file.Translate(log, "w");
+
+ HDC screen_dc = ::GetDC(NULL);
+ COLORREF pixel_color = ::GetPixel(screen_dc, 0, 0);
+
+ for (int x = 0; x < 10; ++x) {
+ for (int y = 0; y < 10; ++y) {
+ if (::GetPixel(screen_dc, x, y) != pixel_color) {
+ fprintf(output, "[GRANTED] Read pixel on screen\r\n");
+ return;
+ }
+ }
+ }
+
+ fprintf(output, "[BLOCKED] Read pixel on screen. Error = %ld\r\n",
+ ::GetLastError());
+}
diff --git a/sandbox/win/sandbox_poc/pocdll/utils.h b/sandbox/win/sandbox_poc/pocdll/utils.h
new file mode 100644
index 0000000000..ae4286147a
--- /dev/null
+++ b/sandbox/win/sandbox_poc/pocdll/utils.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__
+#define SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__
+
+#include <stdio.h>
+#include <io.h>
+#include "base/basictypes.h"
+
+// Class to convert a HANDLE to a FILE *. The FILE * is closed when the
+// object goes out of scope
+class HandleToFile {
+ public:
+ HandleToFile() {
+ file_ = NULL;
+ };
+
+ // Note: c_file_handle_ does not need to be closed because fclose does it.
+ ~HandleToFile() {
+ if (file_) {
+ fflush(file_);
+ fclose(file_);
+ }
+ };
+
+ // Translates a HANDLE (handle) to a FILE * opened with the mode "mode".
+ // The return value is the FILE * or NULL if there is an error.
+ FILE* Translate(HANDLE handle, const char *mode) {
+ if (file_) {
+ return NULL;
+ }
+
+ HANDLE new_handle;
+ BOOL result = ::DuplicateHandle(::GetCurrentProcess(),
+ handle,
+ ::GetCurrentProcess(),
+ &new_handle,
+ 0, // Don't ask for a specific
+ // desired access.
+ FALSE, // Not inheritable.
+ DUPLICATE_SAME_ACCESS);
+
+ if (!result) {
+ return NULL;
+ }
+
+ int c_file_handle = _open_osfhandle(reinterpret_cast<LONG_PTR>(new_handle),
+ 0); // No flags
+ if (-1 == c_file_handle) {
+ return NULL;
+ }
+
+ file_ = _fdopen(c_file_handle, mode);
+ return file_;
+ };
+ private:
+ // the FILE* returned. We need to closed it at the end.
+ FILE* file_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandleToFile);
+};
+
+#endif // SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__
diff --git a/sandbox/win/sandbox_poc/resource.h b/sandbox/win/sandbox_poc/resource.h
new file mode 100644
index 0000000000..87ff920ca4
--- /dev/null
+++ b/sandbox/win/sandbox_poc/resource.h
@@ -0,0 +1,30 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by sandbox.rc
+//
+#define IDI_SANDBOX 107
+#define IDR_MENU_MAIN_UI 129
+#define IDD_LAUNCH_DLL 130
+#define IDC_RADIO_POCDLL 1000
+#define IDC_RADIO_CUSTOM_DLL 1001
+#define IDC_DLL_NAME 1002
+#define IDC_ENTRY_POINT 1003
+#define IDC_LOG_FILE 1004
+#define IDC_BROWSE_DLL 1005
+#define IDC_BROWSE_LOG 1006
+#define ID_FILE_EXIT 32771
+#define ID_COMMANDS_LAUNCHDLL 32772
+#define ID_COMMANDS_SPAWNTARGET 32773
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 131
+#define _APS_NEXT_COMMAND_VALUE 32774
+#define _APS_NEXT_CONTROL_VALUE 1007
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/sandbox/win/sandbox_poc/sandbox.cc b/sandbox/win/sandbox_poc/sandbox.cc
new file mode 100644
index 0000000000..e282075321
--- /dev/null
+++ b/sandbox/win/sandbox_poc/sandbox.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <tchar.h>
+#include <shellapi.h>
+#include "sandbox/win/sandbox_poc/sandbox.h"
+#include "base/logging.h"
+#include "sandbox/win/sandbox_poc/main_ui_window.h"
+#include "sandbox/win/src/sandbox.h"
+#include "sandbox/win/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,
+ base::string16 * 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;
+ }
+
+ base::string16 entry_point_wide = arg_list[1];
+ base::string16 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;
+ base::string16 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;
+ }
+
+ // 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;
+ }
+
+ // Initialization is finished, so we can enter lock-down mode
+ target_service->LowerToken();
+
+ 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;
+}
diff --git a/sandbox/win/sandbox_poc/sandbox.h b/sandbox/win/sandbox_poc/sandbox.h
new file mode 100644
index 0000000000..65c09a119f
--- /dev/null
+++ b/sandbox/win/sandbox_poc/sandbox.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SANDBOX_POC_SANDBOX_H__
+#define SANDBOX_SANDBOX_POC_SANDBOX_H__
+
+#include "sandbox/win/sandbox_poc/resource.h"
+
+#endif // SANDBOX_SANDBOX_POC_SANDBOX_H__
diff --git a/sandbox/win/sandbox_poc/sandbox.ico b/sandbox/win/sandbox_poc/sandbox.ico
new file mode 100644
index 0000000000..916fa12fc2
--- /dev/null
+++ b/sandbox/win/sandbox_poc/sandbox.ico
Binary files differ
diff --git a/sandbox/win/sandbox_poc/sandbox.rc b/sandbox/win/sandbox_poc/sandbox.rc
new file mode 100644
index 0000000000..978c96f6f2
--- /dev/null
+++ b/sandbox/win/sandbox_poc/sandbox.rc
@@ -0,0 +1,136 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU_MAIN_UI MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", ID_FILE_EXIT
+ END
+ POPUP "&Commands"
+ BEGIN
+ MENUITEM "&Spawn target", ID_COMMANDS_SPAWNTARGET
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_LAUNCH_DLL DIALOGEX 0, 0, 269, 118
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "BrokerUI: Load an Attack DLL"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Call now",IDOK,212,70,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,212,95,50,14
+ EDITTEXT IDC_DLL_NAME,7,43,200,13,ES_AUTOHSCROLL
+ LTEXT "DLL to load in target:",IDC_STATIC,7,33,168,8
+ LTEXT "Function to call:",IDC_STATIC,7,61,139,8
+ EDITTEXT IDC_ENTRY_POINT,7,71,200,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_LOG_FILE,7,17,200,13,ES_AUTOHSCROLL
+ LTEXT "File for Target logging (optional):",IDC_STATIC,7,7,139,8
+ PUSHBUTTON "Browse...",IDC_BROWSE_DLL,212,42,50,14
+ PUSHBUTTON "Browse...",IDC_BROWSE_LOG,212,16,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_LAUNCH_DLL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 262
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 111
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SANDBOX ICON "sandbox.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/sandbox/win/sandbox_poc/sandbox_poc.vcproj b/sandbox/win/sandbox_poc/sandbox_poc.vcproj
new file mode 100644
index 0000000000..5fde1cd407
--- /dev/null
+++ b/sandbox/win/sandbox_poc/sandbox_poc.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sandbox_poc"
+ ProjectGUID="{CF757839-F2A1-417C-8F25-DCAE480020F1}"
+ RootNamespace="sandbox_poc"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="2"
+ ForcedIncludeFiles="stdafx.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\main_ui_window.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\main_ui_window.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\sandbox.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\sandbox.h"
+ >
+ </File>
+ <File
+ RelativePath=".\sandbox.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\sandbox.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>