Skip to content

scc_lib.dll loaded with bare LoadLibrary (search-order/dependency hijack) #138

@JustinMDotNet

Description

@JustinMDotNet

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:

  1. 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.

  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions