📄 createprocessasuser.cpp
字号:
/////////////////////////////////////////////////////////////
// CreateProcessAsUser.cpp
//
// Written by Valery Pryamikov (1999)
//
// Command line utility that executes a command under specified user identity
// by temporarily installing itself as a service.
//
// Based on Keith Brown's AsLocalSystem utility (http://www.develop.com/kbrown)
// Uses some code from Mike Nelson's dcomperm sample utility
// and from tlist sample (Microsoft Source Code Samples)
//
// Use:
// CreateProcessAsUser.exe [-i[nteractive]]|[-s[ystem]]|
// [-u"UserName" -d"DomainName" -p"Password"]|[-a"AppID"] command
// Command must begin with the process (path to the exe file) to launch
// -i process will be launched under credentials of the
// "Interactive User" (retrieved from winlogon\shell process)
// -a process will be launched under credentials of the user
// specified in "RunAs" parameter of AppID.
// -s process will be launched as local system
// -u -d -p process will be launched on the result token of the
// LogonUser(userName,domainName,password,LOGON32_LOGON_BATCH...)
//
// either (-s) or (-i) or (-a) or (-u -d -p) parameters must supplied
//
// Examples:
// CreateProcessAsUser -s cmd.exe
// CreateProcessAsUser -a"{731A63AF-2990-11D1-B12E-00C04FC2F56F}" winfile.exe
//
/////////////////////////////////////////////////////////////
#define _WIN32_WINNT 0x400
#include <windows.h>
#include <stdio.h>
#include "common.h"
#include <ntsecapi.h>
#pragma comment( lib, "advapi32.lib" )
#define E_OBJ_IS_A_SERVICE 0x80040500
#define E_NO_RUN_AS_DATA 0x80040501
#define E_RUN_AS_INTERACTIVE 0x80040502
#define E_NO_INTERACTIVE_SESSION 0x80040503
#define E_SHELL_NOT_FOUND 0x80040504
#define GUIDSTR_MAX 38
#define MAX_TASKS 256
#define MAX_CMD_LEN 8192
HRESULT GrantDesktopAccess(HANDLE hToken);
HRESULT GetProcessToken(DWORD dwProcessID, LPHANDLE token, DWORD nUserNameMax, LPWSTR szwUserName, DWORD nUserDomainMax, LPWSTR szwUserDomain)
{
HANDLE hProcess=OpenProcess(PROCESS_DUP_HANDLE|PROCESS_QUERY_INFORMATION,TRUE,dwProcessID);
HRESULT retval = S_OK;
if(hProcess) {
HANDLE hToken = INVALID_HANDLE_VALUE;
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) retval = HRESULT_FROM_WIN32(GetLastError());
else {
BYTE buf[MAX_PATH]; DWORD dwRead = 0;
if (!GetTokenInformation(hToken, TokenUser, buf, MAX_PATH, &dwRead)) retval = HRESULT_FROM_WIN32(GetLastError());
else {
TOKEN_USER *puser = reinterpret_cast<TOKEN_USER*>(buf);
SID_NAME_USE eUse;
if (!LookupAccountSid(NULL, puser->User.Sid, szwUserName, &nUserNameMax, szwUserDomain, &nUserDomainMax, &eUse))
retval = HRESULT_FROM_WIN32(GetLastError());
}
if (FAILED(retval)) return retval;
if (!DuplicateTokenEx(hToken,
TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
NULL, SecurityImpersonation, TokenPrimary,token))
retval = HRESULT_FROM_WIN32(GetLastError());
else retval = S_OK;
CloseHandle(hToken);
}
CloseHandle(hProcess);
} else retval = HRESULT_FROM_WIN32(GetLastError());
return retval;
}
HRESULT GetInteractiveUserToken(LPHANDLE token, DWORD nUserNameMax, LPWSTR szwUserName, DWORD nUserDomainMax, LPWSTR szwUserDomain)
{
HKEY registryKey;
ULONG returnValue = RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_READ, ®istryKey);
if (returnValue != ERROR_SUCCESS) return HRESULT_FROM_WIN32(returnValue);
DWORD valueType;
DWORD valueSize = (MAX_PATH+1)*sizeof(WCHAR);
WCHAR process[MAX_PATH+1];
memset(process,0,sizeof(process));
returnValue = RegQueryValueEx(registryKey, L"Shell", NULL, &valueType, (BYTE*)process, &valueSize);
RegCloseKey(registryKey);
if (returnValue != ERROR_SUCCESS) return E_NO_INTERACTIVE_SESSION;
if (wcslen(process)==0) return E_NO_INTERACTIVE_SESSION;
WCHAR *p = wcsrchr( process , L'.' );
if (p) {
p[0] = L'\0';
}
for (p = process; *p!=L'\0'; p++) *p = _totupper(*p);
TASK_LIST tlist[MAX_TASKS];
memset(tlist,0, sizeof(tlist));
DWORD numTasks = GetTaskListNT( tlist, MAX_TASKS );
WCHAR tname[MAX_PATH+1];
memset(tname,0,sizeof(tname));
for (DWORD i=0; i<numTasks; i++) {
tname[0] = 0;
wcscpy( tname, tlist[i].ProcessName );
p = wcsrchr( tname, L'.' );
if (p) {
p[0] = L'\0';
}
if (MatchPattern( tname, process)) {
return GetProcessToken(tlist[i].dwProcessId, token, nUserNameMax, szwUserName, nUserDomainMax, szwUserDomain);
} else if (MatchPattern( tlist[i].ProcessName, process )) {
return GetProcessToken(tlist[i].dwProcessId, token, nUserNameMax, szwUserName, nUserDomainMax, szwUserDomain);
} else if (MatchPattern(tlist[i].WindowTitle, process)) {
return GetProcessToken(tlist[i].dwProcessId, token, nUserNameMax, szwUserName, nUserDomainMax, szwUserDomain);
}
}
return E_SHELL_NOT_FOUND;
}
HRESULT GetRunAsPassword (LPWSTR AppID, int nPasswordMax, LPWSTR szwPassword, int nUserNameMax, LPWSTR szwUserName, int nUserDomainMax, LPWSTR szwUserDomain)
{
LSA_OBJECT_ATTRIBUTES objectAttributes;
HANDLE policyHandle = NULL;
LSA_UNICODE_STRING lsaKeyString;
PLSA_UNICODE_STRING lsaPasswordString;
WCHAR key [4 + GUIDSTR_MAX + 1];
ULONG returnValue;
WCHAR keyName [MAX_PATH+1];
HKEY registryKey;
wsprintf (keyName, L"AppID\\%s", AppID);
returnValue = RegOpenKeyEx (HKEY_CLASSES_ROOT, keyName, 0, KEY_READ, ®istryKey);
if (returnValue == ERROR_SUCCESS) {
DWORD valueType;
DWORD valueSize = 0;
returnValue = RegQueryValueEx (registryKey, L"LocalService", NULL, &valueType, NULL, &valueSize);
if (returnValue == ERROR_SUCCESS || returnValue == ERROR_MORE_DATA) return RegCloseKey (registryKey), E_OBJ_IS_A_SERVICE;
WCHAR principal[MAX_PATH+1];
valueSize = (MAX_PATH+1)*sizeof(WCHAR);
returnValue = RegQueryValueEx(registryKey, L"RunAs", NULL, &valueType, (BYTE*)principal, &valueSize);
RegCloseKey (registryKey);
if (returnValue != ERROR_SUCCESS) return E_NO_RUN_AS_DATA;
if (_wcsicmp(principal, L"Interactive User") == 0) return E_RUN_AS_INTERACTIVE;
LPCOLESTR ptmp = wcschr(principal, L'\\');
if (ptmp == 0) {
memset(szwUserDomain, 0, nUserDomainMax);
wcsncpy(szwUserName, principal, nUserNameMax);
} else {
memset(szwUserDomain, 0, nUserDomainMax);
wcsncpy(szwUserDomain, principal, min(nUserDomainMax, ptmp-principal));
wcsncpy(szwUserName, ptmp+1, nUserNameMax);
}
} else return E_NO_RUN_AS_DATA;
wcscpy (key, L"SCM:");
wcscat (key, AppID);
lsaKeyString.Length = (USHORT) ((wcslen (key) + 1) * sizeof (WCHAR));
lsaKeyString.MaximumLength = (GUIDSTR_MAX + 5) * sizeof (WCHAR);
lsaKeyString.Buffer = key;
//
// Open the local security policy
//
memset (&objectAttributes, 0x00, sizeof (LSA_OBJECT_ATTRIBUTES));
objectAttributes.Length = sizeof (LSA_OBJECT_ATTRIBUTES);
returnValue = LsaOpenPolicy (NULL,
&objectAttributes,
POLICY_GET_PRIVATE_INFORMATION,
&policyHandle);
if (returnValue != ERROR_SUCCESS)
return returnValue;
//
// Read the user's password
//
returnValue = LsaRetrievePrivateData (policyHandle,
&lsaKeyString,
&lsaPasswordString);
if (returnValue != ERROR_SUCCESS)
{
LsaClose (policyHandle);
return returnValue;
}
LsaClose (policyHandle);
wcsncpy (szwPassword, lsaPasswordString->Buffer, nPasswordMax);
LsaFreeMemory(lsaPasswordString->Buffer);
return ERROR_SUCCESS;
}
void Quit( const wchar_t* pszMsg, int nExitCode = 1 )
{
wprintf( L"%s\n", pszMsg );
exit( nExitCode );
}
void Err( const wchar_t* pszFcn, DWORD nErr = GetLastError() )
{
wchar_t szErrMsg[256];
wchar_t szMsg[512];
if ( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, nErr, 0, szErrMsg, sizeof szErrMsg / sizeof *szErrMsg, 0 ) )
swprintf( szMsg, L"%s failed: %s", szErrMsg );
else swprintf( szMsg, L"%s failed: 0x%08X", nErr );
Quit( szMsg );
}
void PrintUsageAndQuit()
{
Quit( L"Use:\n"
L"CreateProcessAsUser.exe [-i[nteractive]]|[-s[ystem]]|\n[-u\"UserName\" -d\"DomainName\" -p\"Password\"]|[-a\"AppID\"] Command\n\n"
L"Command must begin with the process (path to the exe file) to launch\n"
L"-i process will be launched under credentials of the\n"
L" \"Interactive User\" (retrieved from winlogon\\shell process)\n"
L"-a process will be launched under credentials of the user\n"
L" specified in \"RunAs\" parameter of AppID\n"
L"-s process will be launched as local system\n"
L"-u -d -p process will be launched on the result token of the\n"
L" LogonUser(userName,domainName,password,LOGON32_LOGON_BATCH...)\n"
L"\nEither -s or -i or -a or -u -d -p parameters must supplied\n"
L"\nExamples:\nCreateProcessAsUser -s cmd.exe\n"
L"CreateProcessAsUser -a\"{731A63AF-2990-11D1-B12E-00C04FC2F56F}\" winfile.exe\n"
L"\nWritten by Valery Pryamikov (1999)\n");
}
void* GetAdminSid()
{
SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
void* psid = 0;
if ( !AllocateAndInitializeSid( &ntauth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psid ) )
Err( L"AllocateAndInitializeSid" );
return psid;
}
void* GetLocalSystemSid()
{
SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
void* psid = 0;
if ( !AllocateAndInitializeSid( &ntauth, 1,
SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psid ) )
Err( L"AllocateAndInitializeSid" );
return psid;
}
bool IsAdmin()
{
bool bIsAdmin = false;
HANDLE htok = 0;
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &htok ) )
Err( L"OpenProcessToken" );
DWORD cb = 0;
GetTokenInformation( htok, TokenGroups, 0, 0, &cb );
TOKEN_GROUPS* ptg = (TOKEN_GROUPS*)malloc( cb );
if ( !ptg )
Err( L"malloc" );
if ( !GetTokenInformation( htok, TokenGroups, ptg, cb, &cb ) )
Err( L"GetTokenInformation" );
void* pAdminSid = GetAdminSid();
SID_AND_ATTRIBUTES* const end = ptg->Groups + ptg->GroupCount;
for ( SID_AND_ATTRIBUTES* it = ptg->Groups; end != it; ++it )
if ( EqualSid( it->Sid, pAdminSid ) )
break;
bIsAdmin = end != it;
FreeSid( pAdminSid );
free( ptg );
CloseHandle( htok );
return bIsAdmin;
}
bool IsLocalSystem()
{
bool bIsLocalSystem = false;
HANDLE htok = 0;
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &htok ) )
Err( L"OpenProcessToken" );
BYTE userSid[256];
DWORD cb = sizeof userSid;
if ( !GetTokenInformation( htok, TokenUser, userSid, cb, &cb ) )
Err( L"GetTokenInformation" );
TOKEN_USER* ptu = (TOKEN_USER*)userSid;
void* pLocalSystemSid = GetLocalSystemSid();
bIsLocalSystem = EqualSid( pLocalSystemSid, ptu->User.Sid ) ? true : false;
FreeSid( pLocalSystemSid );
CloseHandle( htok );
return bIsLocalSystem;
}
void StartAsService( int argc, const wchar_t* argv[] )
{
wchar_t szModuleFileName[MAX_PATH];
GetModuleFileName( 0, szModuleFileName, sizeof szModuleFileName / sizeof *szModuleFileName );
// come up with unique name for this service
SC_HANDLE hscm = OpenSCManager( 0, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE );
if ( !hscm )
Err( L"OpenSCManager" );
SC_HANDLE hsvc = 0;
for ( int nRetry = 0; nRetry < 2; ++nRetry )
{
hsvc = CreateService( hscm,
L"AsPrincipal",
L"AsPrincipal service",
SERVICE_START | SERVICE_QUERY_STATUS | DELETE,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
szModuleFileName,
0, 0,
0,
0, 0 );
if ( hsvc )
break;
else if ( ERROR_SERVICE_EXISTS == GetLastError() )
{
SC_HANDLE hsvc = OpenService( hscm, L"AsPrincipal", DELETE );
DeleteService( hsvc );
CloseServiceHandle( hsvc );
hsvc = 0;
// try again
}
else break;
}
if ( !hsvc )
Err( L"CreateService" );
if ( !StartService( hsvc, argc, argv ) )
Err( L"StartService" );
DeleteService( hsvc );
CloseServiceHandle( hsvc );
CloseServiceHandle( hscm );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -