[+] Aurora::Process::GetBinaryClassPath

[+] Aurora::Process::SetBinaryClassPath
[+] Aurora::Process::AddBinaryClassPath
[+] Aurora::Process::LoadModuleEx
[+] Aurora::Process::GetProcHandle
[+] Aurora::Process::GetProcAddressEx
[+] Aurora::ProcessConfig
[*] Cleanup a bit
This commit is contained in:
Reece Wilson 2023-10-11 00:21:32 +01:00
parent bee9b8b07b
commit 33f77cf011
5 changed files with 310 additions and 51 deletions

View File

@ -29,6 +29,7 @@ namespace Aurora::Process
eModulePathSystemDir, /// /usr/lib/, windir/system32
eModulePathUserDir, /// /usr/local/lib
eProcessDirectory, ///
eClassPath,
//eOSSpecified, /// LD_LIBRARY_PATH + /etc/ld.so.conf, AddDllDirectory
eSpecified
));
@ -40,18 +41,19 @@ namespace Aurora::Process
// 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<EModulePath> kUserOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathCWD, EModulePath::eProcessDirectory, EModulePath::eModulePathUserDir, EModulePath::eModulePathSystemDir};
static AuList<EModulePath> kAdminOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathSystemDir, EModulePath::eProcessDirectory, EModulePath::eModulePathCWD, EModulePath::eModulePathUserDir};
static AuList<EModulePath> kSpecifiedPath = {EModulePath::eSpecified};
static AuList<EModulePath> kCWDPath = {EModulePath::eModulePathCWD};
static AuList<EModulePath> kProcPath = {EModulePath::eProcessDirectory};
static AuList<EModulePath> kUserOverloadableSearchPath = { EModulePath::eSpecified, EModulePath::eModulePathCWD, EModulePath::eClassPath, EModulePath::eProcessDirectory, EModulePath::eModulePathUserDir, EModulePath::eModulePathSystemDir };
static AuList<EModulePath> kAdminOverloadableSearchPath = { EModulePath::eSpecified, EModulePath::eModulePathSystemDir, EModulePath::eProcessDirectory, EModulePath::eClassPath, EModulePath::eModulePathCWD, EModulePath::eModulePathUserDir };
static AuList<EModulePath> kSpecifiedPath = { EModulePath::eSpecified, EModulePath::eClassPath };
static AuList<EModulePath> kSpecifiedPathStrict = { EModulePath::eSpecified };
static AuList<EModulePath> kCWDPath = { EModulePath::eModulePathCWD };
static AuList<EModulePath> kProcPath = { EModulePath::eProcessDirectory };
struct ModuleLoadRequest
{
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod) : mod(mod), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPath)
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod) : mod(mod), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict)
{}
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod, const AuString &version) : mod(mod), version(version), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPath)
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod, const AuString &version) : mod(mod), version(version), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict)
{}
inline ModuleLoadRequest(const AuString &mod) : mod(mod), searchPath(&kAdminOverloadableSearchPath)
@ -79,6 +81,17 @@ namespace Aurora::Process
*/
AUKN_SYM bool LoadModule(const ModuleLoadRequest &request);
AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request);
AUKN_SYM AuMach GetProcAddress(AuString mod, AuString symbol);
AUKN_SYM void *GetProcHandle(const AuString &name);
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol);
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol);
AUKN_SYM AuList<AuString> GetBinaryClassPath();
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll = false);
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll = false);
}

View File

@ -409,6 +409,13 @@ namespace Aurora
AuUInt8 uSignalGAIOWorkerThreadDone { 28 };
};
struct ProcessConfig
{
bool bAlwaysPreloadEntireClassPath { false };
bool bForcePreload { false };
bool bEnablePreload { true };
};
struct RuntimeStartInfo
{
ConsoleConfig console;
@ -419,6 +426,7 @@ namespace Aurora
AuAlignTo<64, DebugConfig> debug;
AuAlignTo<32, ThreadingConfig> threadingConfig;
AuAlignTo<32, LinuxConfig> linuxConfig;
AuAlignTo<32, ProcessConfig> processConfig;
AuAlignTo<32, DummyConfig> padding;
};

View File

@ -137,6 +137,8 @@ namespace Aurora
ADD_GET_PROC(Kernel32, VerSetConditionMask)
ADD_GET_PROC(Kernel32, QueryPerformanceCounter)
ADD_GET_PROC(Kernel32, QueryPerformanceFrequency)
ADD_GET_PROC(Kernel32, RemoveDllDirectory)
ADD_GET_PROC(Kernel32, AddDllDirectory)
ADD_GET_PROC_BI2(Kernel32, PSAPILegacy, K32GetProcessMemoryInfo, GetProcessMemoryInfo)

View File

@ -239,6 +239,14 @@ namespace Aurora
);
#endif
inline BOOL(__stdcall *pRemoveDllDirectory)(
PVOID Cookie
);
inline PVOID(__stdcall *pAddDllDirectory)(
PCWSTR NewDirectory
);
inline INT(__stdcall *pGetAddrInfoExCancel)(
LPHANDLE lpHandle
);

View File

@ -40,6 +40,7 @@
namespace Aurora::Process
{
static AuFutexMutex gSpinLock;
static AuList<AuString> gClassPath;
static AuHashMap<AuString, void *> gModuleHandles;
static const bool kIsMainSigned = false;
@ -273,12 +274,12 @@ namespace Aurora::Process
}
#endif
static bool LoadModule(const AuString &name, const AuString &path)
static void *LoadModule(const AuString &name, const AuString &path)
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
if (!pLoadLibraryW)
{
return false;
return {};
}
auto handle = pLoadLibraryW(Locale::ConvertFromUTF8(path).c_str());
@ -296,11 +297,12 @@ namespace Aurora::Process
}
#endif
gModuleHandles.insert(AuMakePair(name, (void *)handle));
return true;
auto pRet = (void *)handle;
gModuleHandles.insert(AuMakePair(name, pRet));
return pRet;
}
static bool TryLoadModule(const AuString &path,
static void *TryLoadModule(const AuString &path,
#if defined(AURORA_IS_MODERNNT_DERIVED)
const AuString &abs,
#endif
@ -320,7 +322,7 @@ namespace Aurora::Process
{
SysPushErrorNested("Couldn't open existing file. Race exploit?");
fail = true;
return false;
return {};
}
auto absPath = AuIOFS::NormalizePathRet(abs);
@ -334,7 +336,7 @@ namespace Aurora::Process
SysPushErrorNested("Couldn't verify file {}", path);
fail = true;
AuWin32CloseHandle(mitigateTimeOfUse);
return false;
return {};
}
#else
AuLogWarn("Can't verify {} on this platform", path);
@ -350,13 +352,13 @@ namespace Aurora::Process
{
SysPushErrorNested("Couldn't open existing file. Race exploit?");
fail = true;
return false;
return {};
}
if ((sb.st_mode & S_IXUSR) == 0)
{
fail = true;
return false;
return {};
}
}
#endif
@ -377,7 +379,7 @@ namespace Aurora::Process
return returnValue;
}
static bool TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
static void *TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
{
AuString a = path + "/" + auDll;
AuString b = path + "/" + genericDll;
@ -412,34 +414,61 @@ namespace Aurora::Process
return {};
}
static bool TryLoadModule(EModulePath path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request)
static void *TryLoadModule(EModulePath path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request)
{
AuString pathA, pathB;
AuList<AuString> arrayPaths;
switch (path)
{
case EModulePath::eClassPath:
{
AU_LOCK_GUARD(gSpinLock);
arrayPaths = gClassPath;
break;
}
case EModulePath::eModulePathCWD:
if (!Process::GetWorkingDirectory(pathA)) return false;
{
if (!Process::GetWorkingDirectory(pathA))
{
return {};
}
break;
}
case EModulePath::eProcessDirectory:
if (!Process::GetProcDirectory(pathA)) return false;
{
if (!Process::GetProcDirectory(pathA))
{
return {};
}
break;
}
case EModulePath::eModulePathSystemDir:
{
pathA = AuIOFS::GetSystemLibPath().value_or(AuString {});
pathB = AuIOFS::GetSystemLibPath2().value_or(AuString {});
if (pathA.empty()) return false;
if (pathA.empty())
{
return {};
}
break;
}
case EModulePath::eModulePathUserDir:
{
pathA = AuIOFS::GetUserLibPath().value_or(AuString {});
pathB = AuIOFS::GetUserLibPath2().value_or(AuString {});
if (pathA.empty()) return false;
if (pathA.empty())
{
return {};
}
break;
}
//case EModulePath::eOSSpecified:
//
// break;
@ -452,27 +481,40 @@ namespace Aurora::Process
if (pathA.size())
{
if (TryLoadModule(pathA, auDll, genericDll, request, fail))
if (auto pRet = TryLoadModule(pathA, auDll, genericDll, request, fail))
{
return true;
return pRet;
}
if (fail)
{
return false;
return {};
}
}
if (pathB.size())
{
if (TryLoadModule(pathB, auDll, genericDll, request, fail))
if (auto pRet = TryLoadModule(pathB, auDll, genericDll, request, fail))
{
return true;
return pRet;
}
if (fail)
{
return false;
return {};
}
}
for (const auto &dir : arrayPaths)
{
if (auto pRet = TryLoadModule(dir, auDll, genericDll, request, fail))
{
return pRet;
}
if (fail)
{
return {};
}
}
@ -480,14 +522,14 @@ namespace Aurora::Process
{
for (const auto &val : *request.specifiedSearchPaths)
{
if (TryLoadModule(val, auDll, genericDll, request, fail))
if (auto pRet = TryLoadModule(val, auDll, genericDll, request, fail))
{
return true;
return pRet;
}
if (fail)
{
return false;
return {};
}
}
}
@ -496,13 +538,18 @@ namespace Aurora::Process
}
AUKN_SYM bool LoadModule(const ModuleLoadRequest &request)
{
return bool(LoadModuleEx(request));
}
AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request)
{
AU_LOCK_GUARD(gSpinLock);
auto h = gModuleHandles.find(request.mod);
if (h != gModuleHandles.end())
{
return true;
return h->second;
}
auto au = request.mod + ConstructAuDllSuffix();
@ -528,37 +575,47 @@ namespace Aurora::Process
auto searchPath = request.searchPath ? request.searchPath : &kUserOverloadableSearchPath;
for (EModulePath path : *searchPath)
{
if (TryLoadModule(path, au, base, request))
if (auto pRet = TryLoadModule(path, au, base, request))
{
return true;
return pRet;
}
}
return false;
}
AUKN_SYM AuMach GetProcAddress(AuString mod, AuString symbol)
{
AU_LOCK_GUARD(gSpinLock);
auto h = gModuleHandles.find(mod);
if (h == gModuleHandles.end())
{
SysPushErrorGen("Module {} is not loaded", mod);
return {};
}
auto handle = h->second;
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol)
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
if (!pGetProcAddress)
{
return {};
}
auto ret = reinterpret_cast<AuMach>(pGetProcAddress(reinterpret_cast<HMODULE>(handle), symbol.c_str()));
auto ret = reinterpret_cast<AuMach>(pGetProcAddress(reinterpret_cast<HMODULE>(pHandle), symbol.c_str()));
#else
auto ret = reinterpret_cast<AuMach>(dlsym(handle, symbol.c_str()));
auto ret = reinterpret_cast<AuMach>(dlsym(hapHandlendle, symbol.c_str()));
#endif
return ret;
}
AUKN_SYM void *GetProcHandle(const AuString &name)
{
AU_LOCK_GUARD(gSpinLock);
auto h = gModuleHandles.find(name);
if (h == gModuleHandles.end())
{
SysPushErrorGen("Module {} is not loaded", name);
return {};
}
return h->second;
}
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol)
{
auto ret = GetProcAddressEx(GetProcHandle(mod), symbol);
if (!ret)
{
@ -590,6 +647,177 @@ namespace Aurora::Process
#endif
}
static void PreloadDLLsDoOnce(const AuList<AuString> &dirs)
{
AU_DEBUG_MEMCRUNCH;
AuList<void *> cookieList;
#if defined(AURORA_PLATFORM_WIN32)
for (const auto dir : dirs)
{
void *pCookie {};
if (pRemoveDllDirectory)
{
if (pAddDllDirectory)
{
pCookie = pAddDllDirectory(AuLocale::ConvertFromUTF8(dir).c_str());
}
}
cookieList.push_back(pCookie);
}
#endif
for (const auto dir : dirs)
{
AuList<AuString> files;
AuList<AuString> sharedObjects;
if (!AuFS::FilesInDirectory(dir, files))
{
SysPushErrorIO("Couldn't readdir: {}", dir);
continue;
}
auto endingPattern = ConstructAuDllSuffix();
auto endingAlt = GetPlatformExt(Build::kCurrentPlatform);
for (const auto &file : files)
{
if (!(file.ends_with(endingPattern.c_str()) ||
file.ends_with(endingAlt)))
{
continue;
}
sharedObjects.push_back(file);
}
{
AuUInt uSuccess {};
do
{
uSuccess = 0;
for (auto itr = sharedObjects.begin();
itr != sharedObjects.end(); )
{
auto &sharedDLL = *itr;
AuLogDbg("[attempt] Loading shared object: {}", sharedDLL);
AuString a = dir + "/" + sharedDLL;
#if defined(AURORA_IS_MODERNNT_DERIVED)
AuString aAbs = dir + "/" + sharedDLL + ".";
#endif
bool fail {};
ModuleLoadRequest request { AuList<AuString>{ dir }, sharedDLL };
if (TryLoadModule(a,
#if defined(AURORA_IS_MODERNNT_DERIVED)
aAbs,
#endif
request,
fail
))
{
if (!fail)
{
AuLogDbg("[attempt] Loaded shared object: {}!", sharedDLL);
uSuccess++;
itr = sharedObjects.erase(itr);
}
else
{
itr++;
}
}
else
{
itr++;
}
}
}
while (uSuccess);
}
}
#if defined(AURORA_PLATFORM_WIN32)
for (const auto pCookie : AuExchange(cookieList, {}))
{
if (pRemoveDllDirectory)
{
if (pCookie)
{
pRemoveDllDirectory(pCookie);
}
}
}
#endif
}
static void PreloadDLLs(const AuString &dir)
{
AU_DEBUG_MEMCRUNCH;
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
{
PreloadDLLsDoOnce(gClassPath);
}
else
{
PreloadDLLsDoOnce({ dir });
}
}
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll)
{
AU_DEBUG_MEMCRUNCH;
AU_LOCK_GUARD(gSpinLock);
AuExchange(gClassPath, list);
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload))
{
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
{
PreloadDLLsDoOnce(gClassPath);
}
else
{
PreloadDLLsDoOnce(list);
}
}
return true;
}
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll)
{
AU_LOCK_GUARD(gSpinLock);
if (!AuTryInsert(gClassPath, dir))
{
return false;
}
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload))
{
PreloadDLLs(dir);
}
return true;
}
AUKN_SYM AuList<AuString> GetBinaryClassPath()
{
AU_LOCK_GUARD(gSpinLock);
return gClassPath;
}
void InitProcess()
{