6

I have a block of of code

if(!CreateProcessWithLogonW(
    szUserName,
    NULL,
    szPassword,
    LOGON_WITH_PROFILE,
    L"C:\\Windows\\System32\\cmd.exe", // file to execute
    NULL,              
    NORMAL_PRIORITY_CLASS | CREATE_BREAKAWAY_FROM_JOB,   // creation flags
    NULL,              // pointer to new environment block 
    NULL,              // name of current directory 
    &si,               // pointer to STARTUPINFO structure
    &pi                // receives information about new process
    )){
        ReportError(L"Create Process");
    }

ReportError is not invoked, but csrss.exe pops up with Startup error

What am I doing wrong?!

The username and password ARE correct.

the whole file:

// cmd.cpp : Defines the entry point for the console application.
//

#include <Windows.h>
#include <Lmcons.h>
#include <iostream>
#include <ctype.h>
#include <string>
#include <stdio.h>

#define winstring LPWSTR
#define stcas(x) static_cast<x>
#define INFO_BUFFER_SIZE    260 

using namespace std;

void ReportError(LPCWSTR pszFunction, DWORD dwError = GetLastError()) 
{ 
    wprintf(L"%s failed w/err 0x%08lx\n", pszFunction, dwError); 
} 

int main()
{
    TCHAR un[UNLEN+1];
    DWORD size = UNLEN + 1;
    GetUserName(un, &size);

    string una(un);

    bool sys = !una.compare("SYSTEM");

    /*
    if(!sys) {
        system("cls");
        system("title Command Prompt");
        system("cmd");
        return 0;
    }
    */


    wchar_t szUserName[INFO_BUFFER_SIZE] = {}; 
    wchar_t szPassword[INFO_BUFFER_SIZE] = {}; 
    wchar_t *pc = NULL; 
    HANDLE hToken = NULL; 
    BOOL fSucceeded = FALSE; 
    BOOL logon = FALSE;


    printf("Enter the username: "); 
    fgetws(szUserName, ARRAYSIZE(szUserName), stdin); 
    pc = wcschr(szUserName, '\n'); 
    if (pc != NULL) *pc = '\0';  // Remove the trailing L'\n' 

    cout << endl;
    //string un(szUserName);

    printf("Enter the password: "); 
    fgetws(szPassword, ARRAYSIZE(szPassword), stdin); 
    pc = wcschr(szPassword, '\n'); 
    if (pc != NULL) *pc = '\0';  // Remove the trailing L'\n'



    if (!LogonUserW(szUserName, NULL, szPassword,  LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken)) 
    {
        ReportError(L"Logon");
        goto Cleanup; 
    } 
    else logon = true;

    HANDLE phToken = NULL;

    BOOL dup = FALSE;

    if(!DuplicateTokenEx(hToken, TOKEN_DUPLICATE|TOKEN_IMPERSONATE|TOKEN_QUERY, NULL, SecurityImpersonation, TokenPrimary, &phToken)){
        ReportError(L"DUPLICATE TOKEN");
    }

    else dup = TRUE;

    // Impersonate the logged on user. 
    if (!ImpersonateLoggedOnUser(phToken)) 
    { 

        ReportError(L"imp");
        goto Cleanup; 
    } 

    fSucceeded = true;

    Cleanup: 

    // Clean up the buffer containing sensitive password. 


    LPTSTR szCmdline[] = {"cmd"};
    STARTUPINFOW si;
    PROCESS_INFORMATION pi;

    TCHAR uni[UNLEN+1];
    DWORD sizei = UNLEN + 1;
    GetUserName(uni, &sizei);

    string unai(uni);
    cout << unai << endl;

    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);



    system("pause");

    // If the impersonation was successful, undo the impersonation. 
    if (fSucceeded && logon) 
    { 
        system("cls");
        system("title Command Prompt");
        //system("cmd");

        if(!CreateProcessWithLogonW(
        szUserName,
        NULL,
        szPassword,
        LOGON_WITH_PROFILE,
        L"cmd.exe", // file to exec
        NULL,              
        NORMAL_PRIORITY_CLASS | CREATE_BREAKAWAY_FROM_JOB,   // creation flags
        NULL,              // pointer to new environment block 
        NULL,              // name of current directory 
        &si,               // pointer to STARTUPINFO structure
        &pi                // receives information about new process
        )){
            ReportError(L"Create Process");
        }
        if (!RevertToSelf()) 
        {  
            ReportError(L"Undo Imp");
        } 

    }
    SecureZeroMemory(szPassword, sizeof(szPassword));
    system("pause");
}
nimsson
  • 930
  • 1
  • 14
  • 27
  • That block of code is probably never even reached. Something else is wrong and it has nothing to do with that code. – Carey Gregory Mar 24 '14 at 04:39
  • It is always reached. When I enter an invalid password, the CreateProcessWithLogonW function returns the invalid username/password error code. – nimsson Mar 24 '14 at 13:05
  • What context is the code running? Desktop app? – David Heffernan Mar 24 '14 at 13:56
  • Oh, you're getting that error from the call to `CreateProcessWithLogonW`? I got the impression you were getting it when you launched your app. Is this application running as a system service? – Carey Gregory Mar 24 '14 at 14:28
  • It will be, but I am currently testing with my own elevated account (run as admin) and type in the password for that same account. @CareyGregory – nimsson Mar 24 '14 at 20:09
  • @DavidHeffernan it's a console application. – nimsson Mar 24 '14 at 20:13
  • That code works fine for me regardless of whether the user credentials I pass are admin or not. The error code you're getting back also doesn't make much sense. I think we'd need to see more code to even begin to guess what the issue is. – Carey Gregory Mar 24 '14 at 22:12
  • @CareyGregory I have posted the code now. – nimsson Mar 25 '14 at 20:49
  • Your code works for me if I skip the calls to `LogonUser`, `DuplicateToken` and `ImpersonateLoggedOnUser`. I don't see why you would want to impersonate another user in order to call `CreateProcessWithLogon`. `CreateProcessWithLogon` basically does that for you. – Carey Gregory Mar 25 '14 at 21:32

1 Answers1

5

The code you posted works for me if I skip the calls to LogonUser, DuplicateToken and ImpersonateLoggedOnUser. You don't want to impersonate another user in order to call CreateProcessWithLogon since it basically does that for you, so just remove all that logic to do the impersonation.

Impersonating a user could also cause your program to be unable to launch an application at all if the target application requires a higher level of privilege than the user has.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47