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