Пример #1
0
	bool MMap::CreateActx(const std::wstring& path, int id /*= 2 */, bool asImage /*= true*/) {
		AsmJitHelper a;
		uint64_t result = 0;
		ACTCTXW act = {0};
		_pAContext = _process.Memory().Allocate(512, PAGE_READWRITE);
		act.cbSize = sizeof(act);
		act.lpSource = reinterpret_cast<LPCWSTR>(_pAContext.Ptr<size_t>() + sizeof(HANDLE) + sizeof(act));
		// Ignore some fields for pure manifest file
		if(asImage) {
			act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
			act.lpResourceName = MAKEINTRESOURCEW(id);
		}
		bool switchMode = (_process.Core().GetNative()->GetWow64Barrier().type == wow_64_32);
		auto pCreateActx = _process.Modules().GetExport(_process.Modules().GetModule(L"kernel32.dll"), "CreateActCtxW");
		if(pCreateActx.procAddress == 0) {
			BLACBONE_TRACE(L"ManualMap: Failed to create activation context for image '%ls'. 'CreateActCtxW' is absent", path.c_str());
			return false;
		}
		// CreateActCtx(&act)
		// Emulate Wow64
		if(switchMode) {
			_ACTCTXW_T<DWORD> act32 = {0};
			act32.cbSize = sizeof(act32);
			act32.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
			act32.lpSource = _pAContext.Ptr<uint32_t>() + sizeof(HANDLE) + sizeof(act32);
			act32.lpResourceName = id;
			a->push(_pAContext.Ptr<uint32_t>() + static_cast<uint32_t>(sizeof(HANDLE)));
			a->mov(asmjit::host::eax, static_cast<uint32_t>(pCreateActx.procAddress));
			a->call(a->zax);
			a->mov(asmjit::host::edx, _pAContext.Ptr<uint32_t>());
			//a->mov( asmjit::host::dword_ptr( asmjit::host::edx ), asmjit::host::eax );
			a->dw('\x01\x02');
			auto pTermThd = _process.Modules().GetExport(_process.Modules().GetModule(L"ntdll.dll"), "NtTerminateThread");
			a->push(a->zax);
			a->push(uint32_t(0));
			a->mov(asmjit::host::eax, static_cast<uint32_t>(pTermThd.procAddress));
			a->call(a->zax);
			a->ret(4);
			// Write path to file
			_pAContext.Write(sizeof(HANDLE), act32);
			_pAContext.Write(sizeof(HANDLE) + sizeof(act32), (path.length() + 1) * sizeof(wchar_t), path.c_str());
			auto pCode = _process.Memory().Allocate(0x1000);
			pCode.Write(0, a->getCodeSize(), a->make());
			result = _process.Remote().ExecDirect(pCode.Ptr<ptr_t>(), _pAContext.Ptr<size_t>() + sizeof(HANDLE));
		}
		// Native way
		else {
			a.GenPrologue();
			a.GenCall(static_cast<size_t>(pCreateActx.procAddress), {_pAContext.Ptr<size_t>() + sizeof(HANDLE)});
			a->mov(a->zdx, _pAContext.Ptr<size_t>());
			a->mov(a->intptr_ptr(a->zdx), a->zax);
			_process.Remote().AddReturnWithEvent(a);
			a.GenEpilogue();
			// Write path to file
			_pAContext.Write(sizeof(HANDLE), act);
			_pAContext.Write(sizeof(HANDLE) + sizeof(act), (path.length() + 1) * sizeof(wchar_t), path.c_str());
			_process.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
		}
		if(reinterpret_cast<HANDLE>(result) == INVALID_HANDLE_VALUE) {
			_pAContext.Free();
			// SetLastError( err::mapping::CantCreateActx );
			BLACBONE_TRACE(L"ManualMap: Failed to create activation context for image '%ls'. Status: 0x%x",
				path.c_str(), _process.Remote().GetLastStatus());
			return false;
		}
		return true;
	}
Пример #2
0
/// <summary>
/// Execute code in context of any existing thread
/// </summary>
/// <param name="pCode">Cde to execute</param>
/// <param name="size">Code size.</param>
/// <param name="callResult">Execution result</param>
/// <param name="thd">Target thread</param>
/// <returns>Status</returns>
NTSTATUS RemoteExec::ExecInAnyThread( PVOID pCode, size_t size, uint64_t& callResult, Thread& thd )
{
    NTSTATUS dwResult = STATUS_SUCCESS;
    CONTEXT_T ctx;

    // Prepare for remote exec
    CreateRPCEnvironment( false, true );

    // Write code
    dwResult = CopyCode( pCode, size );
    if (dwResult != STATUS_SUCCESS)
        return dwResult;

    if (_hWaitEvent)
        ResetEvent( _hWaitEvent );

    if (!thd.Suspend())
        return LastNtStatus();

    if (thd.GetContext( ctx, CONTEXT_ALL, true ))
    {
        AsmJitHelper a;

#ifdef USE64
        const int count = 15;
        static const asmjit::GpReg regs[] = 
        {
            asmjit::host::rax, asmjit::host::rbx, asmjit::host::rcx, asmjit::host::rdx, asmjit::host::rsi,
            asmjit::host::rdi, asmjit::host::r8,  asmjit::host::r9,  asmjit::host::r10, asmjit::host::r11,
            asmjit::host::r12, asmjit::host::r13, asmjit::host::r14, asmjit::host::r15, asmjit::host::rbp     
        };

        //
        // Preserve thread context
        // I don't care about FPU, XMM and anything else
        //
        a->sub( asmjit::host::rsp, count * WordSize );  // Stack must be aligned on 16 bytes 
        a->pushf();                                     //

        // Save registers
        for (int i = 0; i < count; i++)
            a->mov( asmjit::Mem( asmjit::host::rsp, i * WordSize ), regs[i] );

        a.GenCall( _userCode.ptr<size_t>(), { _userData.ptr<size_t>() } );
        AddReturnWithEvent( a, mt_default, rt_int32, INTRET_OFFSET );

        // Restore registers
        for (int i = 0; i < count; i++)
            a->mov( regs[i], asmjit::Mem( asmjit::host::rsp, i * WordSize ) );

        a->popf();
        a->add( asmjit::host::rsp, count * WordSize );

        // jmp [rip]
        a->dw( '\xFF\x25' ); a->dd( 0 );
        a->dq( ctx.Rip );
    #else
        a->pusha();
        a->pushf();

        a.GenCall( _userCode.ptr<size_t>(), { _userData.ptr<size_t>() } );
        AddReturnWithEvent( a, mt_default, rt_int32, INTRET_OFFSET );

        a->popf();
        a->popa();

        a->push( (size_t)ctx.NIP );
        a->ret();
    #endif

        if (_userCode.Write( size, a->getCodeSize(), a->make() ) == STATUS_SUCCESS)
        {
            ctx.NIP = _userCode.ptr<size_t>() + size;

            if (!thd.SetContext( ctx, true ))
                dwResult = LastNtStatus();
        }
        else
            dwResult = LastNtStatus();
    }
    else
        dwResult = LastNtStatus();

    thd.Resume();

    if (dwResult == STATUS_SUCCESS)
    {
        WaitForSingleObject( _hWaitEvent, INFINITE );
        callResult = _userData.Read<size_t>( INTRET_OFFSET, 0 );
    }

    return dwResult;
}