Summary
scc_lib.dll is loaded with a bare LoadLibrary that does not pin the search path or apply any of the safe-search flags. Depending on what the game passes as the scc.exe command, this is either a DLL search-order hijack or a dependency-search hijack against scc_lib.dll's own imports.
Where
src/dll/Hooks/ExecuteProcess.cpp:26-32:
auto sccPath = std::filesystem::path(aCommand.c_str());
auto& sccLib = sccPath.replace_filename("scc_lib.dll");
auto sccHandle = LoadLibrary(sccLib.c_str());
Why it matters
Two separate problems:
-
If aCommand is ever a relative path ("scc.exe" or "r6\\scripting\\redscript\\scc.exe" without a drive letter), replace_filename produces a relative path, and LoadLibrary falls back to the standard search order: application directory, system directories, current directory, %PATH%. bin\x64 and the process working directory are user-writable, which is the textbook DLL-hijack surface.
-
Even when aCommand is absolute, scc_lib.dll's own dependencies are still resolved with the standard search order because no LOAD_LIBRARY_SEARCH_* flags are passed. A planted DLL with the same name as one of those dependencies wins.
Either case ends with attacker-controlled code running inside the game process at user privilege.
Suggested fix
Require an absolute path and use LoadLibraryEx with safe-search flags:
auto sccPath = std::filesystem::path(aCommand.c_str());
if (!sccPath.is_absolute())
{
spdlog::warn(L"Refusing to load scc_lib.dll from a relative path: '{}'", sccPath.native());
return Global_ExecuteProcess(a1, aCommand, aArgs, aCurrentDirectory, a5);
}
auto sccLib = sccPath.replace_filename(L"scc_lib.dll");
auto sccHandle = LoadLibraryExW(
sccLib.c_str(),
nullptr,
LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
The exact flag combination is up for discussion — LOAD_LIBRARY_SEARCH_DEFAULT_DIRS may also be appropriate depending on what scc_lib.dll actually needs. The point is that the bare LoadLibrary call is not acceptable for a DLL loaded into a game process.
Severity
High. The "absolute path" guard alone closes most of the surface; the safe-search flags close the rest.
Summary
scc_lib.dllis loaded with a bareLoadLibrarythat does not pin the search path or apply any of the safe-search flags. Depending on what the game passes as thescc.execommand, this is either a DLL search-order hijack or a dependency-search hijack againstscc_lib.dll's own imports.Where
src/dll/Hooks/ExecuteProcess.cpp:26-32:Why it matters
Two separate problems:
If
aCommandis ever a relative path ("scc.exe"or"r6\\scripting\\redscript\\scc.exe"without a drive letter),replace_filenameproduces a relative path, andLoadLibraryfalls back to the standard search order: application directory, system directories, current directory,%PATH%.bin\x64and the process working directory are user-writable, which is the textbook DLL-hijack surface.Even when
aCommandis absolute,scc_lib.dll's own dependencies are still resolved with the standard search order because noLOAD_LIBRARY_SEARCH_*flags are passed. A planted DLL with the same name as one of those dependencies wins.Either case ends with attacker-controlled code running inside the game process at user privilege.
Suggested fix
Require an absolute path and use
LoadLibraryExwith safe-search flags:The exact flag combination is up for discussion —
LOAD_LIBRARY_SEARCH_DEFAULT_DIRSmay also be appropriate depending on whatscc_lib.dllactually needs. The point is that the bareLoadLibrarycall is not acceptable for a DLL loaded into a game process.Severity
High. The "absolute path" guard alone closes most of the surface; the safe-search flags close the rest.