Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save 2010phenix/acfa279d14b74671ee385dbfb0676eba to your computer and use it in GitHub Desktop.

Select an option

Save 2010phenix/acfa279d14b74671ee385dbfb0676eba to your computer and use it in GitHub Desktop.

Revisions

  1. @ondrasek ondrasek renamed this gist Jun 13, 2018. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions spanw-interactive-process.c → spawn-interactive-process.c
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,10 @@
    // spawn-interactive-process.cpp : Defines the entry point for the console application.
    // Do not forget to link against wtsapi32.lib
    // How to test this: use psexec from SysInternals, such as ```psexec -s c:\windows\system32\cmd.exe```
    // to run CMD under NT AUTHORITY\SYSTEM account (you can confirm this by running whoami) and then
    // run spawn-interactive-process (feel free to disable waiting for debugger). The result is a notepad process
    // running under interactive user credentials and on the interactive desktop launched from a service running under
    // system account.

    #include <stdio.h>
    #include <tchar.h>
  2. @ondrasek ondrasek revised this gist Jun 13, 2018. 2 changed files with 5 additions and 10 deletions.
    7 changes: 5 additions & 2 deletions spanw-interactive-process.c
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,10 @@
    // spawn-interactive-process.cpp : Defines the entry point for the console application.
    //
    // Do not forget to link against wtsapi32.lib

    #include "stdafx.h"
    #include <stdio.h>
    #include <tchar.h>
    #include <windows.h>
    #include <WtsApi32.h>

    void waitForDebugger()
    {
    8 changes: 0 additions & 8 deletions stdafx.h
    Original file line number Diff line number Diff line change
    @@ -1,8 +0,0 @@
    #pragma once

    #include "targetver.h"

    #include <stdio.h>
    #include <tchar.h>
    #include <windows.h>
    #include <WtsApi32.h>
  3. @ondrasek ondrasek revised this gist Jun 13, 2018. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions stdafx.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    #pragma once

    #include "targetver.h"

    #include <stdio.h>
    #include <tchar.h>
    #include <windows.h>
    #include <WtsApi32.h>
  4. @ondrasek ondrasek created this gist Jun 13, 2018.
    141 changes: 141 additions & 0 deletions spanw-interactive-process.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,141 @@
    // spawn-interactive-process.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"

    void waitForDebugger()
    {
    while (!IsDebuggerPresent())
    Sleep(1000);
    DebugBreak();
    }

    BOOL spawnProcess(HANDLE const hUserToken, PWSTR exeFileName)
    {
    BOOL result = FALSE;
    DWORD lastError = 0;
    PROCESS_INFORMATION processInfo;
    STARTUPINFO startupInfo;
    HANDLE hToken;

    ZeroMemory(&processInfo, sizeof(processInfo));
    ZeroMemory(&startupInfo, sizeof(startupInfo));
    startupInfo.cb = sizeof(startupInfo);

    result = DuplicateTokenEx(
    hUserToken,
    MAXIMUM_ALLOWED,
    NULL,
    SecurityImpersonation,
    TokenPrimary,
    &hToken);
    if (!result)
    return result;

    result = CreateProcessAsUser(
    hToken,
    (PWSTR) exeFileName,
    NULL,
    NULL,
    NULL,
    FALSE,
    CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_PROCESS_GROUP,
    NULL,
    NULL,
    &startupInfo,
    &processInfo);

    return result;
    }

    void dumpSession(WTS_SESSION_INFO_1* pSessionInfo)
    {
    printf("SessionId: %d\n", pSessionInfo->SessionId);
    printf("State: %d\n", pSessionInfo->State);
    printf("Domain: %ls\n", pSessionInfo->pDomainName);
    printf("Hostname: %ls\n", pSessionInfo->pHostName);
    printf("FarmName: %ls\n", pSessionInfo->pFarmName);
    printf("UserName: %ls\n", pSessionInfo->pUserName);
    printf("\n");
    }

    HANDLE getTokenFromSession(WTS_SESSION_INFO_1* pSessionInfo)
    {
    HANDLE hUserToken = 0;
    WTSQueryUserToken(pSessionInfo->SessionId, &hUserToken);
    return hUserToken;
    }

    BOOL adjustPrivileges()
    {
    LUID tcbPrivilege;
    HANDLE hToken = GetCurrentProcessToken();
    BOOL result = FALSE;
    TOKEN_PRIVILEGES tokenPrivileges;
    DWORD dwSize;

    result = LookupPrivilegeValue(NULL, SE_TCB_NAME, &tcbPrivilege);
    if (!result)
    goto error;

    tokenPrivileges.PrivilegeCount = 1;
    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tokenPrivileges.Privileges[0].Luid = tcbPrivilege;

    result = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, sizeof(tokenPrivileges), NULL, &dwSize);
    goto final;

    error:
    return FALSE;

    final:
    return TRUE;
    }

    int main()
    {
    BOOL retVal = FALSE;
    WTS_SESSION_INFO_1 *pSessionInfo = NULL;
    DWORD dwLevel = 1;
    DWORD dwCount = 0;
    HANDLE hWTSServer = WTS_CURRENT_SERVER_HANDLE;

    waitForDebugger();

    retVal = adjustPrivileges();
    if (!retVal)
    goto error;

    retVal = WTSEnumerateSessionsEx(
    hWTSServer,
    &dwLevel,
    0,
    &pSessionInfo,
    &dwCount);
    if (retVal == FALSE)
    goto error;

    for (unsigned int i = 0; i < dwCount; i++) {
    dumpSession(&pSessionInfo[i]);
    if (pSessionInfo[i].pUserName != NULL)
    {
    spawnProcess(
    getTokenFromSession(&pSessionInfo[i]),
    L"C:\\Windows\\Notepad.exe");
    }
    }

    goto final;

    error:
    printf("Error: %d.\n", GetLastError());
    goto final;

    final:
    if (pSessionInfo != NULL) {
    WTSFreeMemoryEx(WTSTypeSessionInfoLevel1, (void*)pSessionInfo, dwCount);
    pSessionInfo = NULL;
    }

    return 0;
    }