diff options
Diffstat (limited to 'chrome_elf')
-rw-r--r-- | chrome_elf/blacklist/blacklist.cc | 50 | ||||
-rw-r--r-- | chrome_elf/blacklist/blacklist.h | 6 | ||||
-rw-r--r-- | chrome_elf/blacklist/blacklist_interceptions.cc | 59 |
3 files changed, 111 insertions, 4 deletions
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc index f9eb065..34a498e 100644 --- a/chrome_elf/blacklist/blacklist.cc +++ b/chrome_elf/blacklist/blacklist.cc @@ -142,6 +142,22 @@ bool IsNonBrowserProcess() { return (command_line && wcsstr(command_line, L"--type")); } +// Record that the thunk setup completed succesfully and close the registry +// key handle since it is no longer needed. +void RecordSuccessfulThunkSetup(HKEY* key) { + if (key != NULL) { + DWORD blacklist_state = blacklist::BLACKLIST_SETUP_RUNNING; + ::RegSetValueEx(*key, + blacklist::kBeaconState, + 0, + REG_DWORD, + reinterpret_cast<LPBYTE>(&blacklist_state), + sizeof(blacklist_state)); + ::RegCloseKey(*key); + key = NULL; + } +} + } // namespace namespace blacklist { @@ -238,7 +254,7 @@ bool ResetBeacon() { int BlacklistSize() { int size = -1; - while(blacklist::g_troublesome_dlls[++size] != NULL); + while (blacklist::g_troublesome_dlls[++size] != NULL) {} return size; } @@ -248,7 +264,7 @@ bool AddDllToBlacklist(const wchar_t* dll_name) { // We need to leave one space at the end for the null pointer. if (blacklist_size + 1 >= kTroublesomeDllsMaxCount) return false; - for (int i=0; i < blacklist_size; ++i) { + for (int i = 0; i < blacklist_size; ++i) { if (!_wcsicmp(g_troublesome_dlls[i], dll_name)) return true; } @@ -306,6 +322,30 @@ bool Initialize(bool force) { // Tells the resolver to patch already patched functions. const bool kRelaxed = true; + // Record that we are starting the thunk setup code. + HKEY key = NULL; + DWORD disposition = 0; + LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, + kRegistryBeaconPath, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_QUERY_VALUE | KEY_SET_VALUE, + NULL, + &key, + &disposition); + if (result == ERROR_SUCCESS) { + DWORD blacklist_state = BLACKLIST_THUNK_SETUP; + ::RegSetValueEx(key, + kBeaconState, + 0, + REG_DWORD, + reinterpret_cast<LPBYTE>(&blacklist_state), + sizeof(blacklist_state)); + } else { + key = NULL; + } + // Create a thunk via the appropriate ServiceResolver instance. sandbox::ServiceResolverThunk* thunk; #if defined(_WIN64) @@ -332,8 +372,10 @@ bool Initialize(bool force) { if (!VirtualProtect(&g_thunk_storage, sizeof(g_thunk_storage), PAGE_EXECUTE_READWRITE, - &old_protect)) + &old_protect)) { + RecordSuccessfulThunkSetup(&key); return false; + } thunk->AllowLocalPatches(); @@ -355,6 +397,8 @@ bool Initialize(bool force) { PAGE_EXECUTE_READ, &old_protect); + RecordSuccessfulThunkSetup(&key); + return NT_SUCCESS(ret) && page_executable; } diff --git a/chrome_elf/blacklist/blacklist.h b/chrome_elf/blacklist/blacklist.h index 17a511d..7e01354 100644 --- a/chrome_elf/blacklist/blacklist.h +++ b/chrome_elf/blacklist/blacklist.h @@ -27,6 +27,12 @@ enum BlacklistState { // The blacklist setup code is running. If this is still set at startup, // it means the last setup crashed. BLACKLIST_SETUP_RUNNING, + // The blacklist thunk setup code is running. If this is still set at startup, + // it means the last setup crashed during thunk setup. + BLACKLIST_THUNK_SETUP, + // The blacklist code is currently intercepting MapViewOfSection. If this is + // still set at startup, it means we crashed during interception. + BLACKLIST_INTERCEPTING, // Always keep this at the end. BLACKLIST_STATE_MAX, }; diff --git a/chrome_elf/blacklist/blacklist_interceptions.cc b/chrome_elf/blacklist/blacklist_interceptions.cc index 6b01438..2be44e1 100644 --- a/chrome_elf/blacklist/blacklist_interceptions.cc +++ b/chrome_elf/blacklist/blacklist_interceptions.cc @@ -166,6 +166,21 @@ bool IsSameAsCurrentProcess(HANDLE process) { (::GetProcessId(process) == ::GetCurrentProcessId()); } +// Record that the interception completed succesfully and close the registry +// key handle since it is no longer needed. +void RecordSuccessfulInterception(HKEY* key, DWORD old_state) { + if (key != NULL) { + ::RegSetValueEx(*key, + blacklist::kBeaconState, + 0, + REG_DWORD, + reinterpret_cast<LPBYTE>(&old_state), + sizeof(old_state)); + ::RegCloseKey(*key); + key = NULL; + } +} + } // namespace namespace blacklist { @@ -196,12 +211,53 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI BlNtMapViewOfSection( SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) { + // Record that we are starting an interception. + HKEY key = NULL; + DWORD disposition = 0; + LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, + kRegistryBeaconPath, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_QUERY_VALUE | KEY_SET_VALUE, + NULL, + &key, + &disposition); + + DWORD old_blacklist_state = BLACKLIST_DISABLED; + if (result == ERROR_SUCCESS) { + DWORD old_blacklist_state_size = sizeof(old_blacklist_state); + DWORD type = 0; + result = ::RegQueryValueEx(key, + kBeaconState, + 0, + &type, + reinterpret_cast<LPBYTE>(&old_blacklist_state), + &old_blacklist_state_size); + + if (result != ERROR_SUCCESS) { + old_blacklist_state = BLACKLIST_ENABLED; + } + + DWORD blacklist_state = BLACKLIST_INTERCEPTING; + ::RegSetValueEx(key, + kBeaconState, + 0, + REG_DWORD, + reinterpret_cast<LPBYTE>(&blacklist_state), + sizeof(blacklist_state)); + } else { + key = NULL; + } + + NTSTATUS ret = orig_MapViewOfSection(section, process, base, zero_bits, commit_size, offset, view_size, inherit, allocation_type, protect); if (!NT_SUCCESS(ret) || !IsSameAsCurrentProcess(process) || !IsModuleValidImageSection(section, base, offset, view_size)) { + RecordSuccessfulInterception(&key, old_blacklist_state); return ret; } @@ -224,8 +280,9 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI BlNtMapViewOfSection( g_nt_unmap_view_of_section_func(process, *base); ret = STATUS_UNSUCCESSFUL; } - } + + RecordSuccessfulInterception(&key, old_blacklist_state); return ret; } |