| /* ********************************************************** |
| * 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. |
| */ |
| |
| /* Copyright (c) 2005-2007 Determina Corp. */ |
| |
| /* |
| * aslr.h - Types and definitions for ASLR address space layout randomization |
| * |
| * Plan to implement only for win32. |
| */ |
| |
| #ifndef ASLR_H |
| #define ASLR_H |
| |
| #include "ntdll.h" |
| |
| /* ASLR control flags for -aslr */ |
| enum { |
| ASLR_DISABLED = 0x00, |
| |
| /* application memory areas to randomize */ |
| ASLR_DLL = 0x01, /* randomize DLLs mapped as image */ |
| ASLR_STACK = 0x02, /* case 6287 - padding initial stack from parent */ |
| /* Note option active in parent applies to its children */ |
| |
| ASLR_HEAP = 0x04, /* random initial virtual memory padding */ |
| ASLR_MAPPED = 0x08, /* FIXME: NYI case 2491, case 6737 */ |
| ASLR_EXECUTABLE = 0x10, /* FIXME: NYI case 2491 + case 1948 */ |
| |
| ASLR_PROCESS_PARAM = 0x20, /* FIXME: NYI case 6840 */ |
| /* Note option active in parent applies to its children */ |
| /* controls earliest possible padding from parent, yet interop |
| * problem with device drivers assuming ProcessParameters is at a |
| * fixed location, separately controlled from ASLR_STACK which |
| * gets allocated later |
| */ |
| |
| ASLR_HEAP_FILL = 0x40, /* random padding between virtual allocations */ |
| ASLR_TEB = 0x80, /* FIXME: NYI case 2491 */ |
| |
| /* FIXME: for TEB can reserve the pages after the PEB allocation |
| * unit, yet the first threads are still in the PEB allocation |
| * unit. We could fill the original threads space from the parent |
| * before any other threads are created, but not that valuable |
| * since still providing known writable location */ |
| |
| /* FIXME: PEB probably CAN'T be moved from user mode at all, |
| * definitely can't relocate in running process since can't change protections |
| */ |
| |
| /* range allocation - case 6739 */ |
| /* A virtual memory range should be allocated to each group, |
| * (DLLs, mappings, heap). Default range allocation within a |
| * group is to add new areas bottom up (from a defined starting |
| * value + random); after each mapping the size is known and some |
| * smaller random padding can be added. |
| * FIXME: Reclaiming ranges is not currently controlled, |
| * committed memory issues due to that tracked in case 6729 |
| */ |
| ASLR_RANGE_BOTTOM_UP = 0x00100, /* default behaviour, reserved */ |
| ASLR_RANGE_TOP_DOWN = 0x00200, /* NYI: FIXME: need size for |
| * going top down requires an |
| * extra system call */ |
| ASLR_RANGE_RANDOM = 0x00400, /* NYI: FIXME: may cause too |
| * much fragmentation, best done |
| * with full vmmap, then we can |
| * choose a random location |
| * anywhere in our range */ |
| |
| ASLR_SHARE_DR_DLL = 0x10000000, /* FIXME: NYI case 8129 */ |
| /* Note option active in parent applies to its children */ |
| /* In addition to the current -aslr_dr feature, should eventually |
| * share views similar to ASLR_SHARED_CONTENTS */ |
| |
| /* default in client mode currently is */ |
| ASLR_CLIENT_DEFAULT = ASLR_DLL | ASLR_STACK | ASLR_HEAP, /* 0x7 */ |
| } aslr_option_t; |
| |
| /* ASLR control flags for -aslr_cache */ |
| enum { |
| /* sharing flags - case 2491 scheme 2.2 |
| * NYI we may publish section handles in a global |
| * namespace to allow sharing of private mappings, |
| * and share addresses for compatibility, or both addresses and contents |
| * for memory reduction |
| */ |
| ASLR_PROCESS_PRIVATE = 0x1, /* default behaviour, flag RESERVED */ |
| |
| ASLR_SHARED_PER_USER = 0x2, |
| /* NYI: allows per-user sharing so that all instances of a |
| * module by 'user' use the same mapping, but other users use |
| * private copies. |
| * 0) sharing - good - for the general desktop only SYSTEM and Administrator |
| * 1) integrity- permission-wise created by 'user' |
| * so other processes may write to it without impact to others |
| * 2) disclosure - other users base addresses will be different |
| */ |
| |
| ASLR_SHARED_INHERIT = 0x4, |
| /* NYI: allow trusted users to create mappings that other users |
| * share (kernel deals with ref counting, and expected to be |
| * sticky! so low priv process doesn't need to do anything about |
| * removing ). |
| * 0) sharing better than ASLR_SHARED_PER_USER |
| * 1) integrity same |
| * |
| * 2) disclosure worse, since now plain users know |
| * the randomized mappings for SYSTEM processes |
| * and allows local attacks |
| * |
| * 3) there is also a more theoretical information disclosure |
| * in case a published executable has 'secrets' that low |
| * privilege users aren't supposed to be able to read or |
| * execute from |
| */ |
| |
| ASLR_SHARED_IN_SESSION = 0x8, |
| /* NYI: \Local\ limits sharing for terminal service users to only |
| * current session, can be combined with INHERIT to prevent |
| * disclosure of mappings of services from remotely logged users. |
| * (Although in Vista services will be the only processes in |
| * Session 0, on earlier Windows versions still allows desktop |
| * user to completely share and inherit mappings). May apply only |
| * to inherit, or could be used to disallow user in multiple sessions... |
| */ |
| /* Note that different security models based on the user |
| * privileges may have some processes independently take some but |
| * not necessarily all of file 'producer', section 'publisher' and |
| * mapping 'subscriber' roles. */ |
| |
| ASLR_SHARED_CONTENTS = 0x10, |
| /* NYI: If not set sharing will be of address only to resolve |
| * incompatible applications requiring a DLL to be mapped at the |
| * same address, if set sharing also means saving memory by not |
| * using private copies. |
| */ |
| |
| ASLR_SHARED_PUBLISHER = 0x20, |
| /* Process is allowed and has permissions to publish sections for |
| * other users to map contents. Note may be different from |
| * file producer marked as ASLR_SHARED_FILE_PRODUCER. |
| */ |
| |
| ASLR_SHARED_SUBSCRIBER = 0x40, |
| /* Process is to take the risk to use published sections, with |
| * risk of privilege escalation if sections or backing files are |
| * improperly secured, and according to the sharing inheritance |
| * flags. |
| */ |
| |
| ASLR_SHARED_ANONYMOUS_CONSUMER = 0x80, |
| /* Anonymous section mappings directly from an already produced |
| * file if current user doesn't have permission to publish, |
| * e.g. direct file consumer. Useful if consistency and security |
| * needs can be satisfied without need for exclusive file access |
| * and other shared objects. Performance hit depends on |
| * consistency checks performed. |
| * |
| * FIXME: we may want to fallback to this option even if we use as |
| * default option a publisher and use any of the further options |
| * tracked in case 8812 |
| */ |
| |
| ASLR_SHARED_FILE_PRODUCER = 0x100, |
| /* Publisher may only be opening files created by a different |
| * process if not set, or may produce the relocated files from |
| * within DR. |
| * |
| * FIXME: can also queue up request to generate a particular file |
| * even if not materializing immediately in that case it will be |
| * combined with ASLR_SHARED_WORKLIST modifier. |
| */ |
| |
| ASLR_SHARED_WORKLIST = 0x200, |
| /* Process a worklist of modules to optionally produce and/or |
| * publish. FIXME: Note that separate queues for publishing and |
| * producing may be needed. |
| */ |
| |
| ASLR_SHARED_INITIALIZE = 0x1000, |
| /* Creates object directories if not yet created - needs to be |
| * done by first highly privileged process, although multiple ones |
| * attempting to do so is OK. FIXME: TOFILE Security |
| * risk for privileged processes if directories and subdirectories |
| * can be created by non-privileged process, needs to make sure |
| * there is no race in which a low-privileged process creates |
| * entries before an older one. See comments in |
| * nt_initialize_shared_directory() about required privileges if a |
| * permanent (until reboot) directory is to be created. |
| */ |
| |
| ASLR_SHARED_INITIALIZE_NONPERMANENT = 0x2000, |
| /* make ASLR_SHARED_INITIALIZE initialize as a temporary object |
| * instead of the default permanent directory, useful for running |
| * a user process without proper permissions. FIXME: may want to |
| * force it to use a per-user directory in this case. |
| */ |
| |
| ASLR_PERSISTENT = 0x100000, /* NYI: namespace placeholder */ |
| /* allow persistent copies to remain reusable possibly until |
| * reboot, or even longer. Currently this is the default behavior |
| * for produced files. |
| */ |
| |
| /* non transparent option, not recommended */ |
| ASLR_ALLOW_ORIGINAL_CLOBBER = 0x1000000, |
| /* FIXME: as a feature case 9033 - would allow overwriting |
| * original files without anyone noticiing. This would allow one |
| * to apply M$ patches without a reboot, and they would take |
| * effect for any other service using them. However, it may |
| * prevent the use of M$ or third party tools to appropriately |
| * determine that application restarts are necessary. xref case |
| * 8623 about the opposite problem of publishers keeping such |
| * handles even after all subscribers have been closed. |
| */ |
| |
| /* non transparent option, not recommended */ |
| ASLR_RANDOMIZE_EXECUTABLE = 0x2000000, |
| /* |
| * executables with relocations can now be randomized |
| * from the parent process (especially on Vista). |
| * case 8902 - however shows in taskmgr the name of our mangled file |
| * we need to change our naming scheme to make this appear the same |
| * FIXME: to support !ASLR_ALLOW_ORIGINAL_CLOBBER |
| * we also need to prevent overwrites of the executablewe by duplicating |
| * our handle in the target process, so it gets closed when the child dies. |
| * |
| */ |
| |
| /* case 9164: default off, may want if many temporary ASP.NET DLLs get created */ |
| ASLR_AVOID_NET20_NATIVE_IMAGES = 0x4000000, |
| |
| /* default in client mode currently should be 0x192 */ |
| ASLR_CACHE_DEFAULT = ASLR_SHARED_PER_USER | /* 0x2 */ |
| ASLR_SHARED_CONTENTS | /* 0x10 */ |
| ASLR_SHARED_ANONYMOUS_CONSUMER | /* 0x80 */ |
| ASLR_SHARED_FILE_PRODUCER /* 0x100 */ |
| } aslr_cache_t; |
| |
| /* ASLR cache coverage options for -aslr_cache_list */ |
| enum { |
| /* almost all controlled by other general ASLR exemptions */ |
| ASLR_CACHE_LIST_DEFAULT, |
| ASLR_CACHE_LIST_INCLUDE, /* -aslr_cache_list_include */ |
| ASLR_CACHE_LIST_EXCLUDE /* -aslr_cache_list_exclude */ |
| /* (note aslr_cache_list_t values match meaning of whitelist blacklist |
| * as in process_control) |
| */ |
| } aslr_cache_list_t; |
| |
| enum { |
| /* consistency check flags for use with aslr_validation. These |
| * are enforced by publishers when validating already produced |
| * files. Note that with better security guarantees different |
| * levels of caching can be employed. We currently demand that |
| * producers produce all supported metadata even if used only by |
| * some publishers, that may have different tradeoffs between |
| * security and/or performance objectives. |
| */ |
| |
| ASLR_PERSISTENT_LAX = 0x0, |
| /* rely only on file size and matching magic |
| * insufficient for small patches, |
| * least consistency and no security |
| */ |
| |
| ASLR_PERSISTENT_PARANOID = 0x1, |
| /* provides strongest consistency and security: full byte |
| * comparison of original DLL and a provided relocated DLL |
| * most expensive to evaluate |
| */ |
| |
| ASLR_PERSISTENT_SOURCE_DIGEST = 0x2, |
| /* provides source consistency and staleness check: MD5 digest of |
| * the source file, assuming reliable and trustworthy producer |
| */ |
| |
| ASLR_PERSISTENT_TARGET_DIGEST = 0x4, |
| /* target corruption only: MD5 digest of the produced file, |
| * nonmalicious corruption only, otherwise no guarantee of the |
| * relationship between source and target */ |
| /* FIXME: This one may not be very useful, but allows for a better |
| * check for corrupt files in case we can't guarantee atomicity, |
| * e.g. in case files are to be shared over the network. |
| * |
| * Note that the combination of target digest and paranoid |
| * verification gives us somewhat more information than either |
| * one: an attacker trying to bypass an MD5 can always calculate |
| * the correct value, while a corrupted file will not have it. |
| * Interesting information only if we run processes with different |
| * privileged with differing level of validation. |
| */ |
| |
| ASLR_PERSISTENT_MODIFIED_TIME = 0x8, /* NYI */ |
| /* FIXME: currently not possible to read the source file time. |
| * Otherwise would provide a weak staleness check only, no |
| * security: has potential for missing an update that preserves |
| * file times. Also has some possibility of false positives in |
| * case say some antivirus program modifies a file or stores |
| * information past the end or in a separate stream of the |
| * original DLL. |
| * |
| * Note that FAT32 vs NTFS times differ so we store this in our |
| * own signature instead of trying to touch our file to match. |
| */ |
| |
| ASLR_PERSISTENT_NOTOWNER_PARANOIA = 0x10, |
| /* FIXME: NYI force paranoia in case file is not securely owned by |
| * the current user, e.g. could have never been overwritten by |
| * another user. This allows us to share between users even in |
| * case files are produced by others, and skipping the check if we |
| * have safe private copies. |
| */ |
| |
| ASLR_PERSISTENT_SHORT_DIGESTS = 0x20, |
| /* a qualifer on ASLR_PERSISTENT_SOURCE_DIGEST and |
| * ASLR_PERSISTENT_TARGET_DIGEST to use short as defined by |
| * aslr_short_digest. Allows us to set a limit on verification time |
| * and working set impact, with acceptable consistency, but with |
| * an obvious security risk. |
| */ |
| |
| ASLR_PERSISTENT_PARANOID_TRANSFORM_EXPLICITLY = 0x10000, /* case 8858 */ |
| /* When set we'll do the comparison by explicitly making a private |
| * copy just as a publisher, otherwise we compare in place |
| * relocation by relocation. FIXME: this flag for |
| * ASLR_PERSISTENT_PARANOID should be internal, but for now |
| * leaving the old implementation for perf comparison, and added |
| * late in the game anyways. |
| */ |
| |
| /* FIXME: not recommended in production, should really make INTERNAL */ |
| ASLR_PERSISTENT_PARANOID_PREFIX = 0x20000, |
| /* This flag for ASLR_PERSISTENT_PARANOID similarly to |
| * ASLR_PERSISTENT_SHORT_DIGESTS makes it not really so paranoid. |
| * Allows to trade security and consistency risk for performance. |
| * |
| * Cannot be used for security if target files are world writable - |
| * planting bad code for Administrator running explorer.exe is a |
| * bad enough elevation of privileges. |
| * |
| * FIXME: if in the future we do on-demand comparison, we may |
| * still want to first verify a prefix before we decide that the |
| * DLL is usable. |
| */ |
| } aslr_consistency_check_t; |
| |
| |
| /* ASLR control flags for -aslr_action */ |
| enum { |
| ASLR_NO_ACTION = 0x0, /* do not track */ |
| |
| /* Track likely attempts to use preferred addresses */ |
| ASLR_TRACK_AREAS = 0x1, /* keep track of would_be regions */ |
| ASLR_AVOID_AREAS = 0x2, /* NYI disallow other DLL mappings */ |
| ASLR_RESERVE_AREAS = 0x4, /* NYI virtually reserve to avoid any allocation */ |
| |
| /* Reporting exceptions */ |
| /* intercept execute faults when run native, or RCT violations |
| * when targeting unreadable memory. |
| * |
| * FIXME: if areas are not reserved an RCT violation in a |
| * would_be area may also be attributed here. |
| */ |
| ASLR_DETECT_EXECUTE = 0x10, |
| /* FIXME: cannot reliably distinguish read from Execute when not |
| * enforcing DR security policies on a machine without NX */ |
| ASLR_DETECT_READ = 0x20, /* NYI */ |
| ASLR_DETECT_WRITE = 0x40, /* NYI */ |
| |
| /* report likely violations */ |
| ASLR_REPORT = 0x100, |
| /* if not set, stays silent, yet detection worthwhile in |
| * combination with alternative handling where we'd kill an |
| * injected thread */ |
| |
| /* Alternative attack handling */ |
| ASLR_HANDLING = 0x1000,/* NYI the default of throw_exception or kill_thread */ |
| /* if not set an exception is simply passed to the application */ |
| |
| /* ThreatIDs can be normalized */ |
| ASLR_NORMALIZE_ID = 0x10000, /* NYI use bytes at current mapping |
| * instead of would_be address */ |
| /* as long as there are no relocations should maintain ThreatID */ |
| } aslr_action_t; |
| |
| /* testing and stress testing range flags for -aslr_internal */ |
| enum { |
| ASLR_INTERNAL_DEFAULT = 0x0000, /* normal handling */ |
| |
| /* stress test option to verify proper dealing with address conflicts */ |
| /* doesn't increment base, so most requests will overlap */ |
| ASLR_INTERNAL_SAME_STRESS = 0x1000, |
| |
| /* testing option - actually not choosing base, FIXME: remove soon */ |
| ASLR_INTERNAL_RANGE_NONE = 0x2000, |
| |
| ASLR_INTERNAL_SHARED_NONUNIQUE = 0x800000, |
| /* stress test naming conflicts */ |
| |
| ASLR_INTERNAL_SHARED_APPFILE = 0x1000000, |
| /* stress test - use application file to test sections */ |
| |
| ASLR_INTERNAL_SHARED_AND_PRIVATE = 0x2000000, |
| /* stress test - use our files but still randomize privately as well */ |
| |
| /* Note that -exempt_aslr_list '*' can also be used as a stress |
| * option, instead of another flag here. |
| */ |
| } aslr_internal_option_t; |
| |
| typedef struct { |
| bool sys_aslr_clobbered; |
| /* mark syscalls modified by ASLR, and need additional handling */ |
| |
| /* ASLR_SHARED_CONTENTS needs to preserve some context across |
| * NtCreateSection and NtMapViewOfSection system calls |
| * xref case 9028 about using a more robust scheme that doesn't depend |
| * on these being consecutive: FIXME: add to section2file table? |
| */ |
| HANDLE randomized_section_handle; /* for shared randomization */ |
| app_pc original_section_base; /* for detecting attacks */ |
| uint original_section_timestamp; /* for hotpatching */ |
| uint original_section_checksum; /* for hotpatching */ |
| HANDLE original_image_section_handle; |
| /* used for !ASLR_ALLOW_ORIGINAL_CLOBBER to pass information from |
| * NtCreateSection to NtMapViewOfSection or NtCreateProcess* */ |
| |
| #ifdef DEBUG |
| /* with i#138's section2file table we only use this for debugging */ |
| HANDLE last_app_section_handle; /* flagging unusual section handle uses */ |
| #endif |
| |
| /* Case 9173: only pad each child once. Rather than record every child seen |
| * (which has problems w/ pid reuse, as well as unbounded growth, as we |
| * won't see child death), we only record the previous one, leaving a corner |
| * case with alternate memory allocations to multiple pre-thread children |
| * causing us to pad multiply; likewise with separate threads each |
| * allocating in the same child. We'll live with both risks. |
| */ |
| process_id_t last_child_padded; /* pid */ |
| } aslr_syscall_context_t; |
| |
| #define ASLR_INVALID_SECTION_BASE ((app_pc)PTR_UINT_MINUS_1) |
| |
| /* names should look like kernel32.dll-12349783 */ |
| #define MAX_PUBLISHED_SECTION_NAME 64 |
| |
| void aslr_init(void); |
| void aslr_exit(void); |
| void aslr_thread_init(dcontext_t *dcontext); |
| void aslr_thread_exit(dcontext_t *dcontext); |
| |
| void aslr_free_last_section_file_name(dcontext_t *dcontext); |
| |
| void aslr_pre_process_mapview(dcontext_t *dcontext); |
| void aslr_post_process_mapview(dcontext_t *dcontext); |
| |
| void aslr_pre_process_unmapview(dcontext_t *dcontext, app_pc base, size_t size); |
| reg_t aslr_post_process_unmapview(dcontext_t *dcontext); |
| |
| void aslr_post_process_allocate_virtual_memory(dcontext_t *dcontext, |
| app_pc base, size_t size); |
| void aslr_pre_process_free_virtual_memory(dcontext_t *dcontext, |
| app_pc base, size_t size); |
| |
| /* FIXME: wrap in aslr_post_process_create_or_open_section */ |
| bool |
| aslr_post_process_create_section(IN HANDLE old_app_section_handle, |
| IN HANDLE file_handle, |
| OUT HANDLE *new_relocated_handle); |
| |
| bool |
| aslr_post_process_create_or_open_section(dcontext_t *dcontext, |
| bool is_create, |
| IN HANDLE file_handle /* OPTIONAL */, |
| OUT HANDLE *sysarg_section_handle); |
| bool |
| aslr_is_handle_KnownDlls(HANDLE directory_handle); |
| |
| bool |
| aslr_recreate_known_dll_file(OBJECT_ATTRIBUTES *obj_attr, |
| OUT HANDLE *recreated_file); |
| |
| void |
| aslr_maybe_pad_stack(dcontext_t *dcontext, HANDLE process_handle); |
| |
| void |
| aslr_force_dynamorio_rebase(HANDLE process_handle); |
| |
| /* deterministic (and reversible) timestamp transformation */ |
| static inline uint |
| aslr_timestamp_transformation(uint old_timestamp) |
| { |
| return old_timestamp + 1; |
| } |
| |
| #ifdef GBOP |
| /* Generically Bypassable Overflow Protection in user mode |
| * |
| * For reference see |
| * P. Szor, "Virus Research and Defense", Chapter 13, 13.3.1.1 and 13.3.4.2, |
| * (skipping 13.2.6 on program shepherding and 13.3.4.1 ASLR) |
| * or "Bypassing 3rd Party Windows Buffer Overflow Protection" |
| * http://www.phrack.org/show.php?p=62&a=5 on how to break one |
| * |
| * FIXME: For interoperability purposes need to identify a |
| * compatibility mode that doesn't do more than competitor's desktop |
| * suite offerings, so their BOP functionality can be turned off. Yet |
| * to avoid reversing them (although legally allowed for |
| * interoperability purposes), for now we'll do the best they may be |
| * doing. |
| */ |
| |
| /* GBOP control flags for the -gbop option */ |
| enum { |
| GBOP_DISABLED = 0x0, |
| /* source is identified as [TOS] for the first level, |
| * and if non-zero gbop_frames a stack backtrace is attempted. |
| * |
| * Note that providing FPO information (requires product updates |
| * for new versions) would allow deeper hooking and reliable |
| * backtraces. |
| */ |
| |
| /* source memory properties, note these are ORed together, |
| * at least one of the following set needs to be enabled */ |
| GBOP_IS_EXECUTABLE = 0x1, /* using our own tracking definitions */ |
| GBOP_IS_X = 0x2, /* allowing all ..X pages, cf -executable_if_x */ |
| GBOP_IS_IMAGE = 0x4, /* allowing all MEM_IMAGE pages, |
| * c.f. -executable_if_image */ |
| /* FIXME: another realistic policy would be to allow RWX as |
| * long as it is in an image, but not otherwise |
| */ |
| /* FIXME: add GBOP_IS_NOT_W to allow as long as not writable */ |
| |
| GBOP_IS_NOT_STACK = 0x8, |
| /* If set, allows returns to anything but the current stack. Case 8085. */ |
| |
| /* see also GBOP_IS_FUTURE_EXEC = 0x04000 */ |
| |
| |
| /* source instruction type. Checks if instruction according to |
| * [TOS] is of valid type to have targeted the hook location. |
| * Note the allowed type checks are ORed. Evaluated only if source |
| * memory protection is satisfied. See also stronger validation |
| * in GBOP_EMULATE_SOURCE. |
| */ |
| GBOP_CHECK_INSTR_TYPE = 0x10, /* no source instruction type restriction if not set */ |
| GBOP_IS_CALL = 0x20, /* verify source is at all a CALL instruction */ |
| GBOP_IS_JMP = 0x40, /* FIXME: not needed - app JMP won't be seen on TOS */ |
| GBOP_IS_HOTPATCH_JMP = 0x80, /* our JMP in case we have hotpatched purported source */ |
| /* FIXME: we can't find the source if it was a JMP or JMP*, unless |
| * the caller explicitly wants to fool us with one. |
| * |
| * Note that in case of tail recursion elimination [TOS] is really |
| * of the caller of the previous function, should check that there |
| * are no internal XREFs to a hooked location, but we don't really |
| * care. |
| */ |
| |
| /* source instruction validation, if correct instruction type, |
| * check further whether it could have targeted our hook or it is |
| * used as chaff to bypass the previous simple validations. |
| */ |
| GBOP_EMULATE_SOURCE = 0x100, /* NYI */ |
| /* We do know that this was the previous instruction and there is |
| * no reason it should have lost its state in normal operations. |
| * All registers can be restored to original expected state when |
| * hooking at entry point, only ESP on say call [esp+8] is the |
| * hardest where should revert ESP a little bit to get back to |
| * original state. Of course call [esp-4] is impossible to |
| * recover since it will be overwritten, but not expected in real |
| * code. |
| * |
| * Needs to support CALL intrasegment to hook, CALL *eax or CALL |
| * *[IAT] intrasegment to hook, and CALL PLT -> JMP *[IAT] to hook. |
| * Other custom jump tables may get more messy. |
| */ |
| |
| /* target instruction check for simple ret2libc */ |
| GBOP_IS_RET_TO_ENTRY = 0x00200, /* NYI */ |
| |
| /* FIXME: See Szor's idea of checking whether PC=[ESP-4] as a |
| * check for RET_LIBC attack. Is at all that safe to do - would |
| * there be a valid program doing PUSH target, RET targeting the |
| * exported routines, or simply remnants from a stack frame where |
| * the entry point is pushed (e.g. register spill). Attacker |
| * could have used a RET 4 instr - then the API entry point is at |
| * [ESP-8] and can no longer be validated |
| */ |
| |
| /* FIXME: GBOP_WHEN_NATIVE_EXEC = 0x01000, NYI */ |
| /* should this be applied when running in native exec mode - need |
| * to tell apart native_exec from hotp_only .NET, Java, maybe VB. |
| * Today -gbop is not by default, and recommended to use only for |
| * hotp_only. This flag would be useful only when running in a |
| * future mix of -hotp_only and DR in the same process the two |
| * modes may need to differentiated. |
| */ |
| |
| GBOP_IS_DGC = 0x02000, |
| /* If set, allows returns to heap (not stack) if a known vm has been loaded. |
| * native_exec today runs all vms/dgc natively; gbop for dgc involves |
| * doing all the same bookkeepping to identify vms and uses -hotp_only |
| * (which uses native_exec), so they are the same. The bookkeepping may |
| * have to be split up if native_exec's definition changes. See case 8087. |
| * The main difference between just native_exec & gbop is that the former |
| * is used only to run a dll/dgc natively, not when the control is in dr, |
| * whereas in gbop it is used to avoid false positives for dgc. |
| */ |
| |
| GBOP_IS_FUTURE_EXEC = 0x04000, |
| /* using our tracking definition for allowing a region as a |
| * futureexec |
| */ |
| |
| GBOP_DIAGNOSE_SOURCE = 0x10000, /* NYI */ |
| /* all enabled checks are evaluated to allow diagnosing all |
| * failures, and evaluate any disabled OR checks to provide |
| * recommendations to workaround a false positive based on a |
| * single run without staging. |
| */ |
| |
| /* FIXME: we may want to further control whether the hooked |
| * locations for other purposes do a GBOP check, or leave it only |
| * to the 'extra' hooks from gbop_include_list */ |
| |
| /* default in client mode currently should be 0x6037 */ |
| GBOP_CLIENT_DEFAULT = GBOP_IS_DGC | GBOP_IS_FUTURE_EXEC | /* 0x06000 */ |
| GBOP_CHECK_INSTR_TYPE | GBOP_IS_CALL | /* 0x30 */ |
| GBOP_IS_EXECUTABLE | GBOP_IS_X | GBOP_IS_IMAGE /* 0x7 */ |
| }; |
| |
| extern bool gbop_vm_loaded; |
| |
| typedef struct { |
| const char *mod_name; |
| const char *func_name; |
| } gbop_hook_desc_t; |
| |
| const gbop_hook_desc_t * |
| gbop_get_hook(uint hook_index); |
| uint |
| gbop_get_num_hooks(void); |
| |
| bool |
| gbop_exclude_filter(const gbop_hook_desc_t *gbop_hook); |
| |
| bool |
| gbop_check_valid_caller(app_pc reg_ebp, app_pc reg_esp, app_pc cur_pc, |
| app_pc *violating_source_addr /* OUT */); |
| void |
| gbop_validate_and_act(app_state_at_intercept_t *state, |
| byte fpo_adjustment, |
| app_pc hooked_target); |
| #endif /* GBOP */ |
| |
| #endif /* ASLR_H */ |