From a814a8d55429605fe6d7045045cd25b6bf624580 Mon Sep 17 00:00:00 2001 From: "initial.commit" Date: Sat, 26 Jul 2008 22:41:28 +0000 Subject: Add sandbox to the repository. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13 0039d316-1c4b-4281-b951-d872f2087c98 --- sandbox/sandbox_poc/main_ui_window.cc | 694 +++++++++++++++++++++ sandbox/sandbox_poc/main_ui_window.h | 218 +++++++ sandbox/sandbox_poc/pocdll/exports.h | 114 ++++ sandbox/sandbox_poc/pocdll/fs.cc | 79 +++ sandbox/sandbox_poc/pocdll/handles.cc | 216 +++++++ sandbox/sandbox_poc/pocdll/invasive.cc | 219 +++++++ sandbox/sandbox_poc/pocdll/network.cc | 91 +++ sandbox/sandbox_poc/pocdll/pocdll.cc | 52 ++ sandbox/sandbox_poc/pocdll/pocdll.vcproj | 218 +++++++ .../sandbox_poc/pocdll/processes_and_threads.cc | 127 ++++ sandbox/sandbox_poc/pocdll/registry.cc | 88 +++ sandbox/sandbox_poc/pocdll/spyware.cc | 83 +++ sandbox/sandbox_poc/pocdll/stdafx.cc | 33 + sandbox/sandbox_poc/pocdll/stdafx.h | 37 ++ sandbox/sandbox_poc/pocdll/utils.h | 90 +++ sandbox/sandbox_poc/resource.h | 30 + sandbox/sandbox_poc/sandbox.cc | 207 ++++++ sandbox/sandbox_poc/sandbox.h | 35 ++ sandbox/sandbox_poc/sandbox.ico | Bin 0 -> 1078 bytes sandbox/sandbox_poc/sandbox.rc | 136 ++++ sandbox/sandbox_poc/sandbox_poc.vcproj | 202 ++++++ sandbox/sandbox_poc/stdafx.cc | 30 + sandbox/sandbox_poc/stdafx.h | 43 ++ 23 files changed, 3042 insertions(+) create mode 100644 sandbox/sandbox_poc/main_ui_window.cc create mode 100644 sandbox/sandbox_poc/main_ui_window.h create mode 100644 sandbox/sandbox_poc/pocdll/exports.h create mode 100644 sandbox/sandbox_poc/pocdll/fs.cc create mode 100644 sandbox/sandbox_poc/pocdll/handles.cc create mode 100644 sandbox/sandbox_poc/pocdll/invasive.cc create mode 100644 sandbox/sandbox_poc/pocdll/network.cc create mode 100644 sandbox/sandbox_poc/pocdll/pocdll.cc create mode 100644 sandbox/sandbox_poc/pocdll/pocdll.vcproj create mode 100644 sandbox/sandbox_poc/pocdll/processes_and_threads.cc create mode 100644 sandbox/sandbox_poc/pocdll/registry.cc create mode 100644 sandbox/sandbox_poc/pocdll/spyware.cc create mode 100644 sandbox/sandbox_poc/pocdll/stdafx.cc create mode 100644 sandbox/sandbox_poc/pocdll/stdafx.h create mode 100644 sandbox/sandbox_poc/pocdll/utils.h create mode 100644 sandbox/sandbox_poc/resource.h create mode 100644 sandbox/sandbox_poc/sandbox.cc create mode 100644 sandbox/sandbox_poc/sandbox.h create mode 100644 sandbox/sandbox_poc/sandbox.ico create mode 100644 sandbox/sandbox_poc/sandbox.rc create mode 100644 sandbox/sandbox_poc/sandbox_poc.vcproj create mode 100644 sandbox/sandbox_poc/stdafx.cc create mode 100644 sandbox/sandbox_poc/stdafx.h (limited to 'sandbox/sandbox_poc') diff --git a/sandbox/sandbox_poc/main_ui_window.cc b/sandbox/sandbox_poc/main_ui_window.cc new file mode 100644 index 0000000..fdef50d --- /dev/null +++ b/sandbox/sandbox_poc/main_ui_window.cc @@ -0,0 +1,694 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sandbox/sandbox_poc/main_ui_window.h" +#include "base/logging.h" +#include "sandbox/sandbox_poc/resource.h" +#include "sandbox/src/acl.h" +#include "sandbox/src/sandbox.h" +#include "sandbox/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(); + + ::SetWindowLong(window, + GWL_USERDATA, + static_cast(reinterpret_cast(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)) { + std::wstring dll_path = std::wstring(current_dir) + + std::wstring(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(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(TRUE); + } else if (LOWORD(wparam) == IDCANCEL) { + // If the user presses the Cancel button + ::EndDialog(dialog, LOWORD(wparam)); + return static_cast(TRUE); + } else if (LOWORD(wparam) == IDC_BROWSE_DLL) { + // If the user presses the Browse button to look for a DLL + std::wstring 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(TRUE); + } else if (LOWORD(wparam) == IDC_BROWSE_LOG) { + // If the user presses the Browse button to look for a log file + std::wstring 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(TRUE); + } + + break; + } + + return static_cast(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 + ::GetWindowLong(main_window, GWL_USERDATA); + return reinterpret_cast( + static_cast(::GetWindowLong(main_window, GWL_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_ = std::wstring(L"\"") + log_file + std::wstring(L"\""); + dll_path_ = dll_path; + entry_point_ = entry_point; + + return true; +} + +DWORD WINAPI MainUIWindow::ListenPipeThunk(void *param) { + return reinterpret_cast(param)->ListenPipe(); +} + +DWORD WINAPI MainUIWindow::WaitForTargetThunk(void *param) { + return reinterpret_cast(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 \"%s\" 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(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(size_call), L"%s %s \"%s\" %s", + 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->SetDesktop(L"random_desktop_name"); + 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 %s w/args (%s), 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::AddKnownSidToKernelObject(pipe_handle_, WinWorldSid, + 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 (%s)", arguments); + return_value = true; + } + + delete[] arguments; + return return_value; +} + +std::wstring 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""; +} + +std::wstring 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; + _crt_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/sandbox_poc/main_ui_window.h b/sandbox/sandbox_poc/main_ui_window.h new file mode 100644 index 0000000..63a9545 --- /dev/null +++ b/sandbox/sandbox_poc/main_ui_window.h @@ -0,0 +1,218 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__ +#define SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__ + +#include +#include "base/basictypes.h" + +namespace sandbox { +class BrokerServices; +class SandboxFactory; +class TargetProcess; +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). + std::wstring 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). + std::wstring 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. + std::wstring 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. + std::wstring dll_path_; + + // The name of the entry point the target should call after it loads the DLL. + std::wstring entry_point_; + + // The name of the log file to use. + std::wstring 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_EVIL_CONSTRUCTORS(MainUIWindow); +}; + +#endif // SANDBOX_SANDBOX_POC_MAIN_UI_WINDOW_H__ diff --git a/sandbox/sandbox_poc/pocdll/exports.h b/sandbox/sandbox_poc/pocdll/exports.h new file mode 100644 index 0000000..d73884b --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/exports.h @@ -0,0 +1,114 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_POCDLL_EXPORTS_H__ +#define SANDBOX_SANDBOX_POC_POCDLL_EXPORTS_H__ + +#include + +#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/sandbox_poc/pocdll/fs.cc b/sandbox/sandbox_poc/pocdll/fs.cc new file mode 100644 index 0000000..d9a142f --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/fs.cc @@ -0,0 +1,79 @@ +// 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 "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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(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 %S.\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 %d.\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/sandbox_poc/pocdll/handles.cc b/sandbox/sandbox_poc/pocdll/handles.cc new file mode 100644 index 0000000..eb63dab --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/handles.cc @@ -0,0 +1,216 @@ +// 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 "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/sandbox_poc/pocdll/utils.h" +#include "sandbox/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 = ::LoadLibraryA("ntdll.dll"); + if (!ntdll_handle) { + fprintf(output, "[ERROR] Cannot load ntdll.dll. Error %d\r\n", + ::GetLastError()); + return; + } + + NtQueryObject = reinterpret_cast( + GetProcAddress(ntdll_handle, "NtQueryObject")); + NtQueryInformationFile = reinterpret_cast( + GetProcAddress(ntdll_handle, "NtQueryInformationFile")); + NtQuerySystemInformation = reinterpret_cast( + GetProcAddress(ntdll_handle, "NtQuerySystemInformation")); + + if (!NtQueryObject || !NtQueryInformationFile || !NtQuerySystemInformation) { + fprintf(output, "[ERROR] Cannot load all NT functions. Error %d\r\n", + ::GetLastError()); + ::FreeLibrary(ntdll_handle); + 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%X\r\n", + status); + ::FreeLibrary(ntdll_handle); + return; + } + + SYSTEM_HANDLE_INFORMATION_EX *system_handles = + reinterpret_cast(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%X\r\n", + status); + ::FreeLibrary(ntdll_handle); + delete [] system_handles; + return; + } + + for (unsigned int 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(h), + ObjectNameInformation, + name, + name_size, + &name_size); + + if (name_size) { + name = reinterpret_cast(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(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(h), + ObjectTypeInformation, + type, + type_size, + &type_size); + if (type_size) { + type = reinterpret_cast( + new BYTE[type_size]); + + // Query the type information a second time to get the object type + // name. + status = NtQueryObject(reinterpret_cast(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) + DWORD size_file = MAX_PATH; + IO_STATUS_BLOCK status_block; + do { + // Delete the previous buffer create. The buffer was too small + if (file_name) { + delete[] reinterpret_cast(file_name); + file_name = NULL; + } + + // Increase the buffer and do the call agan + size_file += MAX_PATH; + file_name = reinterpret_cast( + new BYTE[size_file]); + status = NtQueryInformationFile(reinterpret_cast(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.8X " + "Type: %-13.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.8X " + "Type: %-13.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; + } + + ::FreeLibrary(ntdll_handle); +} diff --git a/sandbox/sandbox_poc/pocdll/invasive.cc b/sandbox/sandbox_poc/pocdll/invasive.cc new file mode 100644 index 0000000..1e225b9 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/invasive.cc @@ -0,0 +1,219 @@ +// 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 +#include "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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%X\r\n", tid); + ::CloseHandle(thread); + number_errors = 0; + } else { + fprintf(output, "[BLOCKED] Creating thread. Error %d\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(%d) priority to Realtime\r\n", + tid); + } else { + fprintf(output, "[BLOCKED] Set thread(%d) 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 %d\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(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(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/sandbox_poc/pocdll/network.cc b/sandbox/sandbox_poc/pocdll/network.cc new file mode 100644 index 0000000..66dbc63 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/network.cc @@ -0,0 +1,91 @@ +// 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 "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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(&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/sandbox_poc/pocdll/pocdll.cc b/sandbox/sandbox_poc/pocdll/pocdll.cc new file mode 100644 index 0000000..3cd21f3 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/pocdll.cc @@ -0,0 +1,52 @@ +// 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 "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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/sandbox_poc/pocdll/pocdll.vcproj b/sandbox/sandbox_poc/pocdll/pocdll.vcproj new file mode 100644 index 0000000..8e4e31f --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/pocdll.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/sandbox_poc/pocdll/processes_and_threads.cc b/sandbox/sandbox_poc/pocdll/processes_and_threads.cc new file mode 100644 index 0000000..a4b3173 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/processes_and_threads.cc @@ -0,0 +1,127 @@ +// 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 +#include +#include "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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 %d\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:%d but cannot open it. " + "Error %d\r\n", + process_entry.szExeFile, + process_entry.th32ProcessID, + ::GetLastError()); + } else { + fprintf(output, "[GRANTED] Found process %S:%d 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 %d 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 %d\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 %d:%d 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 %d 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/sandbox_poc/pocdll/registry.cc b/sandbox/sandbox_poc/pocdll/registry.cc new file mode 100644 index 0000000..6fd3370 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/registry.cc @@ -0,0 +1,88 @@ +// 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 "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/sandbox_poc/pocdll/utils.h" + +// This file contains the tests used to verify the security of the registry. + +// Converts an HKEY to a string. This is using the lazy way and works only +// for the main hives. +// "key" is the hive to convert to string. +// The return value is the string corresponding to the hive or "unknown" +const wchar_t *HKEYToString(const HKEY key) { + switch (reinterpret_cast(key)) { + case HKEY_CLASSES_ROOT: + return L"HKEY_CLASSES_ROOT"; + case HKEY_CURRENT_CONFIG: + return L"HKEY_CURRENT_CONFIG"; + case HKEY_CURRENT_USER: + return L"HKEY_CURRENT_USER"; + case HKEY_LOCAL_MACHINE: + return L"HKEY_LOCAL_MACHINE"; + case HKEY_USERS: + return L"HKEY_USERS"; + } + return L"unknown"; +} + +// 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 *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", + HKEYToString(hive), + path, + key); + ::RegCloseKey(key); + } else { + fprintf(output, "[BLOCKED] Opening key \"%S\\%S\". Error %d\r\n", + HKEYToString(hive), + path, + err_code); + } +} + +void POCDLL_API TestRegistry(HANDLE log) { + HandleToFile handle2file; + FILE *output = handle2file.Translate(log, "w"); + + TryOpenKey(HKEY_LOCAL_MACHINE, NULL, output); + TryOpenKey(HKEY_CURRENT_USER, NULL, output); + TryOpenKey(HKEY_USERS, NULL, output); + TryOpenKey(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon", + output); +} diff --git a/sandbox/sandbox_poc/pocdll/spyware.cc b/sandbox/sandbox_poc/pocdll/spyware.cc new file mode 100644 index 0000000..1226e81 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/spyware.cc @@ -0,0 +1,83 @@ +// 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 +#include "sandbox/sandbox_poc/pocdll/exports.h" +#include "sandbox/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"); + + fprintf(output, "[INFO] Logging keystrokes for 15 seconds\r\n"); + fflush(output); + std::wstring 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(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 = %d\r\n", + ::GetLastError()); +} diff --git a/sandbox/sandbox_poc/pocdll/stdafx.cc b/sandbox/sandbox_poc/pocdll/stdafx.cc new file mode 100644 index 0000000..73f4ea8 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/stdafx.cc @@ -0,0 +1,33 @@ +// 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 "sandbox/sandbox_poc/pocdll/stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/sandbox/sandbox_poc/pocdll/stdafx.h b/sandbox/sandbox_poc/pocdll/stdafx.h new file mode 100644 index 0000000..519e453 --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/stdafx.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_POCDLL_STDAFX_H__ +#define SANDBOX_SANDBOX_POC_POCDLL_STDAFX_H__ + +#include +#include +#include + +#endif // SANDBOX_SANDBOX_POC_POCDLL_STDAFX_H__ diff --git a/sandbox/sandbox_poc/pocdll/utils.h b/sandbox/sandbox_poc/pocdll/utils.h new file mode 100644 index 0000000..c2c257c --- /dev/null +++ b/sandbox/sandbox_poc/pocdll/utils.h @@ -0,0 +1,90 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__ +#define SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__ + +#include +#include +#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(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_EVIL_CONSTRUCTORS(HandleToFile); +}; + +#endif // SANDBOX_SANDBOX_POC_POCDLL_UTILS_H__ diff --git a/sandbox/sandbox_poc/resource.h b/sandbox/sandbox_poc/resource.h new file mode 100644 index 0000000..87ff920 --- /dev/null +++ b/sandbox/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/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 +#include +#include +#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; +} diff --git a/sandbox/sandbox_poc/sandbox.h b/sandbox/sandbox_poc/sandbox.h new file mode 100644 index 0000000..73adf09 --- /dev/null +++ b/sandbox/sandbox_poc/sandbox.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_SANDBOX_H__ +#define SANDBOX_SANDBOX_POC_SANDBOX_H__ + +#include "sandbox/sandbox_poc/resource.h" + +#endif // SANDBOX_SANDBOX_POC_SANDBOX_H__ diff --git a/sandbox/sandbox_poc/sandbox.ico b/sandbox/sandbox_poc/sandbox.ico new file mode 100644 index 0000000..916fa12 Binary files /dev/null and b/sandbox/sandbox_poc/sandbox.ico differ diff --git a/sandbox/sandbox_poc/sandbox.rc b/sandbox/sandbox_poc/sandbox.rc new file mode 100644 index 0000000..978c96f --- /dev/null +++ b/sandbox/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/sandbox_poc/sandbox_poc.vcproj b/sandbox/sandbox_poc/sandbox_poc.vcproj new file mode 100644 index 0000000..5fde1cd --- /dev/null +++ b/sandbox/sandbox_poc/sandbox_poc.vcproj @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/sandbox_poc/stdafx.cc b/sandbox/sandbox_poc/stdafx.cc new file mode 100644 index 0000000..1c62c89 --- /dev/null +++ b/sandbox/sandbox_poc/stdafx.cc @@ -0,0 +1,30 @@ +// 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 "sandbox/sandbox_poc/stdafx.h" diff --git a/sandbox/sandbox_poc/stdafx.h b/sandbox/sandbox_poc/stdafx.h new file mode 100644 index 0000000..dde07f1 --- /dev/null +++ b/sandbox/sandbox_poc/stdafx.h @@ -0,0 +1,43 @@ +// 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. + +#ifndef SANDBOX_SANDBOX_POC_STDAFX_H__ +#define SANDBOX_SANDBOX_POC_STDAFX_H__ + +#include +#include +#include +#include +#include + +#define _ATL_NO_EXCEPTIONS +#include +#include + +#endif // SANDBOX_SANDBOX_POC_STDAFX_H__ \ No newline at end of file -- cgit v1.1