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>
/// Execute code in context of our worker thread
/// </summary>
/// <param name="pCode">Cde to execute</param>
/// <param name="size">Code size.</param>
/// <param name="callResult">Execution result</param>
/// <returns>Status</returns>
NTSTATUS RemoteExec::ExecInWorkerThread( PVOID pCode, size_t size, uint64_t& callResult )
{
    NTSTATUS dwResult = STATUS_SUCCESS;

    // Create thread if needed
    CreateRPCEnvironment();

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

    if (_hWaitEvent)
        ResetEvent( _hWaitEvent );

    // Patch KiUserApcDispatcher 
#ifdef USE64
    if (!_apcPatched && IsWindows7OrGreater() && !IsWindows8OrGreater())
    {
        if (_proc.core().native()->GetWow64Barrier().type == wow_64_32)
        {
            auto patchBase = _proc.nativeLdr().APC64PatchAddress();

            if (patchBase != 0)
            {
                DWORD flOld = 0;
                _memory.Protect(patchBase, 6, PAGE_EXECUTE_READWRITE, &flOld);
                _memory.Write(patchBase + 0x2, (uint8_t)0x0C);
                _memory.Write( patchBase + 0x4, (uint8_t)0x90 );
                _memory.Protect( patchBase, 6, flOld, nullptr );
            }

            _apcPatched = true;
        }
        else
            _apcPatched = true;
    }
#endif

    // Execute code in thread context
    if (QueueUserAPC( _userCode.ptr<PAPCFUNC>(), _hWorkThd.handle(), _userCode.ptr<ULONG_PTR>() ))
    {
        dwResult = WaitForSingleObject( _hWaitEvent, INFINITE );
        callResult = _userData.Read<uint64_t>( RET_OFFSET, 0 );
    }
    else
        return LastNtStatus();

    // Ensure APC function fully returns
    Sleep( 1 );

    return dwResult;
}
Beispiel #3
0
void PragEnding( void )
/*********************/
{
    if( CurrEntry == NULL )
        return;
    CurrInfo->use = CurrAlias->use; /* for compare */
    if( memcmp( CurrAlias, CurrInfo, sizeof( aux_info ) ) == 0 ) {
        CurrEntry->info = CurrAlias;
        CurrAlias->use++;
        CMemFree( CurrInfo );
    } else {
        CopyParms();
        CopyLinkage();
        CopyCode();
        CopyObjName();
#if _CPU == _AXP
        CopyExceptRtn();
#endif
        CurrInfo->use = 1;
        CurrEntry->info = CurrInfo;
    }

    /* If this pragma defines code, check to see if we already have a function body */   
    if( CurrEntry->name != NULL && CurrEntry->info != NULL && CurrEntry->info->code != NULL ) {
        SYM_HANDLE  sym_handle;
        SYM_ENTRY   sym;

        if( 0 != (sym_handle = SymLook( CalcHash( CurrEntry->name, strlen( CurrEntry->name ) ), CurrEntry->name )) ) {
            SymGet( &sym, sym_handle );
            if( ( sym.flags & SYM_DEFINED ) && ( sym.flags & SYM_FUNCTION ) ) {
                CErr2p( ERR_SYM_ALREADY_DEFINED, CurrEntry->name );
            }
        }
    }

    CurrEntry->next = AuxList;
    AuxList = CurrEntry;
}
Beispiel #4
0
bool Compiler::CreateData( VM::Data& data, int codeSize )
{
	// Entry point for the program is main function.
	const FunctionTag* pTag = GetFunctionTag( "main" );
	if( pTag == 0 ){
		error( "Function : main is not found." );
		return false;
	}

	data.m_Command = new unsigned char[ codeSize ];		// Binary data.
	data.m_TextBuffer = new char[ m_TextTable.size() ];	// Source code.
	data.m_CommandSize = codeSize;						// Binary size.
	data.m_TextSize = (int)m_TextTable.size();			// Source code size.
	data.m_ValueSize = (int)m_Variables[ 0 ].GetSize();
	data.m_EntryPoint = m_Labels[ pTag->m_Index ].m_Pos;	// Entry point.(main function)

	if( data.m_TextSize != 0 ){
		memcpy( data.m_TextBuffer, &m_TextTable[ 0 ], data.m_TextSize );
	}

	std::for_each( m_Statement.begin(), m_Statement.end(), CopyCode( data.m_Command ) );
	
	return true;
}
Beispiel #5
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( 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;
        asmjit::host::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::host::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::host::Mem( asmjit::host::rsp, i * WordSize ) );

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

        a->jmp( asmjit::Imm( 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;
}
Beispiel #6
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( 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 ))
    {
        AsmJit::Assembler a;
        AsmJitHelper ah( a );

#ifdef _M_AMD64
        const int count = 15;
        AsmJit::GPReg regs[] = { AsmJit::rax, AsmJit::rbx, AsmJit::rcx, AsmJit::rdx, AsmJit::rsi,
                                 AsmJit::rdi, AsmJit::r8,  AsmJit::r9,  AsmJit::r10, AsmJit::r11,
                                 AsmJit::r12, AsmJit::r13, AsmJit::r14, AsmJit::r15, AsmJit::rbp
                               };
        //
        // Preserve thread context
        // I don't care about FPU, XMM and anything else
        //
        a.sub(AsmJit::rsp, count * WordSize);  // Stack must be aligned on 16 bytes
        a.pushfq();                            //

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

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

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

        a.popfq();
        a.add( AsmJit::rsp, count * WordSize );

        a.jmp( ctx.Rip );
#else
        a.pushad();
        a.pushfd();

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

        a.popfd();
        a.popad();

        a.push( 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;
}
Beispiel #7
0
TInt E32ImageFile_ELF::Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, \
								 TBool aSymLkupEnabled)
//
// Translate a ELF format file to a E32Image file
//
	
{
	iSource = EElfFile;
	ELFFile elffile;
	if (!elffile.Init((const TText * const)aFileName)) return KErrGeneral;
		
	iFileName = strdup(aFileName);

	Adjust(ALIGN4(sizeof(E32ImageHeaderV)));	// fixed for now because holes not supported
	SetDefaultHeader();
	iHdr->iDllRefTableCount = elffile.NumberOfImportDlls();
	iHdr->iExportDirCount = elffile.NumberOfExports();
	iHdr->iCodeBase = elffile.iLinkedBase;

	if(aSymLkupEnabled)
	{
		if( !SetUpLookupTable(elffile) )
			return KErrGeneral;
	}


	TInt size = ALIGN4(sizeof(E32ImageHeaderV));	// fixed for now because holes not supported
	iHdr->iCodeOffset = size;
	TInt pos = size;
	size+=DoCodeHeader(elffile);

	size += DoSymbolLookupHeader(elffile, size - pos);

	TInt nimports=elffile.NumberOfImports();
	TInt importSectionSize;
	char *newImportSection=CreateImportSection(elffile, importSectionSize);

	TInt t=DoDataHeader(elffile, aDataBase);
	if (t>0)
		{
		iHdr->iDataOffset = size;
		size += t;
		}
	if (importSectionSize!=0)
		{
		iHdr->iImportOffset=size;
		size+=ALIGN4(importSectionSize);
		}

	char *newCodeRelocs=NULL;
	char *newDataRelocs=NULL;
	TInt codeRelocSize=0, dataRelocSize=0;
	TInt nCodeRelocs=elffile.NumberOfCodeRelocs();
	TInt nDataRelocs=elffile.NumberOfDataRelocs();
	if (nCodeRelocs + nDataRelocs)
		{
		Elf32_Rel **codeRelocs=new Elf32_Rel * [nCodeRelocs];
		Elf32_Rel **dataRelocs=new Elf32_Rel * [nDataRelocs];
		if (!elffile.GetRelocs(codeRelocs, dataRelocs)) return KErrGeneral;
		       
		FixRelocs(elffile, codeRelocs, dataRelocs);
		if (elffile.iCodeSegmentHdr)
			newCodeRelocs=CreateRelocs(elffile, codeRelocs, nCodeRelocs, codeRelocSize, elffile.iCodeSegmentHdr->p_vaddr);
		if (elffile.iDataSegmentHdr)
			newDataRelocs=CreateRelocs(elffile, dataRelocs, nDataRelocs, dataRelocSize, elffile.iDataSegmentHdr->p_vaddr);
		if (codeRelocSize)
			{
			iHdr->iCodeRelocOffset = size;
			size += codeRelocSize;
			}
		if (dataRelocSize)
			{
			iHdr->iDataRelocOffset = size;
			size += dataRelocSize;
			}
		delete [] codeRelocs;
		delete [] dataRelocs;
		}

	Adjust(size);
	t=CopyCode(iData + pos, elffile);
	if (t<0)
		return KErrGeneral;
	pos += t;
	t = CopyExportSymInfo(iData+pos, elffile);
	if (t<0)
		return KErrGeneral;
	pos += t;

	pos += CopyData(iData + pos, elffile);
	if (nimports)
		{
		memcpy(iData + pos, newImportSection, importSectionSize);
		pos += ALIGN4(importSectionSize);
		}
	if (codeRelocSize)
		{
		memcpy(iData + pos, newCodeRelocs, codeRelocSize);
		pos += codeRelocSize;
		}
	if (dataRelocSize)
		{
		memcpy(iData + pos, newDataRelocs, dataRelocSize);
		pos += dataRelocSize;
		}

	// locate the entry point
	TUint entryPointOffset=elffile.GetEntryPointOffset();

	// Arrange a header for this E32 Image
	iHdr->iCpuIdentifier = (TUint16)ECpuArmV4;
	// Import format is ELF-derived
	iHdr->iFlags |= KImageImpFmt_ELF;
	// ABI is ARM EABI
	iHdr->iFlags |= KImageABI_EABI;
	if (ImageIsDll(elffile))
		{
		iHdr->iFlags |= KImageDll;
		if (iHdr->iDataSize && !aAllowDllData)
			return Print(EError, "Dll '%s' has initialised data.\n", iFileName);
		if (iHdr->iBssSize  && !aAllowDllData)
			return Print(EError, "Dll '%s' has uninitialised data.\n", iFileName);
		}
	iHdr->iHeapSizeMin = elffile.iHeapCommittedSize;
	iHdr->iHeapSizeMax = elffile.iHeapReservedSize;
	iHdr->iStackSize = elffile.iStackCommittedSize;
	iHdr->iEntryPoint = entryPointOffset;
	TInt r = DetermineEntryPointType();
	if (r == KErrCorrupt)
		return Print(EError, "File '%s': Bad Entry Point.\n", iFileName);
	else if (r == KErrNotSupported)
		return Print(EError, "File '%s': Bad Entry Point Type.\n", iFileName);

	SetUpExceptions(elffile);

	delete [] newImportSection;
	delete [] newCodeRelocs;
	delete [] newDataRelocs;

	return KErrNone;
	}