9d9149d9d8
refactor some dead conditionals and a case/switch that wasn't doing anything
324 lines
16 KiB
C++
Executable File
324 lines
16 KiB
C++
Executable File
#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;
|
|
}
|