Beispiel #1
0
/// <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;
}
Beispiel #2
0
/// <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();
}