/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Process.hpp Date: 2021-6-10 Author: Reece ***/ #pragma once #include "Paths.hpp" #include "ProcessMap.hpp" #include "IProcessSectionMapView.hpp" #include "IProcessSectionView.hpp" #include "ProcessEnvironment.hpp" #include "ProcessStartTime.hpp" namespace Aurora::Process { /** * @brief Aborts the current process with the provided exitcode * @param exitcode * @return */ AUKN_SYM AU_NORETURN void Exit(AuUInt32 exitcode); AUE_DEFINE(EModulePath, ( eModulePathCWD, eModulePathSystemDir, /// /usr/lib/, windir/system32 eModulePathUserDir, /// /usr/local/lib eProcessDirectory, /// eClassPath, //eOSSpecified, /// LD_LIBRARY_PATH + /etc/ld.so.conf, AddDllDirectory eSpecified )); // eModulePathSystemDir -> why /usr/lib and not /lib? // https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/ // Arch 2012: https://archlinux.org/news/the-lib-directory-becomes-a-symlink/ // Ubuntu 2018 (mandatory 2021+): https://lists.ubuntu.com/archives/ubuntu-devel-announce/2018-November/001253.html https://wiki.debian.org/UsrMerge // Fedora (2011?): https://fedoraproject.org/wiki/Features/UsrMove static AuList kUserOverloadableSearchPath = { EModulePath::eSpecified, EModulePath::eModulePathCWD, EModulePath::eClassPath, EModulePath::eProcessDirectory, EModulePath::eModulePathUserDir, EModulePath::eModulePathSystemDir }; static AuList kAdminOverloadableSearchPath = { EModulePath::eSpecified, EModulePath::eModulePathSystemDir, EModulePath::eProcessDirectory, EModulePath::eClassPath, EModulePath::eModulePathCWD, EModulePath::eModulePathUserDir }; static AuList kSpecifiedPath = { EModulePath::eSpecified, EModulePath::eClassPath }; static AuList kSpecifiedPathStrict = { EModulePath::eSpecified }; static AuList kCWDPath = { EModulePath::eModulePathCWD }; static AuList kProcPath = { EModulePath::eProcessDirectory }; // Binding warning: this object takes references to references/pointers within the full-expressions (we live here) to parent scope[s] (your callframe lives here, with the provided temp string views). // this object is therefore not expected to outlive any references you pass at it. // we should only exist in the scope of FULL-EXPRESSION := { LoadModule({ ModuleLoadRequest: { temp raw string pointer view to anywhere valid throughout the call }}) } // binders will need to create a derived type to contain two AuStrings to fill mod and version. struct ModuleLoadRequest { inline ModuleLoadRequest() : searchPath(&kSpecifiedPathStrict) { } inline ModuleLoadRequest(const AuList &directories, const AuString &mod) : mod(mod), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict) {} inline ModuleLoadRequest(const AuList &directories, const AuROString &mod, const AuROString &version) : mod(mod), version(version), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict) {} inline ModuleLoadRequest(const AuROString &mod) : mod(mod), searchPath(&kAdminOverloadableSearchPath) {} inline ModuleLoadRequest(const AuROString &mod, const AuROString &version) : mod(mod), version(version), searchPath(&kAdminOverloadableSearchPath) {} AuROString mod; AuROString version; AuList const * specifiedSearchPaths {}; AuList const * searchPath {}; bool verify {}; // always effectively true if the executable is signed and enableMitigations is true bool unixCheckPlusX { true }; bool enableMitigations { true }; bool forceMitigations { false }; char padZero[128] { 0 }; }; /// Provides a scriptability style DLL suffix including the relevant file extension. /// I do not recommend trying to build DLL filenames yourself, use LoadModule instead. /// Different version, file extension, and unique suffix order and values may apply. AUKN_SYM AuROString GetViewOfAuroraDLLSuffix(); /// Provides the platform extension for dynamically linked objects. /// This may become before or after the version string, depending on the host platform style. /// I do not recommend trying to build DLL filenames yourself, use LoadModule instead. AUKN_SYM AuROString GetViewOfDynamicLibraryExtensionSuffix(); /// Provides the scriptability style architecture string for platform local build artefects. AUKN_SYM AuROString GetViewOfArchitectureSuffix(); /// @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'. /// You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of /// resolving the Aurora build ABI strings, falling back to "${request.mod}.${GetViewOfDynamicLibraryExtensionSuffix()}". /// @param request /// @return AUKN_SYM bool LoadModule(const ModuleLoadRequest &request); /// Updated version of LoadModule. /// Returns a VOID* handle to be used as a replacement for win32 LoadLibraryW(...) / posix dlopen(...), to be followed up by a/multiple GetProcessAddress / dlsym calls. /// GetProcAddressEx is to be used with this VOID* handle. AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request); /// Safe (without unloads) handle fetch of LoadModuleEx. AUKN_SYM void *GetProcHandle(const AuROString &name); /// Safe process address fetch a symbol inside of a nammed LoadModule object. AUKN_SYM AuMach GetProcAddress(const AuROString &mod, const AuRONString &symbol); /// Safe (without unloads) process address fetch a symbol inside of LoadModuleEx object. AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuRONString &symbol); /// Returns a copy of the directories in which the requests of LoadModule can be fulfilled. AUKN_SYM AuList GetBinaryClassPath(); /// Warning: in production applications, becareful about preloading binaries of unknown origin. /// /// Consider every directory in "list" to be within the perview of the plugin-write user group. /// Anybody, presumably the local user and all its processes, can write/install plugins, is capable of loading any arbitrary code whatsoever. /// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin. /// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support. /// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs). /// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks. /// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc). /// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly. /// /// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections. /// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts), /// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security. /// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks. /// /// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms. /// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work. /// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox. AUKN_SYM bool SetBinaryClassPath(const AuList &list, AuOptional optBoolPreloadAll = { false }); /// Warning: in production applications, becareful about preloading binaries of unknown origin. /// /// Consider every directory in "list" to be within the perview of the plugin-write user group. /// Anybody, the local user and its processes, who can write/install plugins, is capable of loading any arbitrary code whatsoever. /// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin. /// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support. /// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs). /// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks. /// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc). /// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly. /// /// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections. /// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts), /// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security. /// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks. /// /// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms. /// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work. /// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox. AUKN_SYM bool AddBinaryClassPath(const AuROString &dir, AuOptional optBoolPreloadAll = { false }); /// TODO: Most platforms *hate* unloading dynamic linked libraries. on the otherhand, artists writing native scripts love them. /// At some point, we'll probably add an API for unloading handles, and flushing out the internal cache table. /// If the platform ignores it, and we just load the old internal handle from the os loader, oh well... guess we dont have dynamic code reloading. }