Exemple #1
0
/// <summary>
/// Get EPT PTE entry for guest physical address
/// </summary>
/// <param name="PML4">PTE PML4 pointer</param>
/// <param name="phys">Guest physical address</param>
/// <param name="pEntry">Found entry or NULL</param>
/// <returns>Status code</returns>
NTSTATUS EptGetPTEForPhysical( IN PEPT_PML4_ENTRY PML4, IN PHYSICAL_ADDRESS phys, OUT PEPT_PTE_ENTRY* pEntry )
{
    NT_ASSERT( pEntry != NULL && PML4 != NULL );
    if (pEntry == NULL|| PML4 == NULL)
        return STATUS_INVALID_PARAMETER;

    ULONG64 offset = EptpTableOffset( PFN( phys.QuadPart ), 3 );
    ULONG64 pfn = PML4[offset].Fields.PhysAddr;
    if (pfn != 0)
    {
        for (CHAR i = 2; i >= 0; i--)
        {
            PHYSICAL_ADDRESS addr = { 0 };
            addr.QuadPart = pfn << PAGE_SHIFT;
            PEPT_MMPTE ptr = MmGetVirtualForPhysical( addr );
            if (ptr == NULL)
                break;

            offset = EptpTableOffset( PFN( phys.QuadPart ), i );
            if (i == 0)
            {
                *pEntry = (PEPT_PTE_ENTRY)&ptr[offset];
                return STATUS_SUCCESS;
            }

            pfn = ptr[offset].Fields.PhysAddr;
        }
    }

    return STATUS_NOT_FOUND;
}
Exemple #2
0
/*
 * @to: index of the smallest element which is >= then @pfn.
 *
 * Return the index of the pfn if found, otherwise negative value.
 */
static int __find_elem(struct ce_array *ca, u64 pfn, unsigned int *to)
{
	u64 this_pfn;
	int min = 0, max = ca->n;

	while (min < max) {
		int tmp = (max + min) >> 1;

		this_pfn = PFN(ca->array[tmp]);

		if (this_pfn < pfn)
			min = tmp + 1;
		else if (this_pfn > pfn)
			max = tmp;
		else {
			min = tmp;
			break;
		}
	}

	if (to)
		*to = min;

	this_pfn = PFN(ca->array[min]);

	if (this_pfn == pfn)
		return min;

	return -ENOKEY;
}
int Mips3MapHandler(uintptr_t nHandler, unsigned int nStart, unsigned int nEnd, int nType)
{
    const int maxPages = (PFN(nEnd) - PFN(nStart)) + 1;

    int page = PFN(nStart);
    for (int i = 0; i < maxPages; i++, page++) {

        if (nType & MAP_READ)
            g_mmap->MemMap[page] = (UINT8*) nHandler;

        if (nType & MAP_WRITE)
            g_mmap->MemMap[PAGE_WADD + page] = (UINT8*) nHandler;
    }
    return 0;
}
int Mips3MapMemory(unsigned char* pMemory, unsigned int nStart, unsigned int nEnd, int nType)
{
    const int maxPages = (PFN(nEnd) - PFN(nStart)) + 1;

    int page = PFN(nStart);
    for (int i = 0; i < maxPages; i++, page++) {

        if (nType & MAP_READ)
            g_mmap->MemMap[page] = pMemory + (PAGE_SIZE * i);

        if (nType & MAP_WRITE)
            g_mmap->MemMap[PAGE_WADD + page] = pMemory + (PAGE_SIZE * i);
    }
    return 0;
}
Exemple #5
0
static int array_dump(struct seq_file *m, void *v)
{
	struct ce_array *ca = &ce_arr;
	u64 prev = 0;
	int i;

	mutex_lock(&ce_mutex);

	seq_printf(m, "{ n: %d\n", ca->n);
	for (i = 0; i < ca->n; i++) {
		u64 this = PFN(ca->array[i]);

		seq_printf(m, " %03d: [%016llx|%03llx]\n", i, this, FULL_COUNT(ca->array[i]));

		WARN_ON(prev > this);

		prev = this;
	}

	seq_printf(m, "}\n");

	seq_printf(m, "Stats:\nCEs: %llu\nofflined pages: %llu\n",
		   ca->ces_entered, ca->pfns_poisoned);

	seq_printf(m, "Flags: 0x%x\n", ca->flags);

	seq_printf(m, "Timer interval: %lld seconds\n", timer_interval);
	seq_printf(m, "Decays: %lld\n", ca->decays_done);

	seq_printf(m, "Action threshold: %d\n", count_threshold);

	mutex_unlock(&ce_mutex);

	return 0;
}
Exemple #6
0
/// <summary>
/// EPT violation (#VE) handler
/// </summary>
/// <param name="GuestState">Guest VM state</param>
VOID VmExitEptViolation( IN PGUEST_STATE GuestState )
{
    //PEPT_PTE_ENTRY pPTE = NULL;
    PEPT_DATA pEPT = &GuestState->Vcpu->EPT;
    ULONG64 pfn = PFN( GuestState->PhysicalAddress.QuadPart );
    PEPT_VIOLATION_DATA pViolationData = (PEPT_VIOLATION_DATA)&GuestState->ExitQualification;

    // Page is hooked
    PPAGE_HOOK_ENTRY pHookEntry = PHGetHookEntryByPFN( pfn, DATA_PAGE );
    if (pHookEntry)
    {
        /*DPRINT(
            "HyperBone: CPU %d: %s: Hooked page %s, EIP 0x%p, Linear 0x%p, Physical 0x%p, Violation data 0x%x\n",
            CPU_IDX, __FUNCTION__, 
            pViolationData->Fields.Execute ? "EXECUTE" : (pViolationData->Fields.Read ? "READ" : "WRITE"),
            GuestState->GuestRip, GuestState->LinearAddress, GuestState->PhysicalAddress.QuadPart, pViolationData->All
            );*/

        // Set target host PFN
        ULONG64 TargetPFN = pHookEntry->DataPagePFN;

        // Executable page for writing
        if (pHookEntry->Type == HOOK_SWAP && pViolationData->Fields.Write)
            TargetPFN = pfn;
        // Executable page for TLB splitting
        else if (pHookEntry->Type == HOOK_SPLIT && pViolationData->Fields.Execute)
            TargetPFN = pHookEntry->CodePagePFN;

        // Impossible execute violation
        if(pHookEntry->Type == HOOK_SWAP &&  pViolationData->Fields.Execute)
        {
            DPRINT(
                "HyperBone: CPU %d: %s: Impossible page 0x%p access 0x%X\n", CPU_IDX, __FUNCTION__,
                GuestState->PhysicalAddress.QuadPart, pViolationData->All
                );
        }
        else
            EptUpdateTableRecursive( pEPT, pEPT->PML4Ptr, EPT_TOP_LEVEL, pfn, EPT_ACCESS_ALL, TargetPFN, 1 );
           
        // Do a MTF exit upon resume
        ToggleMTF( TRUE );
        GuestState->Vcpu->HookDispatch.pEntry = pHookEntry;
        GuestState->Vcpu->HookDispatch.Rip = GuestState->GuestRip;
    }
    // Create new identity page map
    else
    {
        /*DPRINT(
                "HyperBone: CPU %d: %s: EPT violation, EIP 0x%p, Linear 0x%p, Physical 0x%p, Violation data 0x%X\n",
                CPU_IDX, __FUNCTION__,
                GuestState->GuestRip, GuestState->LinearAddress, GuestState->PhysicalAddress.QuadPart, pViolationData->All
                );*/

        EptUpdateTableRecursive( pEPT, pEPT->PML4Ptr, EPT_TOP_LEVEL, pfn, EPT_ACCESS_ALL, pfn, 1 );
    }
}
uint64_t read_dword(addr_t address)
{
    address &= 0xFFFFFFFF;

    UINT8 *pr = g_mmap->MemMap[PFN(address)];
    if ((uintptr_t)pr >= MIPS_MAXHANDLER) {
        return BURN_ENDIAN_SWAP_INT64(fast_read<uint64_t>(pr, address));
    }
    return g_mmap->ReadDouble[(uintptr_t)pr](address);
}
uint16_t read_half(addr_t address)
{
    address &= 0xFFFFFFFF;

    UINT8 *pr = g_mmap->MemMap[PFN(address)];
    if ((uintptr_t)pr >= MIPS_MAXHANDLER) {
        return BURN_ENDIAN_SWAP_INT16(fast_read<uint16_t>(pr, address));
    }
    return g_mmap->ReadHalf[(uintptr_t)pr](address);
}
uint8_t read_byte(addr_t address)
{
    address &= 0xFFFFFFFF;

    UINT8 *pr = g_mmap->MemMap[PFN(address)];
    if ((uintptr_t)pr >= MIPS_MAXHANDLER) {
        return pr[address & PAGE_MASK];
    }
    return g_mmap->ReadByte[(uintptr_t)pr](address);
}
void write_dword(addr_t address, uint64_t value)
{
    address &= 0xFFFFFFFF;

    UINT8 *pr = g_mmap->MemMap[PAGE_WADD + PFN(address)];
    if ((uintptr_t)pr >= MIPS_MAXHANDLER) {
        fast_write<uint64_t>(pr, address, BURN_ENDIAN_SWAP_INT64(value));
        return;
    }
    g_mmap->WriteDouble[(uintptr_t)pr](address, value);
}
void write_byte(addr_t address, uint8_t value)
{
    address &= 0xFFFFFFFF;

    UINT8 *pr = g_mmap->MemMap[PAGE_WADD + PFN(address)];
    if ((uintptr_t)pr >= MIPS_MAXHANDLER) {
        pr[address & PAGE_MASK] = value;
        return;
    }
    g_mmap->WriteByte[(uintptr_t)pr](address, value);
}
Exemple #12
0
/// <summary>
/// Update EPT entry
/// </summary>
/// <param name="pEPTData">CPU EPT data</param>
/// <param name="pTable">EPT table</param>
/// <param name="level">EPT table level</param>
/// <param name="pfn">Page frame number to update</param>
/// <param name="access">New PFN access</param>
/// <param name="hostPFN">New hot PFN</param>
/// <param name="count">Number of entries to update</param>
/// <returns>Status code</returns>
NTSTATUS EptUpdateTableRecursive( 
    IN PEPT_DATA pEPTData,
    IN PEPT_MMPTE pTable,
    IN EPT_TABLE_LEVEL level,
    IN ULONG64 pfn,
    IN UCHAR access,
    IN ULONG64 hostPFN,
    IN ULONG count
    )
{
    if (level == EPT_LEVEL_PTE)
    {
        ULONG64 first = EptpTableOffset( pfn, level );
        ASSERT( first + count <= EPT_TABLE_ENTRIES );

        PEPT_PTE_ENTRY pPTE = (PEPT_PTE_ENTRY)pTable;
        for (ULONG64 i = first; i < first + count; i++, hostPFN++)        
        {
            pPTE[i].Fields.Read       = (access & EPT_ACCESS_READ)  != 0;
            pPTE[i].Fields.Write      = (access & EPT_ACCESS_WRITE) != 0;
            pPTE[i].Fields.Execute    = (access & EPT_ACCESS_EXEC)  != 0;
            pPTE[i].Fields.MemoryType = VMX_MEM_TYPE_WRITEBACK;
            pPTE[i].Fields.PhysAddr   = hostPFN;
        }

        return STATUS_SUCCESS;
    }

    ULONG64 offset = EptpTableOffset( pfn, level );
    PEPT_MMPTE pEPT = &pTable[offset];
    PEPT_MMPTE pNewEPT = 0;

    if (pEPT->Fields.PhysAddr == 0)
    {
        pNewEPT = (PEPT_MMPTE)EptpAllocatePage( pEPTData );
        if (pNewEPT == NULL)          
            return STATUS_INSUFFICIENT_RESOURCES;

        pEPT->Fields.Present  = 1;
        pEPT->Fields.Write    = 1;
        pEPT->Fields.Execute  = 1;
        pEPT->Fields.PhysAddr = PFN( MmGetPhysicalAddress( pNewEPT ).QuadPart );
    }
    else
    {
        PHYSICAL_ADDRESS phys = { 0 };
        phys.QuadPart = pEPT->Fields.PhysAddr << 12;
        pNewEPT = MmGetVirtualForPhysical( phys );
    }

    return EptUpdateTableRecursive( pEPTData, pNewEPT, level - 1, pfn, access, hostPFN, count );
}
Exemple #13
0
static u64 del_lru_elem_unlocked(struct ce_array *ca)
{
	unsigned int min = FULL_COUNT_MASK;
	int i, min_idx = 0;

	for (i = 0; i < ca->n; i++) {
		unsigned int this = FULL_COUNT(ca->array[i]);

		if (min > this) {
			min = this;
			min_idx = i;
		}
	}

	del_elem(ca, min_idx);

	return PFN(ca->array[min_idx]);
}
Exemple #14
0
/// <summary>
/// Hook function
/// </summary>
/// <param name="pFunc">Function address</param>
/// <param name="pHook">Hook address</param>
/// /// <param name="Type">Hook type</param>
/// <returns>Status code</returns>
NTSTATUS PHHook( IN PVOID pFunc, IN PVOID pHook, IN HOOK_TYPE Type )
{
    PUCHAR CodePage = NULL;
    BOOLEAN Newpage = FALSE;
    PHYSICAL_ADDRESS phys = { 0 };
    phys.QuadPart = MAXULONG64;

    // No CPU support
    if (!g_Data->EPTSupported || !g_Data->EPTExecOnlySupported)
        return STATUS_NOT_SUPPORTED;

    // Check if page is already hooked
    PPAGE_HOOK_ENTRY pEntry = PHGetHookEntryByPage( pFunc, DATA_PAGE );
    if (pEntry != NULL)
    {
        CodePage = pEntry->CodePageVA;
    }
    else
    {
        CodePage = MmAllocateContiguousMemory( PAGE_SIZE, phys );
        Newpage = TRUE;
    }

    if (CodePage == NULL)
        return STATUS_INSUFFICIENT_RESOURCES;

    PPAGE_HOOK_ENTRY pHookEntry = ExAllocatePoolWithTag( NonPagedPool, sizeof( PAGE_HOOK_ENTRY ), HB_POOL_TAG );
    if (pHookEntry == NULL)
        return STATUS_INSUFFICIENT_RESOURCES;

    RtlZeroMemory( pHookEntry, sizeof( PAGE_HOOK_ENTRY ) );
    RtlCopyMemory( CodePage, PAGE_ALIGN( pFunc ), PAGE_SIZE );
    
    // Copy original code
    NTSTATUS status = PHpCopyCode( pFunc, pHookEntry->OriginalData, &pHookEntry->OriginalSize );
    if (!NT_SUCCESS( status ))
    {
        ExFreePoolWithTag( pHookEntry, HB_POOL_TAG );
        return status;
    }

    ULONG_PTR page_offset = (ULONG_PTR)pFunc - (ULONG_PTR)PAGE_ALIGN( pFunc );

    // TODO: atomic memory patching, i.e. with other CPUs spinlocked
    JUMP_THUNK thunk = { 0 };
    PHpInitJumpThunk( &thunk, (ULONG64)pHook );
    memcpy( CodePage + page_offset, &thunk, sizeof( thunk ) );

    pHookEntry->Type = Type;
    pHookEntry->OriginalPtr = pFunc;
    pHookEntry->DataPageVA = PAGE_ALIGN( pFunc );
    pHookEntry->DataPagePFN = PFN( MmGetPhysicalAddress( pFunc ).QuadPart );
    pHookEntry->CodePageVA = CodePage;
    pHookEntry->CodePagePFN = PFN( MmGetPhysicalAddress( CodePage ).QuadPart );

    // Add to list
    if (g_PageList.Flink == NULL)
        InitializeListHead( &g_PageList );
    InsertTailList( &g_PageList, &pHookEntry->Link );

    // Create EPT page translation
    if (Newpage)
    {
        HOOK_CONTEXT ctx = { 0 };
        ctx.Hook = TRUE;
        ctx.DataPagePFN = pHookEntry->DataPagePFN;
        ctx.CodePagePFN = pHookEntry->CodePagePFN;
        ctx.Type = Type;

        KeGenericCallDpc( PHpHookCallbackDPC, &ctx );
    }

    return STATUS_SUCCESS;
}
Exemple #15
0
    return *((T*)  ((uint8_t*) ptr + (adr & PAGE_MASK)));
}

template<typename T>
inline void fast_write(uint8_t *xptr, unsigned adr, T value) {
    T *ptr = ((T*)  ((uint8_t*) xptr + (adr & PAGE_MASK)));
    *ptr = value;
}

UINT16 adsp21xx_data_read_word_16le(UINT32 address)
{
//    address &= 0xFFFF;
    address >>= 1;
    address &= 0x3FFF;

    UINT8 *pr = pMemMap->DataMap[PFN(address)];
    if ((uintptr_t)pr >= ADSP_MAXHANDLER) {
        return BURN_ENDIAN_SWAP_INT16(fast_read<uint16_t>(pr, address));
    }
    return pMemMap->dataReadWord[(uintptr_t)pr](address);
}

void adsp21xx_data_write_word_16le(UINT32 address, UINT16 data)
{
//    address &= 0xFFFF;
    address >>= 1;
    address &= 0x3FFF;

    UINT8 *pr = pMemMap->DataMap[PAGE_WADD + PFN(address)];
    if ((uintptr_t)pr >= ADSP_MAXHANDLER) {
        fast_write<uint16_t>(pr, address, BURN_ENDIAN_SWAP_INT16(data));