trying to spawn a process (say an exe file) with different user crendentials than that of the current user but getting 1314 error
I am trying to spawn a process (say an exe file) with different user
crendentials than that of the current user.
1) Called LogonUserEx() to logon the user and recieve a handle to the
token that represents the logged-on user.
2) Called ImpersonateLoggedOnUSer() to let the calling thread
impersonate the security context of logged on user.
3) Used CreateEnvironmentBlock() to get lpEnv
GetUserProfileDirectory()
LoadUserProfile()
and then called CreateProcessAsUser() with appropriate arguments.
But this fails with the error 1314 : ERROR_NO_SUCH_PRIVILEGE when the
calling thread
has admin credentails.
Also tried another option of using CreateUserWithLogonW() but it
also gives Application failed to initialize error(0xc0000142)
The Code I used is as follows
#include "stdafx.h"
#include "Windows.h"
#include "winbase.h"
#include <stdio.h>
#include "Userenv.h"
#include <windows.h>
#include <strsafe.h>
//typedef basic_string<wchar_t> wstring;
void log(char*);
BOOL logonUser(HANDLE &h);
BOOL SetPrivilege(
HANDLE , // token handle
LPCTSTR , // Privilege to enable/disable
BOOL // TRUE to enable. FALSE to disable
);
BOOL createProcessAsUser(HANDLE&);
BOOL impersonateUser(HANDLE&);
BOOL createProcessWithLogon(HANDLE&);
void ReadToEnd(HANDLE& hRead);
int main()
{
HANDLE h;
logonUser(h);
impersonateUser(h);
createProcessAsUser(h);
return 0;
}
BOOL logonUser(HANDLE &h)
{
TCHAR* username = _T("SOMEUSER");
TCHAR* password = _T("SOMEPASSWORD");
TCHAR* domain = _T("SOMEDOMAIN");
DWORD logonType = LOGON32_LOGON_NEW_CREDENTIALS;
DWORD logonProvider =LOGON32_PROVIDER_WINNT50;
PSID ppLogonSid=NULL;
PVOID ppProfileBuffer=NULL;
DWORD pdwProfileLength=0;
QUOTA_LIMITS pQuotaLimits;
ZeroMemory(&pQuotaLimits, sizeof(pQuotaLimits));
BOOL ret = FALSE;
if ( (ret = LogonUserEx(username, domain, password, logonType,
logonProvider,
&h,&ppLogonSid,&ppProfileBuffer,&pdwProfileLength,&pQuotaLimits)) ==
FALSE
)
{
char buf[1000];
sprintf(buf, "LogonUser failed with error: %ld\n",
HRESULT_FROM_WIN32(GetLastError()));
log(buf);
}
else
{
log("LogonUser succeeded\n");
}
return ret;
}
BOOL impersonateUser(HANDLE& h)
{
BOOL ret = ImpersonateLoggedOnUser(h);
if (!ret )
{
char buf[1000];
sprintf(buf, "ImpersonateLoggedOnUser failed with error: %ld
\n", HRESULT_FROM_WIN32(GetLastError()));
log(buf);
}
else
{
log("ImpersonateLoggedOnUser succeeded\n");
}
return ret;
}
BOOL createProcessAsUser(HANDLE &h)
{
TCHAR *appName = _T("c:\\windows\\notepad.exe");
TCHAR *cmdline = _T("");
LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL;
LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
BOOL bInheritHandles = FALSE;
DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
void * lpEnv = NULL;
TCHAR* curDir = NULL;
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION pi;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&pi, 0, sizeof(pi));
siStartupInfo.cb = sizeof(siStartupInfo);
TCHAR* lpDesktop = _T("winsta0\\default");
siStartupInfo.lpDesktop = lpDesktop;
DWORD cchPath = 1024;
TCHAR szUserProfile[1024] = _T("");
PROFILEINFO pfi;
WCHAR szUserName[20];
_tcscpy( szUserName, _T("SOMEUSER") );
ZeroMemory( &pfi, sizeof(pfi) );
pfi.dwSize = sizeof(pfi);
pfi.lpUserName = szUserName;
pfi.dwFlags = PI_NOUI;
if (!CreateEnvironmentBlock(&lpEnv, h, TRUE))
log("CreateEnvironmentBlock failed");
if (!GetUserProfileDirectory(h, szUserProfile, &cchPath))
log("GetUserProfileDirectory failed");
// Load the profile. Since it doesn't exist, it will be created
if ( !LoadUserProfile(
h,
&pfi ) ) {
char msg[256];
sprintf(msg,"LoadUserProfile() failed. Error %d\n",
GetLastError() );
log(msg);
return -1;
}
BOOL ret = CreateProcessAsUser(h, appName, cmdline,
lpProcessAttributes, lpThreadAttributes, bInheritHandles,
dwCreationFlags, lpEnv, szUserProfile,
&siStartupInfo, &pi);
if(!ret)
{
char msg[256];
sprintf(msg,"CreateProcessAsUser() failed. Error %d\n",
GetLastError() );
log(msg);
}
else
{
log("CreateProcessAsUser succeeded\n");
}
if (!DestroyEnvironmentBlock(lpEnv)) {
log("DestroyEnvironmentBlock failed");
return FALSE;
}
if ( !UnloadUserProfile(
h,
pfi.hProfile ) ) {
char msg[256];
sprintf(msg,"UnloadUserProfile() failed. Error %d\n",
GetLastError() );
log(msg);
return -1;
}
if (!RevertToSelf()) {
log("RevertToSelf Failed");
return FALSE;
}
if (!CloseHandle(h)) {
log("CloseHandle Failed");
return FALSE;
}
return ret;
}
=================================================================
The Code for the other Option using CreateProcessWithLogonW is as
follows
Calls
LogonUser()
ImpersonateLoggedOnUser() as in the above code and then called the
following function:
BOOL createProcessWithLogon(HANDLE &hToken)
{
LPVOID lpvEnv;
DWORD cchPath = 1024;
TCHAR szUserProfile[1024] = _T("");
//TCHAR *appName = _T("D:\\Tutorial\\JoinTwoFile\\JoinTwoFile\
\ContinuousLogger\\bin\\Debug\\ContinuousLogger.exe");
TCHAR *appName = _T("d:\\pubcomps\\lmpub.exe");
TCHAR *cmdline = _T("\"c:\\windows\\notepad.exe\"");
TCHAR* username = _T("SOMEUSER");
TCHAR* password = _T("SOMEPASSWORD");
TCHAR* domain = _T("SOMEDOMAIN");
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
PROFILEINFO pfi;
WCHAR szUserName[20];
_tcscpy( szUserName, username );
ZeroMemory( &pfi, sizeof(pfi) );
pfi.dwSize = sizeof(pfi);
pfi.lpUserName = szUserName;
pfi.dwFlags = PI_NOUI;
SECURITY_ATTRIBUTES secAttr = {0};
secAttr.nLength = sizeof(secAttr);
secAttr.bInheritHandle = TRUE;
secAttr.lpSecurityDescriptor = NULL;
HANDLE fileHandle = CreateFile(_T("d:\\redirFile.txt"),
GENERIC_WRITE| GENERIC_READ, FILE_SHARE_READ| FILE_SHARE_WRITE,
&secAttr, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == fileHandle) {
log("CreateFile failed");
return FALSE;
}
HANDLE hPipeWr;
HANDLE hPipeRd;
if ( !CreatePipe(&hPipeRd, &hPipeWr, &secAttr, 0) ) {
log("CreatePipe failed");
return FALSE;
}
si.hStdOutput = hPipeWr;
SetHandleInformation( hPipeRd, HANDLE_FLAG_INHERIT, 0);
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
log("CreateEnvironmentBlock failed");
DWORD dwSize = sizeof(szUserProfile)/sizeof(TCHAR);
// Load the profile. Since it doesn't exist, it will be created
if ( !LoadUserProfile(
hToken,
&pfi ) ) {
char msg[256];
sprintf(msg,"LoadUserProfile() failed. Error %d\n",
GetLastError() );
log(msg);
return -1;
}
if (!GetUserProfileDirectory(hToken, szUserProfile, &cchPath))
log("GetUserProfileDirectory failed");
//
// TO DO: change NULL to '.' to use local account database
//
if (!CreateProcessWithLogonW(username, domain, password,
LOGON_WITH_PROFILE, NULL, cmdline,
NORMAL_PRIORITY_CLASS |CREATE_UNICODE_ENVIRONMENT, lpvEnv,
szUserProfile,
&si, &pi)) {
log("CreateProcessWithLogonW failed");
return FALSE;
}
else
{
log("createProcessWithLogonW suceeded");
}
if (!DestroyEnvironmentBlock(lpvEnv)) {
log("DestroyEnvironmentBlock failed");
return FALSE;
}
CloseHandle(hPipeWr);
// WaitForSingleObject(pi.hProcess, 0xffffffff);
//DWORD exitCode = 0;
//BOOL ret = GetExitCodeProcess(pi.hProcess, &exitCode);
//if(!ret)
//{
// char buf[1000];
// sprintf(buf, "GetExitCodeProcess failed with error: %ld\n",
HRESULT_FROM_WIN32(GetLastError()));
// log(buf);
//}
//else
//{
// log("GetExitCodeProcess succeeded\n");
//}
ReadToEnd(hPipeRd);
return TRUE;
}
void ReadToEnd(HANDLE& hRead)
{
DWORD dwRead, dwWritten;
CHAR chBuf[40];
// Read output from the child process, and write to parent's STDOUT.
for (;;)
{
if( !ReadFile( hRead, chBuf, 40, &dwRead,
NULL) || dwRead == 0) break;
fwrite(chBuf, sizeof(CHAR), dwRead, stdout);
}
}