CMDT - Ultra-lightweight Run-as-TrustedInstaller (Pure x64/x86 Assembly)

Discussion in 'MDL Projects and Applications' started by wesmar, Feb 6, 2026.

  1. ceo54

    ceo54 MDL Addicted

    Aug 13, 2015
    969
    466
    30
    Code:
    github.com
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. ceo54

    ceo54 MDL Addicted

    Aug 13, 2015
    969
    466
    30
    @wesmar BSoD issue mentioned in #16, I think is caused by ELAM drivers disabled. I re-enabled ELAM drivers and it appears to have resolved the issue.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. hkurttt

    hkurttt MDL Novice

    Jul 25, 2025
    5
    0
    0
    Password: github.com
     
  4. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    Environmental Note: TrustedInstaller Profile & Environment Isolation

    • The "Clean Profile" Phenomenon
      When using CMDT (or any tool spawning processes as NT SERVICE\TrustedInstaller), Windows does more than just switch the security token; it switches the entire operational environment. If you notice a "clean" state (default theme, missing app configs, default paths), this is not a bug. It is a mandatory security feature called System Profile Isolation.
    • Virtual Service Account (VSA) Architecture
      TrustedInstaller is not a standard user account; it is a Virtual Service Account.
      • Standard Admins have SIDs (Security Identifiers) assigned from the User pool.
      • TrustedInstaller uses a unique Service SID:
        Code:
        S-1-5-80-956008885-...
      In Windows architecture, every SID attempting to "log in" (even non-interactively) is assigned a profile. Since TI is a system service, its "Home" is not C:\Users\Username, but the System Profile directory.
    • Registry Hives & Filesystem Mapping
      When the
      Code:
      CreateProcessWithTokenW
      API is called, the following occurs:
      • HKCU Mapping: The HKEY_CURRENT_USER registry hive for a TI process does not point to the Admin's NTUSER.DAT. Instead, it maps to the System hive located at C:\Windows\System32\config\systemprofile.
      • Directory Structure: Upon the first execution of a GUI app in this context, Windows creates a standard profile structure (Desktop, AppData, Documents, etc.) inside the systemprofile folder.
      • Environment Variables: The
        Code:
        CreateEnvironmentBlock
        function pulls variables like %APPDATA% or %USERPROFILE% directly from the TI token, redirecting all I/O to the system-managed paths.
    • Why sharing the Admin Profile is an Engineering "Critical Stop"
      One might ask: "Why can't CMDT just use my current Admin settings?". There are three fundamental reasons for this isolation:
      • Administrator Agnosticism: On a machine with multiple active admins (e.g., via RDP), TrustedInstaller remains a single system-wide entity. If TI used Admin A's profile, Admin B would inadvertently be working with Admin A's private files and registry keys, breaking Session Isolation.
      • Permission Integrity: User profiles have restrictive ACLs. TrustedInstaller, being more powerful than SYSTEM, could accidentally alter permissions within a user's profile, making files inaccessible to the user after they return to a standard session (the so-called "permission screwing" effect).
      • Security Boundary: TI is meant for modifying protected system components. Isolating its profile ensures that any potential malware residing in a user's AppData\Temp is not automatically loaded or executed by the TI process during startup.
    • Impact on Third-Party Tools (e.g., Total Commander)
      Tools like Total Commander store .ini configurations in HKCU or %APPDATA%. In the TI context, %APPDATA% points to C:\Windows\System32\config\systemprofile\AppData\Roaming. Because this folder is initially empty, the application behaves as a "First Run" instance.

      Advantage: This ensures a "Vanilla" environment where no user-specific plugins, scripts, or macros can interfere with critical system operations.
    • Conclusion
      CMDT correctly implements the Token Impersonation mechanism. Running in a "Clean" system account is the only stable and secure way to operate with the highest privileges in Windows. Any attempt at Profile Redirection (injecting Admin paths into the TI token) would be highly unstable
     
  5. Xadiaris

    Xadiaris MDL Junior Member

    Apr 23, 2008
    64
    23
    0
    "C:\Windows\System32\config\systemprofile" is safe to delete this folder?
     
  6. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    YES!!!!
     
  7. Carlos Detweiller

    Carlos Detweiller Emperor of Ice-Cream
    Staff Member

    Dec 21, 2012
    8,076
    10,298
    270
    There is none.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  8. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    Special Version: Post-Logout Support & IFEO Hook

    I'm sharing a special 64-bit version of CMDT, specifically optimized to work even after the user logs out (e.g., on the logon screen). In my opinion, this is highly valuable, especially when performing operations on the main account where all files, including the Administrator registry hives, are unlocked.

    Key Features:
    • No Services / No File Mods: It doesn't create any system services or modify a single system file.
    • IFEO Debugger Hook: It utilizes the classic "Sticky Keys" method by adding a debugger entry to:
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe
    • Dynamic Path Detection: No matter what you name the file or where you place it (though System32\cmdt.exe is recommended), the tool automatically resolves the correct path for the registry entry.
    • Defender Auto-Exclusion: It automatically adds PowerShell-based exclusions for both the CMD console process and the CMDT process itself. Without this, Microsoft Defender would likely flag the IFEO injection.

    Usage:

    Code:
    cmdt -shift
    Installs the hook. Once executed, you can trigger CMDT (with TrustedInstaller privileges) by pressing SHIFT 5 times, even at the Windows login screen.
    Command executed: cmdt.exe -cli -new cmd.exe

    Code:
    cmdt -unshift
    Removes all registry entries and restores the original Sticky Keys functionality.

    Request for Technical Insight:
    I'm looking for information on specific registry keys or system behaviors regarding EDR/PatchGuard. I've noticed that sometimes, processes launched this way after a logout are terminated after a certain period.

    If anyone has knowledge on how to prevent the system from closing these processes (or which registry entry governs this session cleanup), please share! I can eventually find it via debugging and analysis, but I suspect some of you might already have this knowledge at your fingertips.

    Source code (Pure Assembly) and 64-bit binary attached below.
     

    Attached Files:

  9. Carlos Detweiller

    Carlos Detweiller Emperor of Ice-Cream
    Staff Member

    Dec 21, 2012
    8,076
    10,298
    270
    I don't have to enter any password for cmdt.zip. Is that only for the GH version?
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  10. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    Github has been scanned for years by Google and Microsoft, and browsers quickly flag it as a false-positive dirty tool, even though the code is of the highest quality. It's just that what the program does is highly controversial. Hence the password github.com. And if you can't download it here, I'll do the same, but for now it's OK :)
     
  11. Carlos Detweiller

    Carlos Detweiller Emperor of Ice-Cream
    Staff Member

    Dec 21, 2012
    8,076
    10,298
    270
    I can, just wanted clarification that the one from here needs no password.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  12. mictlan

    mictlan MDL Senior Member

    Nov 9, 2009
    251
    129
    10
    Thank you for this!
    Pure ASM is seen rarely these days - NICE!!
     
  13. crypticus

    crypticus MDL Senior Member

    Jun 29, 2015
    318
    143
    10
    #33 crypticus, May 1, 2026
    Last edited: May 1, 2026

    So we have no way to add a function to direct HKCU reg commands to the user? (like RunAsTI do?) then maybe u can add run as user function like not TI but privileged elevated administrator user like minsudo does
     
  14. Xadiaris

    Xadiaris MDL Junior Member

    Apr 23, 2008
    64
    23
    0
    You have full access, you can change anything.
     
  15. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    You can even log in as PPL/WinTCB. But this tool is my calling card in x64 Assembly—a keepsake for my grandchildren, showing that Grandpa used to write low-level code. I don’t want to bloat it into a larger size. Other tools in higher-level languages do that. As my colleague said, this has everything you need regarding permissions with massive performance. The name CmdT itself would also have to be changed - its last letter “T” stands for the TrustedInstaller token :)
     
  16. adric

    adric MDL Expert

    Jul 30, 2009
    1,527
    1,720
    60
    #36 adric, May 8, 2026
    Last edited: May 9, 2026
    I'm having a senior moment right now, but I can't get cmdt_x64.exe to show me all available options when run from a non-admin cmd prompt. The 1st thing I tried was the standard /? -? -help for a lot of commands, but nothing is listed. The Readme indicates running cmdt -help will give me a list which did not work for me. I also tried piping to >cmdt.txt, but the file ended up with 0-bytes. What am I missing?

    It seems like other commands like this: cmdt_x64.exe -cli net session >test.txt also do not produce any output when run from a non-admin command prompt. UAC Self-Elevation doesn't seem to be working for me in this case.
     
  17. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    I am very grateful for any errors you found.

    1. Missing /?, -?, -h, --help support

    • Currently, only -help is recognized (main.asm:66).
    • Unknown switches like -x do jump to show_usage (main.asm:732), so -h and --help would work if they were caught properly.
    • But /? starts with /, not -, so it falls into mode_file_run and tries to execute /? as a file.
    2. No output in non‑admin cmd, redirection yields 0 bytes

    • IsUserAnAdmin is checked before parsing arguments (main.asm:590-595).
    • If non‑admin, it immediately calls ShellExecuteEx with runas (line 656) → original process exits (line 662).
    • The elevated process is a separate process tree – it does not inherit the original cmd’s stdout.
    • AttachConsole(ATTACH_PARENT_PROCESS) inside show_usage attaches to the elevated copy’s parent (the UAC prompt’s parent), not to the original command prompt.
    • Redirection (>) from the original shell does nothing.
    Result:

    cmdt -help from a non‑admin cmd flashes an elevated window and > out.txt is empty. Same for cmdt -cli net session >test.txt.

    Everything has been fixed (x64 versions) and I'll be syncing GitHub shortly. It took a while because I missed this thread.
     

    Attached Files:

  18. adric

    adric MDL Expert

    Jul 30, 2009
    1,527
    1,720
    60
    With the zip above, I still get a flashing screen when running cmdt_x64.exe -cli net session in a non-admin command prompt and a 0-byte file when redirecting that net cmd.

    Help displays correctly.
     
  19. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    #39 wesmar, May 15, 2026
    Last edited: May 15, 2026
    (OP)
    A lot of changes and trickery. I'm doing a complete inventory in main.asm.
    Testing now with:
    Code:
    cmdt_x64.exe -cli net session >> out.txt

    I changed the file in the previous thread, but I'm separating files by responsibility, so after thorough testing to make sure there’s no regression I’ll update GitHub.
    P.S - “Help”- I'll do it properly later, after the tests
     
  20. wesmar

    wesmar MDL Member

    Apr 1, 2012
    181
    636
    10
    Changelog — 15.05.2026

    Current build available on GitHub, on the project site, and a few posts up. The first post has not been updated to preserve the download counter.

    Source Refactoring — Monolith Split Into Focused Modules

    One of the source code files for the x64 architecture, `main.asm`, had grown to 90 KB. It was split into several separate modules, which did not significantly affect the size of the compiled binary file or its performance:

    • main.asm — entry point, CLI/GUI dispatch, privilege table, global data
    • cli.asm — CLI mode and file-run dispatch; owns the relay protocol (-outfile)
    • help.asm — usage banner text and help-switch recognition (HelpCheckAndExit, ShowUsage)
    • relay.asm — non-admin output relay (NonAdminRelayLaunch)
    • install.asm — context menu registration and Sticky Keys IFEO hook management
    • strutil.asm — wide-character string helpers (wcscpy_p, wcscat_p, wcscmp_ci, wcscmp_token, wcslen_p, skip_spaces, DecryptWideStr)
    • process.asmCreateProcessWithTokenW wrapper
    • token.asm, window.asm — unchanged in responsibility, trimmed in size

    Fix: Output Redirection From a Non-Admin Shell

    Running cmdt -cli <command> >> out.txt (or any >, >>, | redirect) from a non-admin shell previously produced no output. The elevated child process was spawned in a new process tree by UAC and its stdout handle was disconnected from the caller's redirect target.

    The fix introduces a temp-file relay in relay.asm:

    • Non-admin parent creates a temp file via GetTempFileNameW.
    • Inserts internal token -outfile <path> into the argument string and launches the elevated child via ShellExecuteExW("runas"), waiting with WaitForSingleObject.
    • Elevated child (cli.asm, mode_cli_setup) opens the temp file with an inheritable GENERIC_WRITE handle and uses it as hStdOutput / hStdError for the spawned process.
    • After the child exits, the non-admin parent streams the temp file to its own STD_OUTPUT_HANDLE and deletes it.

    All of the following now work correctly from both admin and non-admin shells:

    Code:
    cmdt_x64.exe -cli net session >> out.txt
    cmdt_x64.exe -cli cmd /c whoami > result.txt
    cmdt_x64.exe -cli cmd /c icacls C:\Windows\servicing | findstr Everyone
    
    The relay is skipped for -new (detached console; no output to capture) and falls back to plain UAC self-elevation if temp-file creation fails.

    Fix: Help Switches Work Without Elevation and With Redirection

    cmdt -help, -h, --help, -?, /?, /h, /help previously triggered UAC self-elevation before printing anything — the elevated process had no console to write to and produced an empty file.

    The help check now runs in mainCRTStartup before IsUserAnAdmin(). HelpCheckAndExit in help.asm scans argv[1] for all seven recognized spellings. If a match is found, it calls ShowUsage and exits without ever invoking UAC.

    ShowUsage selects the output API via GetFileType(STD_OUTPUT_HANDLE): WriteConsoleW for a real console, WriteFile for a file or pipe. Both interactive display and cmdt -help > out.txt now produce correct output in all session types.