Results 1 to 13 of 13

Thread: [VB6] Run process as TrustedInstalled (NT AUTHORITY\SYSTEM) w/ full system privileges

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Lightbulb [VB6] Run process as TrustedInstalled (NT AUTHORITY\SYSTEM) w/ full system privileges

    Name:  RunAsTI2.jpg
Views: 5573
Size:  104.3 KB
    RunAs TrustedInstaller (NT AUTHORITY\SYSTEM)
    VB6 Version 2.0 (Updated 24 Feb 2022)
    twinBASIC Version 2.3.2 (Updated 16 Apr 2025)

    If you've been running Windows 10, 11, and even to some extent 7, you've no doubt found even a so-called Administrator account doesn't have permission to do many things. Certain files, registry keys, etc, can only be accessed with the SYSTEM account under which many OS services run. TrustedInstaller is particularly privileged among system processes: It's the owner of many protected files and registry keys, so even just running as SYSTEM would leave you needing adjust permissions to take ownership (which you might not even be able to do) before altering them. So if you look at programs that do one of the most highly protected operations, disabling Windows Defender, they impersonate this process rather than simply run as SYSTEM (and why programs like AdvancedRun have 'Run as TrustedInstaller' as a separate option in addition to 'Run as SYSTEM').

    This code shows you how to use the undocumented API NtImpersonateThread to have your thread impersonate TrustedInstaller, which allows full access to duplicate it's security token and start a process with the same privileges, running as the NT AUTHORITY\SYSTEM user. A big advantage of doing it this way is that we don't have to be running as a service, like the methods used by some other privilege escalating techniques.

    Nirsoft's AdvancedRun has a feature to do this, but which sadly isn't open source much less written in VB, so I wanted to create something like it in VB6. I'll probably add more features like it has in the future, but this was the most complicated and useful.

    Important: You must use Run As Administrator to use this code; it simply allows an admin to be an actual admin, it cannot escalate a unprivileged normal user to administrator. It does appear to work when run from the IDE, but that will of course need to also have been run with administrator privileges.
    Also, while the code is fully Unicode-supporting, the built-in VB6 TextBox is of course not. If you need to launch a command line with non-ASCII characters, you can replace the TextBox with one that supports Unicode, or otherwise pass Unicode strings to the LaunchAsTI function.

    Requirements
    No external requirements, but the program does require a manifest with Common Controls 6 enabled to show the security shield icon on the button.

    I've only tested this code on Windows 10 (1809/Enterprise LTSC), but it should work on all versions from XP through 11.


    Version 2.0 Changes
    -Added support for command line arguments. You can enter them with normal syntax: If the path to the program has a space, you must put it in quotes. Examples:
    Code:
    "C:\folder name\prog.exe" /arg
    C:\path\prog.exe "C:\folder\filearg"
    C:\prog.exe -a -b -c:d
    Arguments parsed by PathGetArgsW in shlwapi.dll
    CreateProcessWithTokenW, like CreateProcess supports command line arguments via setting both lpApplicationName and lpCommandLine. The trick is you have to pass just the path as the former, and the full path+args as the latter.
    IMPORTANT: Supporting arguments this way means that even if you have none, if there's a space, the path must be enclosed in quotes, e.g.
    "C:\Program Files\Process Hacker 2\ProcessHacker.exe"


    -Error messages now have their descriptions looked up.

    -Replaced the 3-second wait for the TrustedInstaller service to start with continuous monitoring with system-suggested wait. This will avoid false errors on a busy system or if e.g. a hard drive spinup pauses the service launch.
    This also saved us from having to search for the process id as the QueryServiceStatusEx call returns that information.


    How the code works:
    (incomplete snippets included for conceptual illustration, download the entire project for complete code)

    1. The SeDebugPrivilege and SeImpersonatePrivilege privileges are enabled with AdjustTokenPrivileges so we can play around with other processes.
      Code:
      lRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken)
          If SetPrivilege(hToken, SE_DEBUG_NAME, True) Then
      [...]
          If SetPrivilege(hToken, SE_IMPERSONATE_NAME, True) Then
    2. This is used to access the token for winlogon.exe and use ImpersonateLoggedOnUser to elevate our access.
      Code:
      Dim hWinLogon As Long
      Dim pidWinLogon As Long
      pidWinLogon = FindProcessByName("winlogon.exe")
      If pidWinLogon Then
          hWinLogon = OpenProcess(PROCESS_DUP_HANDLE Or PROCESS_QUERY_INFORMATION, 0&, pidWinLogon)
          If hWinLogon Then
              lRet = OpenProcessToken(hWinLogon, TOKEN_QUERY Or TOKEN_DUPLICATE, hSysTkn)
              If lRet Then
                  If ImpersonateLoggedOnUser(hSysTkn) Then
    3. We start the TrustedInstaller service via Service APIs (and ignore any 'already running' error).
      Code:
      hSCM = OpenSCManagerW(0&, 0&, SC_MANAGER_ALL_ACCESS)
      hSvc = OpenServiceW(hSCM, StrPtr("TrustedInstaller"), SERVICE_START)
      hr = StartServiceW(hSvc, 0&, 0&)
    4. We use CreateToolhelp32Snapshot to get a list of running processes, identify the process id of the TrustedInstaller service, then use the same API to get a list of threads to find TI's thread.
      Code:
      hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0&)
      If hSnapshot Then
          te32.dwSize = Len(te32)
          hr = Thread32First(hSnapshot, te32)
          Do
              If te32.th32OwnerProcessID = pid Then
                  GetFirstThreadId = te32.th32ThreadID
                  Exit Function
              End If
          Loop While Thread32Next(hSnapshot, te32)
      End If
    5. NtImpersonateThread is used to have our thread impersonate TrustedInstaller.
      Code:
                  hThread = OpenThread(THREAD_DIRECT_IMPERSONATION, 0&, hTiTid)
                  If hThread Then
                      Dim sqos As SECURITY_QUALITY_OF_SERVICE
                      sqos.Length = Len(sqos)
                      sqos.ImpersonationLevel = SecurityImpersonation
                      status = NtImpersonateThread(GetCurrentThread(), hThread, sqos)
    6. Since it's now in our thread, we can open 'our' token (impersonating TI) with TOKEN_ALL_ACCESS and duplicate it.
      Code:
      lRet = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, 0&, hTiToken)
      Dim satr As SECURITY_ATTRIBUTES
      Dim hStolenToken As Long
      satr.nLength = Len(satr)
      lRet = DuplicateTokenEx(hTiToken, MAXIMUM_ALLOWED, VarPtr(satr), SecurityImpersonation, TokenImpersonation, hStolenToken)
    7. The duplicate token can now be used with CreateProcessWithTokenW to start a process with the fully privileged token copied from TrustedInstaller running as NT AUTHORITY\SYSTEM.
      Code:
          Dim tStartInfo As STARTUPINFOW
          Dim tProcInfo As PROCESS_INFORMATION
          
          sDesktop = "WinSta0\Default"
          tStartInfo.cbSize = Len(tStartInfo)
          tStartInfo.lpDesktop = StrPtr(sDesktop)
           
          LaunchAsTI = CreateProcessWithTokenW(hStolenToken, LOGON_WITH_PROFILE, 0&, StrPtr(sCommandLine), CREATE_UNICODE_ENVIRONMENT, 0&, 0&, tStartInfo, tProcInfo)

    You can start something like ProcessExplorer or ProcessHacker, and right in the titlebar it will note it's running as SYSTEM, and you'll see all the stuff that previously just said access denied, even if you ran as administrator.


    Thanks

    This project was based on Norbert Federa's run-as-trustedinstaller and APTortellini's unDefender.

    SetPrivilege function borrowed from Nayan Patel at BinaryWorld's code found here. Some declares from DavidUK's Viewing Token Privileges CodeBank project.

    Background: The Art of Becoming TrustedInstaller.




    The VB6 version attached to this post is out of date and missing features and fixes of the latest version.

    The twinBASIC version is the latest (v2.3.2, 15 Apr 2025) and the project source and binaries can be found in the project repository: https://github.com/fafalone/RunAsTrustedInstaller
    Attached Files Attached Files
    Last edited by fafalone; Apr 17th, 2025 at 12:01 PM. Reason: Clarified why TrustedInstaller is useful beyond SYSTEM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width