SHARE
TWEET

TIOR.EXE

a guest Nov 17th, 2012 152 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "stdafx.h"
  2. #include "resource.h"
  3. #include "Win7Elevate_Utils.h"
  4. #include "Win7Elevate_Inject.h"
  5.  
  6. #include <iostream>
  7. #include <sstream>
  8. #include <algorithm>
  9.  
  10. #include ".\..\Redirector.h"
  11. #include ".\..\CMMN.h"
  12.  
  13. //
  14. //      By Pavlov P.S. (PavPS)
  15. //
  16.  
  17. void PrintUsage()
  18. {
  19.         std::cout << "Incorrect input. Please find samples below. " << std::endl;
  20.         std::cout << "Note, 'elevate stuff' will be executed in the elevated shell as 'cmd.exe stuff' " << std::endl;
  21.         std::cout << "\televate /c <ANY COMMAND SEQUENCE THAT IS ALLOWED BY CMD.EXE SHELL>" << std::endl;
  22.         std::cout << "\televate /c <command> [arg1] [arg2] .. [argn]" << std::endl;
  23.         std::cout << "\televate --pid 1234 /c <command> [arg1] [arg2] .. [argn]" << std::endl;
  24.         std::cout << "\televate /c c:\\path\\foo.exe [arg1] [arg2] .. [argn]" << std::endl;
  25.         std::cout << "\televate --pid 1234 /c c:\\path\\foo.exe [arg1] [arg2] .. [argn]" << std::endl;
  26. }
  27.  
  28. HANDLE PipeIn = NULL;
  29. OVERLAPPED PipeInO;
  30.  
  31. HANDLE PipeOut = NULL;
  32. OVERLAPPED PipeOutO;
  33.  
  34. HANDLE PipeErr = NULL;
  35. OVERLAPPED PipeErrO;
  36.  
  37. //
  38. //      Initializes named pipes that will be used for connection with TIOR
  39. //
  40. bool SetupNamedPipe()
  41. {
  42.         PipeInO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  43.         PipeIn = CreateNamedPipe(
  44.                 STDIn_PIPE,
  45.                 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
  46.                 PIPE_TYPE_BYTE | PIPE_WAIT,  
  47.                 PIPE_UNLIMITED_INSTANCES,
  48.                 0, 0,
  49.                 NMPWAIT_USE_DEFAULT_WAIT,
  50.                 NULL );
  51.  
  52.         ConnectNamedPipe( PipeIn, &PipeInO );
  53.  
  54.         PipeOutO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  55.         PipeOut = CreateNamedPipe(
  56.                 STDOut_PIPE,
  57.                 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
  58.                 PIPE_TYPE_BYTE | PIPE_WAIT,  
  59.                 PIPE_UNLIMITED_INSTANCES,
  60.                 0, 0,
  61.                 NMPWAIT_USE_DEFAULT_WAIT,
  62.                 NULL );
  63.  
  64.         ConnectNamedPipe( PipeOut, &PipeOutO );
  65.  
  66.         PipeErrO.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  67.         PipeErr = CreateNamedPipe(
  68.                 STDErr_PIPE,
  69.                 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
  70.                 PIPE_TYPE_BYTE | PIPE_WAIT,  
  71.                 PIPE_UNLIMITED_INSTANCES,
  72.                 0, 0,
  73.                 NMPWAIT_USE_DEFAULT_WAIT,
  74.                 NULL );
  75.  
  76.         ConnectNamedPipe( PipeErr, &PipeErrO );
  77.  
  78.         return true;
  79. }
  80.  
  81. //
  82. //      Initiates data pumping.
  83. //
  84. DWORD __stdcall Redirector()
  85. {
  86.         if ( !PipeIn )
  87.                 return -1;
  88.  
  89.         if ( PipeInO.hEvent )
  90.                 WaitForSingleObject( PipeInO.hEvent, -1000 );
  91.         if ( PipeOutO.hEvent )
  92.                 WaitForSingleObject( PipeOutO.hEvent, -1000 );
  93.         if ( PipeErrO.hEvent )
  94.                 WaitForSingleObject( PipeErrO.hEvent, -1000 );
  95.  
  96.         TRedirectorPair in = {0};
  97.         in.Source = GetStdHandle(STD_INPUT_HANDLE);
  98.         in.Destination = PipeIn;
  99.         in.Linux = true;
  100.         in.Name.assign(TEXT("w7e-in"));
  101.         in.Thread= CreateThread( NULL, 0, Redirector, &in, 0, NULL);
  102.  
  103.         TRedirectorPair out = {0};
  104.         out.Destination = GetStdHandle(STD_OUTPUT_HANDLE);
  105.         out.Source = PipeOut;
  106.         out.Name.assign(TEXT("w7e-out"));
  107.         out.Thread= CreateThread( NULL, 0, Redirector, &out, 0, NULL);
  108.  
  109.         TRedirectorPair err = {0};
  110.         err.Destination = GetStdHandle(STD_ERROR_HANDLE);
  111.         err.Source = PipeErr;
  112.         err.Name.assign(TEXT("w7e-err"));
  113.         err.Thread= CreateThread( NULL, 0, Redirector, &err, 0, NULL);
  114.  
  115.         HANDLE waiters[3] = { in.Thread, out.Thread, err.Thread };
  116.         WaitForMultipleObjects( 3, waiters, FALSE, INFINITE );
  117.  
  118.         return 0;
  119. }
  120.  
  121. bool IsDefaultProcess ( std::pair<DWORD, std::wstring> pair ) {
  122.         return lstrcmpi( pair.second.c_str(), TEXT("explorer.exe") ) == 0;
  123. }
  124.  
  125. //
  126. //      To avoid some problems with deadlocked processes we need to find way how to run program
  127. //      once more. Since program uses named papes, it can not be started twice (in current realization).
  128. //      So, if instance of this process already exists, we need to kill it. Regular exe, started from the
  129. //      user's account has no access to kill existing app.
  130. //      Here i use named event to listen for and perform suicide. So, i just need to set this event (if one)
  131. //      and already existsing app will kill itself.
  132. //
  133. DWORD WINAPI Suicide( LPVOID Parameter )
  134. {
  135.         CLogger::LogLine(TEXT("Waiting for suicide..."));
  136.         WaitForSingleObject( reinterpret_cast<HANDLE>( Parameter ), INFINITE );
  137.         SetEvent( reinterpret_cast<HANDLE>( Parameter ) );
  138.         CLogger::LogLine(TEXT("Suicide..."));
  139.         ExitProcess( EXIT_FAILURE );
  140.        
  141.         return EXIT_SUCCESS;
  142. }
  143.  
  144. int _tmain(int argc, _TCHAR* argv[])
  145. {
  146.         CLogger::Reset();
  147.         CLogger::LogLine(TEXT("Started"));
  148.  
  149.         //
  150.         //      Looking for suicide.
  151.         //
  152.         HANDLE obj = CreateEvent( NULL, FALSE, TRUE, TEXT("ws7Suicide") );
  153.         if ( !obj )
  154.         {
  155.                 CLogger::LogLine(TEXT("Unable to create suicide object"));
  156.                 ExitProcess( EXIT_FAILURE );
  157.         }
  158.  
  159.         //
  160.         //      If we see that suicide event is in reset state, we just pulce one and wait for
  161.         //      it's owner to die. When its done, we acuire this event object and also starting listening for
  162.         //      any signals of this object.
  163.         //
  164.         do
  165.         {
  166.                 DWORD rv = WaitForSingleObject( obj, 100 );
  167.                 if ( rv == WAIT_OBJECT_0 ) break;
  168.  
  169.                 if ( rv != WAIT_TIMEOUT )
  170.                 {
  171.                         CLogger::LogLine(TEXT("Suicide wait error"));
  172.                         ExitProcess( EXIT_FAILURE );
  173.                 }
  174.  
  175.                 CLogger::LogLine(TEXT("Somebody alive. Pulse."));
  176.                 PulseEvent( obj );
  177.                 Sleep(1000); // wee need to wait;
  178.  
  179.         }while( true );
  180.  
  181.         HANDLE hSuicide = CreateThread( NULL, 0, Suicide, obj, 0, NULL );
  182.         if ( !hSuicide )
  183.         {
  184.                 CLogger::LogLine(TEXT("Immortals are not allowed"));
  185.                 return EXIT_FAILURE;
  186.         }
  187.  
  188.         do
  189.         {
  190.                 int pass_through_index = 1;
  191.                 if ( argc <= pass_through_index )
  192.                 {
  193.                         std::cout << "Too few arguments" << std::endl;
  194.                         break;
  195.                 }
  196.  
  197.  
  198.                 DWORD pid = 0;
  199.                 if ( lstrcmpi( argv[1], TEXT("--pid") ) == 0 )
  200.                 {
  201.                         pass_through_index = 3;
  202.                         if ( argc <= pass_through_index )
  203.                         {
  204.                                 std::cout << "Too few arguments" << std::endl;
  205.                                 break;
  206.                         }
  207.  
  208.                         std::wistringstream pid_stream( argv[2] );
  209.                         if ( ! ( pid_stream >> pid ) )
  210.                         {
  211.                                 std::cout << "Invalid pid" << std::endl;
  212.                                 pid = 0;
  213.                         }
  214.                 }
  215.  
  216.                 if ( ! pid )
  217.                 {
  218.                         std::map< DWORD, std::wstring > procs;
  219.                         if (!W7EUtils::GetProcessList(GetConsoleWindow(), procs))
  220.                         {
  221.                                 std::cout << "Unable to obtain list of processes" << std::endl;
  222.                                 break;
  223.                         }
  224.  
  225.                         std::map< DWORD, std::wstring >::const_iterator iter = std::find_if( procs.begin(), procs.end(), IsDefaultProcess );
  226.                         if (iter == procs.end())
  227.                         {
  228.                                 std::cout << "Unable to find default process" << std::endl;
  229.                                 break;
  230.                         }
  231.  
  232.                         pid = (*iter).first;
  233.                 }
  234.  
  235.                 TOKEN_ELEVATION_TYPE g_tet = TokenElevationTypeDefault;
  236.                 if (!W7EUtils::GetElevationType(&g_tet))
  237.                 {
  238.                         _tprintf(_T("GetElevationType failed"));
  239.                         break;
  240.                 }
  241.  
  242.                 switch(g_tet)
  243.                 {
  244.                 default:
  245.                 case TokenElevationTypeDefault:
  246.                         CLogger::LogLine(_T("<< UNKNOWN elevation level. >>\n"));
  247.                         break;
  248.                 case TokenElevationTypeFull:
  249.                         CLogger::LogLine(_T("*** Since the program is already elevated the tests below are fairly meaningless. Re-run it without elevation. ***\n"));
  250.                         break;
  251.                 case TokenElevationTypeLimited:
  252.                         CLogger::LogLine(_T("This program attempts to bypass Windows 7's default UAC settings to run the specified command with silent elevation.\n"));
  253.                         break;
  254.                 }
  255.  
  256.                 W7EUtils::CTempResource dllResource(NULL, IDD_EMBEDDED_DLL);
  257.                 std::wstring strOurDllPath;
  258.                 if (!dllResource.GetFilePath(strOurDllPath))
  259.                 {
  260.                         //MessageBox(GetConsoleWindow(), L"Error extracting dll resource.", L"W7Elevate", MB_OK | MB_ICONERROR);
  261.                         CLogger::LogLine(TEXT("Error extracting dll resource."));
  262.                         break;
  263.                 }
  264.  
  265.                 //
  266.                 //      Extraction TIOR.exe from resources and saves exe in the folder where current application
  267.                 //      exists.
  268.                 //
  269.                 W7EUtils::CTempResource TIORResource(NULL, IDD_EMBEDDED_TIOR);
  270.                 std::wstring strOurTIORPath;
  271.                 std::wstring tior;
  272.                 bool tior_succeed = false;
  273.                 if (TIORResource.GetFilePath(strOurTIORPath))
  274.                 {
  275.                         CLogger::LogLine(TEXT("TIOR extracted"));
  276.  
  277.                         TCHAR me_buff[MAX_PATH];
  278.                         DWORD me_count = GetModuleFileName( NULL, me_buff, MAX_PATH );
  279.                         if ( me_count )
  280.                         {
  281.                                 TCHAR *me_tail = me_buff + me_count - 1;
  282.                                 for( ; me_tail > me_buff; me_tail-- )
  283.                                         if ( *me_tail == '\\' )
  284.                                         {
  285.                                                 me_tail++;
  286.                                                 *me_tail = 0;
  287.                                                 break;
  288.                                         }
  289.  
  290.                                 tior.assign(me_buff);
  291.                                 tior.append( TEXT("tior.exe") );
  292.  
  293.                                 if ( CopyFile( strOurTIORPath.c_str(), tior.c_str(), FALSE ) )
  294.                                 {
  295.                                         CLogger::LogLine(TEXT("TIOR copied"));
  296.                                         tior_succeed = true;
  297.                                 }
  298.                         }
  299.                 }
  300.  
  301.                 if ( tior_succeed )
  302.                 {
  303.                         tior_succeed = false;
  304.  
  305.                         CInterprocessStorage *tior_storage = CInterprocessStorage::Create( TEXT("w7e_TIORPath") );
  306.                         if ( tior_storage )
  307.                         {
  308.                                 CLogger::LogLine(TEXT("TIOR path set"));
  309.                                 tior_storage->SetString( tior );
  310.                                 tior_succeed = true;
  311.                         }
  312.                 }
  313.  
  314.                 if ( !tior_succeed )
  315.                 {
  316.                         //MessageBox(GetConsoleWindow(), L"Error extracting tior resource.", L"W7Elevate", MB_OK | MB_ICONERROR);
  317.                         CLogger::LogLine(L"Error extracting tior resource.");
  318.                         break;
  319.                 }
  320.  
  321.                 std::wstring args;
  322.                 for ( int i = pass_through_index; i < argc; i++ )
  323.                 {
  324.                         bool q = wcsstr(argv[i], TEXT(" ")) || wcsstr(argv[i], TEXT("\t"));
  325.  
  326.                         if ( q ) args.append( TEXT("\"") );
  327.                         args.append( argv[i] );
  328.                         if ( q ) args.append( TEXT("\"") );
  329.                         args.append( TEXT(" ") );
  330.                 }
  331.  
  332.                 if ( !SetupNamedPipe() )
  333.                         std::cout << "Unable to setup named pipe" << std::endl;
  334.  
  335.                 //
  336.                 //      Preparing shared variables to be used by TIOR that is going to start after we will inject
  337.                 //      and load dll into elevated process.
  338.                 //
  339.                 CInterprocessStorage::Create( TEXT("w7e_TIORShell"), std::wstring(TEXT("cmd.exe")) );
  340.                 CInterprocessStorage::Create( TEXT("w7e_TIORArgs"), args );
  341.                 CInterprocessStorage::Create( TEXT("w7e_TIORDir"), std::wstring(TEXT("C:\\Windows\\System32")) );
  342.  
  343.                 W7EInject::AttemptOperation(
  344.                         GetConsoleWindow(),
  345.                         true,
  346.                         true,
  347.                         pid,
  348.                         TEXT("n/a"),
  349.                         argv[pass_through_index],
  350.                         args.c_str(),
  351.                         TEXT("C:\\Windows\\System32"),
  352.                         strOurDllPath.c_str(),
  353.                         Redirector);
  354.  
  355.                 return EXIT_SUCCESS;
  356.  
  357.         }while(false);
  358.  
  359.         PrintUsage();
  360.         return EXIT_FAILURE;
  361. }
RAW Paste Data
Top