Skip to content

Commit

Permalink
Merge pull request #38 from pgrawehr/NonAdminExec
Browse files Browse the repository at this point in the history
Fix remote code execution if not locally logged in as admin
  • Loading branch information
poweradminllc committed Dec 14, 2020
2 parents c4d9923 + b4aa94e commit ac60aaa
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
52 changes: 50 additions & 2 deletions Remote.cpp
Expand Up @@ -117,6 +117,13 @@ void DeletePAExecFromRemote(LPCWSTR targetComputer, Settings& settings)
Log(StrFormat(L"Failed to cleanup [%s] on %s.", dest, targetComputer), gle);
break;
}

if (!BAD_HANDLE(settings.hUserImpersonated))
{
::RevertToSelf();
::CloseHandle(settings.hUserImpersonated);
settings.hUserImpersonated = INVALID_HANDLE_VALUE;
}
}

bool CopyPAExecToRemote(Settings& settings, LPCWSTR targetComputer)
Expand Down Expand Up @@ -247,6 +254,23 @@ void StopAndDeleteRemoteService(LPCWSTR remoteServer, Settings& settings)
::CloseServiceHandle(hSCM);
}

// Strips the domain name from an user name string, if given as domain\user or user@domain
CString RemoveDomainFromUserName(CString user)
{
CString ret = user;
int idx = user.Find(L"\\");
if (idx != -1)
{
ret.Delete(0, idx + 1);
}
idx = user.Find(L"@");
if (idx != -1)
{
ret = ret.Left(idx);
}
return ret;
}

// Installs and starts the remote service on remote machine
bool InstallAndStartRemoteService(LPCWSTR remoteServer, Settings& settings)
{
Expand All @@ -267,12 +291,36 @@ bool InstallAndStartRemoteService(LPCWSTR remoteServer, Settings& settings)
gle = GetLastError();
}

if (BAD_HANDLE(hSCM))
{
Log(StrFormat(L"Failed to connect to Service Control Manager on %s. Will try alternate method.", remoteServer ? remoteServer : L"{local computer}"), gle);
}

if(gbStop)
return false;

if (BAD_HANDLE(hSCM))
{
Log(StrFormat(L"Failed to connect to Service Control Manager on %s.", remoteServer ? remoteServer : L"{local computer}"), gle);
// If the above fails, we try a different approach that includes impersonation.
// This seems to happen if we do not have admin rights locally when starting a remote process.
// See https://docs.microsoft.com/de-de/windows/win32/api/winsvc/nf-winsvc-openscmanagera?redirectedfrom=MSDN
CString strippedUser = RemoveDomainFromUserName(settings.user);
// This fails if we specify a domain here
bool success = ::LogonUserW(strippedUser, NULL, settings.password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &settings.hUserImpersonated);
if (!success || BAD_HANDLE(settings.hUserImpersonated))
{
gle = GetLastError();
Log(StrFormat(L"Failed to log on as remote user %s.", strippedUser.GetString()), gle);
return false;
}
::ImpersonateLoggedOnUser(settings.hUserImpersonated);
hSCM = ::OpenSCManager(remoteServer, NULL, SC_MANAGER_ALL_ACCESS);
gle = GetLastError();
}

if (BAD_HANDLE(hSCM))
{
Log(StrFormat(L"Failed to impersonate to open Service Control Manager on %s.", remoteServer ? remoteServer : L"{local computer}"), gle);
return false;
}

Expand Down Expand Up @@ -331,7 +379,7 @@ bool InstallAndStartRemoteService(LPCWSTR remoteServer, Settings& settings)
}
settings.bNeedToDeleteService = true;
}

::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);

Expand Down
2 changes: 2 additions & 0 deletions stdafx.h
Expand Up @@ -150,6 +150,7 @@ class Settings
hProcess = INVALID_HANDLE_VALUE;
hUserProfile = INVALID_HANDLE_VALUE; //call UnloadUserProfile when done
hUser = INVALID_HANDLE_VALUE;
hUserImpersonated = INVALID_HANDLE_VALUE;
bDisableFileRedirection = false;
bODS = false;
hStdOut = INVALID_HANDLE_VALUE;
Expand Down Expand Up @@ -330,6 +331,7 @@ class Settings
DWORD processID;
HANDLE hUserProfile; //call UnloadUserProfile when done
HANDLE hUser;
HANDLE hUserImpersonated;
CString localLogPath;
HANDLE hStdOut;
HANDLE hStdIn;
Expand Down

0 comments on commit ac60aaa

Please sign in to comment.