interception.h revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Defines InterceptionManager, the class in charge of setting up interceptions 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the sandboxed process. For more details see 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://dev.chromium.org/developers/design-documents/sandbox . 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANDBOX_SRC_INTERCEPTION_H_ 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_SRC_INTERCEPTION_H_ 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string16.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_types.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TargetProcess; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum InterceptorId; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal structures used for communication between the broker and the target. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DllPatchInfo; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DllInterceptionData; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The InterceptionManager executes on the parent application, and it is in 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// charge of setting up the desired interceptions, and placing the Interception 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Agent into the child application. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The exposed API consists of two methods: AddToPatchedFunctions to set up a 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// particular interception, and InitializeInterceptions to actually go ahead and 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// perform all interceptions and transfer data to the child application. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The typical usage is something like this: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterceptionManager interception_manager(child); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (!interception_manager.AddToPatchedFunctions( 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// L"ntdll.dll", "NtCreateFile", 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sandbox::INTERCEPTION_SERVICE_CALL, &MyNtCreateFile, MY_ID_1)) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return false; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (!interception_manager.AddToPatchedFunctions( 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// L"kernel32.dll", "CreateDirectoryW", 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sandbox::INTERCEPTION_EAT, L"MyCreateDirectoryW@12", MY_ID_2)) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return false; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (!interception_manager.InitializeInterceptions()) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DWORD error = ::GetLastError(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return false; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Any required syncronization must be performed outside this class. Also, it is 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not possible to perform further interceptions after InitializeInterceptions 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is called. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterceptionManager { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The unit test will access private members. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do not work with sandbox tests. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout1); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout2); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An interception manager performs interceptions on a given child process. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are allowed to intercept functions that have been patched by somebody 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else, relaxed should be set to true. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: We increase the child's reference count internally. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptionManager(TargetProcess* child_process, bool relaxed); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~InterceptionManager(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Patches function_name inside dll_name to point to replacement_code_address. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function_name has to be an exported symbol of dll_name. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The new function should match the prototype and calling convention of the 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function to intercept except for one extra argument (the first one) that 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contains a pointer to the original function, to simplify the development 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of interceptors (for IA32). In x64, there is no extra argument to the 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interceptor, so the provided InterceptorId is used to keep a table of 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // intercepted functions so that the interceptor can index that table to get 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the pointer that would have been the first argument (g_originals[id]). 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, to intercept NtClose, the following code could be used: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NTSTATUS WINAPI MyNtCose(IN NtCloseFunction OriginalClose, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IN HANDLE Handle) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // // do something 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // // call the original function 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return OriginalClose(Handle); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And in x64: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NTSTATUS WINAPI MyNtCose64(IN HANDLE Handle) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // // do something 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // // call the original function 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NtCloseFunction OriginalClose = g_originals[NT_CLOSE_ID]; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return OriginalClose(Handle); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AddToPatchedFunctions(const wchar_t* dll_name, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* function_name, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptionType interception_type, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* replacement_code_address, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptorId id); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Patches function_name inside dll_name to point to 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // replacement_function_name. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AddToPatchedFunctions(const wchar_t* dll_name, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* function_name, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptionType interception_type, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* replacement_function_name, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptorId id); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The interception agent will unload the dll with dll_name. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AddToUnloadModules(const wchar_t* dll_name); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes all interceptions on the client. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The child process must be created suspended, and cannot be resumed until 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after this method returns. In addition, no action should be performed on 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the child that may cause it to resume momentarily, such as injecting 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads or APCs. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function must be called only once, after all interceptions have been 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set up using AddToPatchedFunctions. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool InitializeInterceptions(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to store the interception information until the actual set-up. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct InterceptionData { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptionType type; // Interception type. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterceptorId id; // Interceptor id. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 dll; // Name of dll to intercept. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string function; // Name of function to intercept. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string interceptor; // Name of interceptor function. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* interceptor_address; // Interceptor's entry point. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculates the size of the required configuration buffer. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t GetBufferSize() const; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rounds up the size of a given buffer, considering alignment (padding). 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value is the current size of the buffer, and alignment is specified in 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static inline size_t RoundUpToMultiple(size_t value, size_t alignment) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((value + alignment -1) / alignment) * alignment; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets up a given buffer with all the information that has to be transfered 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the child. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffer size should be at least the value returned by GetBufferSize 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SetupConfigBuffer(void* buffer, size_t buffer_bytes); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fills up the part of the transfer buffer that corresponds to information 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about one dll to patch. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data is the first recorded interception for this dll. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On successful return, buffer will be advanced from it's current position 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the point where the next block of configuration data should be written 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (the actual interception info), and the current size of the buffer will 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // decrease to account the space used by this method. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SetupDllInfo(const InterceptionData& data, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** buffer, size_t* buffer_bytes) const; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fills up the part of the transfer buffer that corresponds to a single 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function to patch. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dll_info points to the dll being updated with the interception stored on 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data. The buffer pointer and remaining size are updated by this call. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SetupInterceptionInfo(const InterceptionData& data, void** buffer, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* buffer_bytes, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DllPatchInfo* dll_info) const; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if this interception is to be performed by the child 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as opposed to from the parent. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsInterceptionPerformedByChild(const InterceptionData& data) const; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocates a buffer on the child's address space (returned on 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remote_buffer), and fills it with the contents of a local buffer. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CopyDataToChild(const void* local_buffer, size_t buffer_bytes, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** remote_buffer) const; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Performs the cold patch (from the parent) of ntdll. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method will insert additional interceptions to launch the interceptor 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // agent on the child process, if there are additional interceptions to do. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PatchNtdll(bool hot_patch_needed); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Peforms the actual interceptions on ntdll. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thunks is the memory to store all the thunks for this dll (on the child), 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and dll_data is a local buffer to hold global dll interception info. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PatchClientFunctions(DllInterceptionData* thunks, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t thunk_bytes, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DllInterceptionData* dll_data); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The process to intercept. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TargetProcess* child_; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Holds all interception info until the call to initialize (perform the 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actual patch). 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::list<InterceptionData> interceptions_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of patches added by name. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool names_used_; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // true if we are allowed to patch already-patched functions. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool relaxed_; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InterceptionManager); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This macro simply calls interception_manager.AddToPatchedFunctions with 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given service to intercept (INTERCEPTION_SERVICE_CALL), and assumes that 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the interceptor is called "TargetXXX", where XXX is the name of the service. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that num_params is the number of bytes to pop out of the stack for 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the exported interceptor, following the calling convention of a service call 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (WINAPI = with the "C" underscore). 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SANDBOX_EXPORTS 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN64) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAKE_SERVICE_NAME(service, params) "Target" # service "64" 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAKE_SERVICE_NAME(service, params) "_Target" # service "@" # params 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ADD_NT_INTERCEPTION(service, id, num_params) \ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddToPatchedFunctions(kNtdllName, #service, \ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::INTERCEPTION_SERVICE_CALL, \ 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKE_SERVICE_NAME(service, num_params), id) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INTERCEPT_NT(manager, service, id, num_params) \ 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((&Target##service) ? \ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager->ADD_NT_INTERCEPTION(service, id, num_params) : false) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// When intercepting the EAT it is important that the patched version of the 2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// function not call any functions imported from system libraries unless 2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// |TargetServices::InitCalled()| returns true, because it is only then that 2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// we are guaranteed that our IAT has been initialized. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INTERCEPT_EAT(manager, dll, function, id, num_params) \ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((&Target##function) ? \ 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKE_SERVICE_NAME(function, num_params), \ 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id) : \ 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // SANDBOX_EXPORTS 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN64) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAKE_SERVICE_NAME(service) &Target##service##64 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAKE_SERVICE_NAME(service) &Target##service 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ADD_NT_INTERCEPTION(service, id, num_params) \ 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddToPatchedFunctions(kNtdllName, #service, \ 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::INTERCEPTION_SERVICE_CALL, \ 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKE_SERVICE_NAME(service), id) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INTERCEPT_NT(manager, service, id, num_params) \ 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager->ADD_NT_INTERCEPTION(service, id, num_params) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// When intercepting the EAT it is important that the patched version of the 2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// function not call any functions imported from system libraries unless 2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// |TargetServices::InitCalled()| returns true, because it is only then that 2738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// we are guaranteed that our IAT has been initialized. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INTERCEPT_EAT(manager, dll, function, id, num_params) \ 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \ 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKE_SERVICE_NAME(function), id) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SANDBOX_EXPORTS 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace sandbox 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SANDBOX_SRC_INTERCEPTION_H_ 282