Files
Derek Bruening de0e3ff7d0 i#4366: Rename filter lists (#5272)
Renames filter lists:
+ s/blacklist/blocklist/
+ s/whitelist/allowlist/

This renames a public-facing drcpusim option:
+ s/-blacklist/-blocklist/
The legacy option is still supported using a droption alias.
Adds a test of both option names.

This also renames some non-publicized DR options:
+ s/whitelist_company_names_default/allowlist_company_names_default/
+ s/whitelist_company_names/allowlist_company_names/
It also renames DR variables like DYNAMORIO_VAR_APP_PROCESS_ALLOWLIST_ID.
We do not bother to provide aliases to support the old names for these
options and variables as they are not documented or commonly used anymore
and maybe should be removed in some future cleanup.

Issue #4366
2022-01-08 03:53:39 +00:00

573 lines
19 KiB
C

/* **********************************************************
* Copyright (c) 2014-2022 Google, Inc. All rights reserved.
* Copyright (c) 2005-2010 VMware, 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 VMware, 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 VMWARE, INC. 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.
*/
/*
* mfapi.h
*
* Interface for controlling Determina protection on a local machine
*
* (assumes a proper installation exists)
*
*/
#ifndef _DETERMINA_MFAPI_H_
#define _DETERMINA_MFAPI_H_
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include <wchar.h>
/* we don't want to include core headers here */
typedef UINT_PTR process_id_t;
#ifdef __cplusplus
extern "C" {
#endif
/* custom Win32-style error codes; using "high" constants so that
* it's obvious it's not win32. */
#define ERROR_OPTION_NOT_FOUND 0xffffffff
#define ERROR_NOT_INITIALIZED 0xfffffffe
#define ERROR_UNKNOWN_ENTRY 0xfffffffd
#define ERROR_DETACH_NOT_ALLOWED 0xfffffffc
#define ERROR_UNSUPPORTED_OS 0xfffffffb
#define ERROR_LIST_VIOLATION 0xfffffffa
#define ERROR_LENGTH_VIOLATION 0xfffffff9
#define ERROR_DETACH_ERROR 0xfffffff8
#define ERROR_PARSE_ERROR 0xfffffff7
#define ERROR_DRMARKER_ERROR 0xfffffff6
/************************
* policy import/export *
************************/
/*
*
* policy definition format specification
* --------------------------------------
*
*
* the syntax of the policy definition message is as follows:
* <policy_message> ::==
* POLICY_VERSION=30000
* APPINITFLAGS=<string>
* APPINITALLOWLIST=<string>
* APPINITBLOCKLIST=<string>
* GLOBAL_PROTECT=<boolean>
* <application_block>*
*
* <application_block> ::==
* BEGIN_BLOCK
* <app_specifier>
* [ <hot_patch_block> ]
* <dynamorio_option_line>*
* END_BLOCK
*
* <app_specifier> ::== [ GLOBAL | APP_NAME=<string> ]
*
* <dynamorio_option_line> ::== <dynamorio_option>=<string>
*
* <dynamorio_option> ::==
* [ DYNAMORIO_OPTIONS |
* DYNAMORIO_AUTOINJECT |
* DYNAMORIO_RUNUNDER |
* DYNAMORIO_HOT_PATCH_MODES |
* DYNAMORIO_HOT_PATCH_POLICIES ]
*
* <hot_patch_block> ::==
* BEGIN_MP_MODES
* <num_hot_patch_lines>
* <hot_patch_line>*
* END_MP_MODES
*
* <num_hot_patch_lines> ::== (int)
*
* <hot_patch_line> ::==
* <patch_id>:<patch_mode>
*
* <patch_mode> ::== [ 0 | 1 | 2 ]
*
* <patch_id>: provided by Determina
*
* <boolean> ::== [ 0 | 1 ]
*
*
*
* details:
*
* (1) the APPINITFLAGS, together with the APPINITBLOCKLIST and
* APPINITALLOWLIST, controls how our bootstrap dll is added to the
* AppInit_DLLs registry key. the value of the flags should be a sum
* of the APPINIT_* flags as defined in share/config.h
*
* The APPINITBLOCKLIST and APPINITALLOWLIST values are only used if
* specified by the flags. we'll provide the allowlist/blocklist.
*
*
* (2) GLOBAL_PROTECT: OPTIONAL: if this is 0, then protection is
* disabled (and all application blocks are optional). in normal
* situations this will be 1. if this is not specified, then the
* current setting is kept (see also enable_protection)
*
*
* (3) there must be a GLOBAL block, which should come first, and it
* must have DYNAMORIO_RUNUNDER=1 set as an option. for consistency it
* should set DYNAMORIO_OPTIONS to blank (DYNAMORIO_OPTIONS=).
*
*
* (4) the APP_NAME must be a valid "application id". this is usually
* the .exe filename, but can also be "qualified". we will provide a
* complete list of supported applications.
*
*
* (5) some applications will also require special values for
* DYNAMORIO_RUNUNDER; we will provide this information as well.
*
*
* (6) DYNAMORIO_AUTOINJECT must be specified for every non-global
* application block, and it should be of the format
* "\lib\NNNNN\dynamorio.dll", where NNNNN is the version number of
* the core dll being used. in general, any value that starts with a
* "\" will have the local installation path prepended when using the
* actual value (eg, it indicates a relative installation path).
*
*
* (7) DYNAMORIO_OPTIONS is a string consisting of protection options
* to our core. the variability in this will depend on the level of
* configurability desired in your UI; but the majority of the options
* will not need to change. probably the only configuration necessary
* will be whether an app should be on or off; and this should be
* controlled by including or excluding the corresponding app block.
*
*
* (8) to enable hot patching, there are three additional
* requirements:
* (a) the global DYNAMORIO_HOT_PATCH_DEFS option should be
* declared, and point to the relative subpath of the hot patch
* definitions file (provided with the update package). Typically
* this should just be "\config" -- the engine version and
* file name is standard. Of course this file must exist in the
* proper place: "\config\30000\hotp-defs.cfg".
* (b) similary, each app must provide the DYNAMORIO_HOT_PATCH_MODES
* subpath for the hotp modes file. Typically this will be the
* config directory followed by the app name, e.g.,
* "\config\detertest.exe". The modes files are created by the
* import process and should NOT be created manually.
* (c) Each app that requires patches must specify a list of patch
* id's and their "modes". The mode codes are 0 = Off, 1 =
* Detect Only, 2 = Protect. Typically only modes 0 and 2 will
* be used. As indicated above, the first line must be the number
* of patches specified. The list of patch id's and their
* descriptions is provided by Determina in the patch update
* packages.
*
* See sample.mfp for an example policy string.
*
*/
/* import the specified configuration, thus enabling Determina
* protection for all newly launched processes. note that, according
* to the policy definition (GLOBAL_PROTECT), this will either call
* enable_protection or disable_protection.
*
* if synchronize_system, then any processes were under Determina
* but are now configured to be off will be detached. otherwise,
* no changes will be made to any running processes.
*
* if inject_flag is not NULL, it will return whether or not injection
* should be turned on, e.g., with the enable_protection()
* method. this is mainly to allow clients to call
* enable_protection_ex() with various custom flags. if inject_flag
* is NULL, the import method will take care of enabling or disabling
* protection based on the policy.
*
* if warning is not NULL, it will be set to an error
* code indicating if a non-critical error (such as detach) was
* encountered.
*
* note that unlike other methods, the policy definition is a char
* (not WCHAR) -- this is because (presumably) the policy
* definition is being read from an ASCII file or a network
* connection. */
DWORD
policy_import(char *policy_definition, BOOL synchronize_system, BOOL *inject_flag,
DWORD *warning);
/* returns a policy definition string based on the current registry
* configuration.
* may return ERROR_MORE_DATA, in which case the call should
* be re-tried with a larger buffer.
* again note char buffer. */
DWORD
policy_export(char *policy_buffer, SIZE_T maxchars, SIZE_T *needed);
/* convenience method for loading from a file */
DWORD
load_policy(WCHAR *filename, BOOL synchronize_system, DWORD *warning);
/* convenience method for storing to a file */
DWORD
save_policy(WCHAR *filename);
/* returns ERROR_SUCCESS unless the policy_buffer is invalid. */
DWORD
validate_policy(char *policy_buffer);
/* writes an empty policy to the registry (so that no apps will be
* protected). distinct from disable_protection, which just clears
* the AppInit_DLLs key. */
DWORD
clear_policy();
/************************
* AppInit_DLLs setting *
************************/
/* enable Determina protection on the system. note that this is not
* required if implicitly invoked in policy_import. */
DWORD
enable_protection();
/* checks the current protection status. */
BOOL
is_protection_enabled();
/* disable Determina protection on the system. */
DWORD
disable_protection();
/*
* For more detailed control over the AppInit_DLLs key, use
* the following function.
*
* AppInit_DLLs flags:
* (for enable_protection_ex())
*
* APPINIT_FORCE_TO_FRONT
* Forces preinject dll to the front of the AppInit_DLLs list.
*
* APPINIT_FORCE_TO_BACK
* Forces preinject dll to the back of the AppInit_DLLs list.
*
* APPINIT_USE_BLOCKLIST
* Will read blocklist from blocklist config parameter and
* validate against it.
*
* APPINIT_USE_ALLOWLIST
* Will read allowlist from allowlist config parameter and
* validate against it.
*
* APPINIT_CHECK_LISTS_ONLY
* If set, the lists are only checked, not enforced; intended
* for use with at least one of the two flags below.
*
* APPINIT_WARN_ON_LIST_VIOLATION
* Whether to generate a warning if a allowlist/blocklist
* violation was detected.
*
* APPINIT_BAIL_ON_LIST_VIOLATION
* If set, the preinjector will not be added to the
* list, thus effectively disabling Determina.
*
*
* The following flags apply only for platforms which
* require preinject to be in SYSTEM32 (ie, NT4 for now).
*
* APPINIT_SYS32_USE_LENGTH_WORKAROUND
* Not yet supported -- must be zero. Placeholder
* for using some alternate technique to handle
* other dlls which may be in the list.
*
* APPINIT_SYS32_FAIL_ON_LENGTH_ERROR
* If existing entries + preinject name
* exceeds the 31-character limit, leave key
* untouched and report an error.
*
* APPINIT_SYS32_CLEAR_OTHERS
* If set, any other appinit entries are
* cleared, regardless of length. otherwise,
* all entries are left intact, and an
* operation that results in too long of
* a string will be truncated but succeed
* unless APPINIT_SYS32_FAIL_ON_LENGTH_ERROR
* is set.
*
* APPINIT_SYS32_TRUNCATE
* If set, appinit is truncated to 31 chars
* before writing; otherwise, the entire
* string is written, even if over the limit.
*
*/
#define APPINIT_FORCE_TO_FRONT 0x1
#define APPINIT_FORCE_TO_BACK 0x2
#define APPINIT_USE_BLOCKLIST 0x4
#define APPINIT_USE_ALLOWLIST 0x8
#define APPINIT_CHECK_LISTS_ONLY 0x10
#define APPINIT_WARN_ON_LIST_VIOLATION 0x20
#define APPINIT_BAIL_ON_LIST_VIOLATION 0x40
#define APPINIT_SYS32_USE_LENGTH_WORKAROUND 0x100
#define APPINIT_SYS32_FAIL_ON_LENGTH_ERROR 0x200
#define APPINIT_SYS32_CLEAR_OTHERS 0x400
#define APPINIT_SYS32_TRUNCATE 0x800
#define APPINIT_OVERWRITE 0x1000
/* The flags, blocklist, allowlist, list_error parameters are as
* described above.
* The inject parameter controls whether protection is enabled or
* disabled. If disabled all other parameters are ignored.
* The custom_preinject_name allows a non-standard DLL to be used;
* generally this should be NULL.
* The current_list buffer (of size maxchars) is optional; if provided
* it will contain the contents of the AppInit_DLLs key before any
* changes are made; this is useful in the case that list_error
* violation is reported.
*/
DWORD
enable_protection_ex(BOOL inject, DWORD flags, const WCHAR *blocklist,
const WCHAR *allowlist, DWORD *list_error,
const WCHAR *custom_preinject_name, WCHAR *current_list,
SIZE_T maxchars);
/*************************
* process status *
*************************/
/* generic process walk callback routine; the callback should
* return FALSE to abort the walk. optionally takes a parameter
* which can be passed to the enumerate_processes method. */
typedef BOOL (*process_callback)(ULONG pid, WCHAR *process_name, void **param);
/* helper method: for each running processes on the system,
* executes the callback with the specified info. (everything is
* synchronous here.)
* note that this is much cleaner than the Win32 api's tlhelp32
* interface, which should NEVER be used! */
DWORD
enumerate_processes(process_callback pcb, void **param);
/* process status codes */
#define INJECT_STATUS_PROTECTED 1
#define INJECT_STATUS_NATIVE 2
#define INJECT_STATUS_UNKNOWN 3
/* returns one of above status definitions in the status pointer.
* if the build pointer is non-NULL, returns the build number of the
* core (if the process is protected).*/
DWORD
inject_status(process_id_t pid, DWORD *status, DWORD *build);
/* returns TRUE if the indicated process is configured for
* protection, yet is not running under Determina (this means it
* must be restarted before protection will take effect).
* returns FALSE if the process is under Determina or not configured
* for protection. (or in the case of any error.)
* note this is fairly expensive because it needs to load the current
* policy from the registry and check against it. a more efficient
* API may be exposed in the future.
*/
BOOL
is_process_pending_restart(process_id_t pid);
/* returns TRUE if any process is_pending_restart */
BOOL
is_any_process_pending_restart();
/********************
* detach / nudge *
********************/
/* in ms */
#define DETACH_RECOMMENDED_TIMEOUT 60000
#define NUDGE_NO_DELAY 0
/* this is recommended for all hotp notification methods. */
#define NUDGE_RECOMMENDED_PAUSE 100
/* detach from indicated process -- if allow_upgraded_perms, then
* attempt to acquire necessary privileges (usually necessary) */
DWORD
detach(process_id_t pid, BOOL allow_upgraded_perms, DWORD timeout_ms);
/* detach from all running processes (with timeout).
* timeout is per process */
DWORD
detach_all(DWORD timeout);
/* detach from all processes with the matching exe name */
DWORD
detach_exe(WCHAR *exename, DWORD timeout_ms);
/* make sure that only configured processes are running under
* Determina */
DWORD
consistency_detach(DWORD timeout);
/* use this to notify a process to use new configuration information
* in the memory patch "modes" file. */
DWORD
hotp_notify_modes_update(process_id_t pid, BOOL allow_upgraded_perms, DWORD timeout_ms);
/* use this to notify a process to use new configuration information
* in the memory patch "definitions" file -- note that since new
* policy definitions will be re-loaded, this will also cause the
* modes information to be re-read as well. */
DWORD
hotp_notify_defs_update(process_id_t pid, BOOL allow_upgraded_perms, DWORD timeout_ms);
/* get modes update for all running processes. timeout is per process */
DWORD
hotp_notify_all_modes_update(DWORD timeout_ms);
/* get defs update for all running processes. timeout is per process */
DWORD
hotp_notify_all_defs_update(DWORD timeout_ms);
/* get modes update for all running processes matching exe name.
* timeout is per process */
DWORD
hotp_notify_exe_modes_update(WCHAR *exename, DWORD timeout_ms);
/************************
* event log *
************************/
/*
* start_eventlog_monitor:
* spawns a new thread which monitors the Araksha event log for
* new messages. the eventlog_callback is called for each new
* event with parameters as described above. any warnings, errors,
* failurse, etc. trigger the cb_err callback.
* returns a handle to the listener thread.
*
* use stop_eventlog_monitor to cleanly destroy the listener thread
*/
/* monitor error codes */
#define ELM_ERR_FATAL 1
#define ELM_ERR_WARN 2
#define ELM_ERR_CLEARED 3
typedef void (*eventlog_formatted_callback)(unsigned int mID, unsigned int type,
WCHAR *message, DWORD timestamp);
typedef void (*eventlog_raw_callback)(EVENTLOGRECORD *record);
typedef void (*eventlog_error_callback)(unsigned int errcode, WCHAR *message);
/* last_record must be a valid eventlog record number!!
* this can be obtained from the "raw" callback by the RecordNumber
* value of the EVENTLOGRECORD struct.
* pass -1 to retrieve all event records. */
DWORD
start_eventlog_monitor(BOOL use_formatted_callback, eventlog_formatted_callback cb_format,
eventlog_raw_callback cb_raw, eventlog_error_callback cb_err,
DWORD next_record);
void
stop_eventlog_monitor();
/* removes all events from the Determina event log */
DWORD
clear_eventlog();
HANDLE
get_eventlog_monitor_thread_handle();
BOOL
is_violation_event(DWORD eventType);
/* helper method for parsing message strings in an EVENTLOGRECORD */
const WCHAR *
next_message_string(const WCHAR *prev_string);
/* helper method for getting the (pathless) executable name out
* of an EVENTLOGRECORD */
const WCHAR *
get_event_exename(EVENTLOGRECORD *pevlr);
/* helper method for getting the PID out of an EVENTLOGRECORD */
UINT
get_event_pid(EVENTLOGRECORD *pevlr);
/* helper method for getting the Threat ID out of an EVENTLOGRECORD.
* If the event type does not have a Threat ID parameter (e.g., for
* information events), then this will return NULL. */
const WCHAR *
get_event_threatid(EVENTLOGRECORD *pevlr);
/* helper method for getting the formatted text from an EVENTLOGRECORD
* structure. */
DWORD
get_formatted_message(EVENTLOGRECORD *pevlr, WCHAR *buf, DWORD maxchars);
/***************************************
* system information / installation *
***************************************/
/* supported platform identifiers */
#define PLATFORM_UNKNOWN 0
#define PLATFORM_WIN_2000 100
#define PLATFORM_WIN_XP 110
#define PLATFORM_WIN_2003 120
#define PLATFORM_WIN_NT_4 130
#define PLATFORM_VISTA 140
#define PLATFORM_WIN_7 150
#define PLATFORM_WIN_8 160
#define PLATFORM_WIN_8_1 170
#define PLATFORM_WIN_10 180
#define PLATFORM_WIN_10_1511 190
#define PLATFORM_WIN_10_1607 200
#define PLATFORM_WIN_10_1703 210
#define PLATFORM_WIN_10_1709 220
#define PLATFORM_WIN_10_1803 230
DWORD
get_platform(DWORD *platform);
const WCHAR *
get_installation_path();
const WCHAR *
get_product_name();
#ifdef __cplusplus
}
#endif
#endif