/// <summary> /// Create new thread and execute code in it. Wait until execution ends /// </summary> /// <param name="pCode">Code to execute</param> /// <param name="size">Code size</param> /// <param name="callResult">Code return value</param> /// <returns>Status</returns> NTSTATUS RemoteExec::ExecInNewThread( PVOID pCode, size_t size, uint64_t& callResult ) { AsmJitHelper a; NTSTATUS dwResult = STATUS_SUCCESS; // Write code dwResult = CopyCode( pCode, size ); if (dwResult != STATUS_SUCCESS) return dwResult; bool switchMode = (_proc.core().native()->GetWow64Barrier().type == wow_64_32); auto pExitThread = _mods.GetExport( _mods.GetModule( L"ntdll.dll", LdrList, switchMode ? mt_mod64 : mt_default ), "NtTerminateThread" ).procAddress; if (pExitThread == 0) return LastNtStatus( STATUS_NOT_FOUND ); a.GenPrologue( switchMode ); // Prepare thread to run in x64 mode if(switchMode) { // Allocate new x64 activation stack auto createActStack = _mods.GetExport( _mods.GetModule( L"ntdll.dll", LdrList, mt_mod64 ), "RtlAllocateActivationContextStack" ).procAddress; if (createActStack) { a.GenCall( static_cast<size_t>(createActStack), { _userData.ptr<size_t>() + 0x3100 } ); a->mov( a->zax, _userData.ptr<size_t>( ) + 0x3100 ); a->mov( a->zax, a->intptr_ptr( a->zax ) ); a.SetTebPtr(); a->mov( a->intptr_ptr( a->zdx, 0x2C8 ), a->zax ); } } a.GenCall( _userCode.ptr<size_t>(), { } ); a.ExitThreadWithStatus( (size_t)pExitThread, _userData.ptr<size_t>() + INTRET_OFFSET ); // Execute code in newly created thread if (_userCode.Write( size, a->getCodeSize(), a->make() ) == STATUS_SUCCESS) { auto thread = _threads.CreateNew( _userCode.ptr<ptr_t>() + size, _userData.ptr<ptr_t>()/*, HideFromDebug*/ ); dwResult = thread.Join(); callResult = _userData.Read<uint64_t>( INTRET_OFFSET, 0 ); } else dwResult = LastNtStatus(); return dwResult; }
/// <summary> /// Create worker RPC thread /// </summary> /// <returns>Thread ID</returns> DWORD RemoteExec::CreateWorkerThread() { AsmJitHelper a; asmjit::Label l_loop = a->newLabel(); // // Create execution thread // if(!_hWorkThd.valid()) { eModType mt = mt_default; if (_memory.core().native()->GetWow64Barrier().type == wow_64_32) { mt = mt_mod64; a.SwitchTo64(); // Align stack on 16 byte boundary a->and_( asmjit::host::zsp, -16 ); // Allocate new x64 activation stack auto createActStack = _mods.GetExport( _mods.GetModule( L"ntdll.dll", LdrList, mt ), "RtlAllocateActivationContextStack" ).procAddress; if(createActStack) { a.GenCall( static_cast<size_t>(createActStack), { _userData.ptr<size_t>() + 0x3000 } ); a->mov( asmjit::host::zax, _userData.ptr<size_t>() + 0x3000 ); a->mov( asmjit::host::zax, asmjit::host::intptr_ptr( asmjit::host::zax ) ); a.SetTebPtr(); a->mov( asmjit::host::intptr_ptr( asmjit::host::zdx, 0x2c8 ), asmjit::host::zax ); } } auto ntdll = _mods.GetModule( L"ntdll.dll", Sections, mt ); auto proc = _mods.GetExport( ntdll, "NtDelayExecution" ).procAddress; auto pExitThread = _mods.GetExport( ntdll, "NtTerminateThread" ).procAddress; if (proc == 0 || pExitThread == 0) return 0; /* for(;;) SleepEx(5, TRUE); ExitThread(SetEvent(m_hWaitEvent)); */ a->bind( l_loop ); a.GenCall( static_cast<size_t>(proc), { TRUE, _workerCode.ptr<size_t>() } ); a->jmp( l_loop ); a.ExitThreadWithStatus( (size_t)pExitThread, _userData.ptr<size_t>() ); // Write code into process LARGE_INTEGER liDelay = { 0 }; liDelay.QuadPart = -10 * 1000 * 5; _workerCode.Write( 0, liDelay ); _workerCode.Write( sizeof(LARGE_INTEGER), a->getCodeSize(), a->make() ); _hWorkThd = _threads.CreateNew( _workerCode.ptr<size_t>() + sizeof(LARGE_INTEGER), _userData.ptr<size_t>() ); } return _hWorkThd.id(); }