Page MenuHomedesp's stash

No OneTemporary

diff --git a/src/avmext/ntinternal.h b/src/avmext/ntinternal.h
index 89267bd..ad311b5 100644
--- a/src/avmext/ntinternal.h
+++ b/src/avmext/ntinternal.h
@@ -1,227 +1,222 @@
#pragma once
#include <ntifs.h>
#pragma warning (disable : 4201)
#pragma warning (disable : 4204)
#pragma warning (disable : 4214)
//
// Inspired by WRK.
//
#define CR4_TSD 0x00000004 // Time stamp disable
+#define CR0_WP 0x10000 // Write Protection enable
+
#define ReadTSC() __rdtsc()
#define ReadTSCP(data) __rdtscp(data)
+#define ReadCR0() __readcr0()
+#define WriteCR0(data) __writecr0(data)
+
#define ReadCR4() __readcr4()
#define WriteCR4(data) __writecr4(data)
#define ReadIDT(data) __sidt(data)
#define WriteIDT(data) __lidt(data)
#define EnableInterrupts() _enable() // sti instruction
#define DisableInterrupts() _disable() // cli instruction
//
// IDT descriptor.
//
struct _AVM_KDESCRIPTOR32
{
USHORT Pad;
USHORT Limit;
ULONG Base;
};
-struct _AVM_KDESCRIPTOR64
-{
- union
- {
- struct
- {
- USHORT Pad[3];
- USHORT Limit;
- };
-
- ULONG_PTR LowPart;
- };
- union
- {
- ULONG_PTR Base;
- ULONG_PTR HighPart;
- };
-};
-
//
// Entry of Interrupt Descriptor Table (IDTENTRY)
//
struct _AVM_KIDTENTRY32
{
USHORT Offset;
USHORT Selector;
USHORT Access;
USHORT ExtendedOffset;
};
+#pragma pack(1)
+struct _AVM_KDESCRIPTOR64
+{
+ USHORT limit;
+ ULONG64 Base;
+};
+
struct _AVM_KIDTENTRY64
{
union
{
struct
{
USHORT OffsetLow;
USHORT Selector;
USHORT IstIndex : 3;
USHORT Reserved0 : 5;
USHORT Type : 5;
USHORT Dpl : 2;
USHORT Present : 1;
USHORT OffsetMiddle;
ULONG OffsetHigh;
ULONG Reserved1;
};
ULONG64 Alignment;
};
};
+#pragma pack()
+
//
// Trap frame
//
struct _AVM_KTRAP_FRAME32
{
//
// Segment registers
//
ULONG SegGs;
ULONG SegEs;
ULONG SegDs;
//
// Volatile registers
//
ULONG Edx;
ULONG Ecx;
ULONG Eax;
//
// FS is TIB/PCR pointer, is here to make save sequence easy
//
ULONG SegFs;
//
// Non-volatile registers
//
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Ebp;
//
// Control registers
//
ULONG ErrCode;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG HardwareEsp; // WARNING - segSS:esp are only here for stacks
ULONG HardwareSegSs; // that involve a ring transition.
};
struct _AVM_KTRAP_FRAME64
{
//
// Volatile registers.
//
// N.B. These registers are only saved on exceptions and interrupts. They
// are not saved for system calls.
//
ULONG64 Rax;
ULONG64 Rcx;
ULONG64 Rdx;
ULONG64 R8;
ULONG64 R9;
ULONG64 R10;
ULONG64 R11;
//
// Saved nonvolatile registers RBX, RDI and RSI. These registers are only
// saved in system service trap frames.
//
ULONG64 Rbx;
ULONG64 Rdi;
ULONG64 Rsi;
//
// Saved nonvolatile register RBP. This register is used as a frame
// pointer during trap processing and is saved in all trap frames.
//
ULONG64 Rbp;
//
// Information pushed by hardware.
//
// N.B. The error code is not always pushed by hardware. For those cases
// where it is not pushed by hardware a dummy error code is allocated
// on the stack.
//
union
{
ULONG64 ErrorCode;
ULONG64 ExceptionFrame;
};
ULONG64 Rip;
USHORT SegCs;
USHORT Fill1[3];
ULONG EFlags;
ULONG Fill2;
ULONG64 Rsp;
USHORT SegSs;
USHORT Fill3[1];
};
#if defined(_X86_)
typedef struct _AVM_KDESCRIPTOR32 AVM_KDESCRIPTOR, *PAVM_KDESCRIPTOR;
typedef struct _AVM_KIDTENTRY32 AVM_KIDTENTRY, *PAVM_KIDTENTRY;
typedef struct _AVM_KTRAP_FRAME32 AVM_KTRAP_FRAME, *PAVM_KTRAP_FRAME;
#elif defined(_AMD64_)
typedef struct _AVM_KDESCRIPTOR64 AVM_KDESCRIPTOR, *PAVM_KDESCRIPTOR;
typedef struct _AVM_KIDTENTRY64 AVM_KIDTENTRY, *PAVM_KIDTENTRY;
typedef struct _AVM_KTRAP_FRAME64 AVM_KTRAP_FRAME, *PAVM_KTRAP_FRAME;
#else
# error "Unknown architecture"
#endif
//
// Initialize & destroy routines.
//
NTSTATUS
NTAPI
AvmNtInternalInitialize(
IN PDRIVER_OBJECT DriverObject
);
VOID
NTAPI
AvmNtInternalDestroy(
IN PDRIVER_OBJECT DriverObject
);
diff --git a/src/avmext/rdtscemup.c b/src/avmext/rdtscemup.c
index 0e59eb5..0c52e9a 100644
--- a/src/avmext/rdtscemup.c
+++ b/src/avmext/rdtscemup.c
@@ -1,125 +1,164 @@
#include "rdtscemu.h"
#include "ntinternal.h"
#include <ntifs.h>
#include <ndis.h>
//
// It is very unlikely that each CPU will have different Trap0D handlers.
//
ULONG_PTR AvmpRdtscEmulationTrap0DOriginalHandler;
//
// Set CR4_TSD flag into the CR4 register.
//
VOID
NTAPI
AvmpRdtscEmulationSetTimeStampDisableFlag(
VOID
)
{
WriteCR4(ReadCR4() | CR4_TSD);
}
//
// Unset CR4_TSD flag from the CR4 register.
//
VOID
NTAPI
AvmpRdtscEmulationUnsetTimeStampDisableFlag(
VOID
)
{
WriteCR4(ReadCR4() & ~CR4_TSD);
}
//
// Force immediate context switch immediate context switch if the current processor
// does not fall in the newly set affinity mask and does not return to the caller
// until the thread is rescheduled on a processor conforming to the new affinity mask.
//
// ref: http://www.drdobbs.com/monitoring-nt-debug-services/184416239
//
VOID
NTAPI
AvmpRdtscEmulationSwitchToProcessor(
IN UCHAR ProcessorIndex
)
{
//
// If KeSetSystemAffinityThread is called at IRQL <= APC_LEVEL and the call is successful,
// the new affinity mask takes effect immediately.
//
// ref: https://msdn.microsoft.com/en-us/library/windows/hardware/ff553267(v=vs.85).aspx (see Remarks section)
//
if (KeGetCurrentIrql() > APC_LEVEL)
{
KeLowerIrql(APC_LEVEL);
}
KeSetSystemAffinityThread(AFFINITY_MASK(ProcessorIndex));
}
//
// Replace IDT entry.
//
#if defined(_X86_)
VOID
NTAPI
AvmpRdtscEmulationHookInterruptEntry(
IN UCHAR Index,
IN ULONG_PTR NewRoutineAddress,
OUT ULONG_PTR* OldRoutineAddress
)
{
AVM_KDESCRIPTOR Idtr;
ReadIDT(&Idtr);
PAVM_KIDTENTRY Idt = (PAVM_KIDTENTRY)(Idtr.Limit | Idtr.Base << 16);
DisableInterrupts();
{
ULONG_PTR OriginalHandler = (ULONG)(Idt[Index].ExtendedOffset) << 16 | Idt[Index].Offset;
Idt[Index].Offset = (USHORT)NewRoutineAddress;
Idt[Index].ExtendedOffset = (USHORT)((ULONG_PTR)NewRoutineAddress >> 16);
*OldRoutineAddress = OriginalHandler;
}
EnableInterrupts();
}
#else
+//
+// WP bit needs to be disabled on newer Windows 64-bit versions,
+// Presumably due to Kernel Data Protection.
+// Code referenced from https://github.com/LLLZed/IDTHOOK
+//
+
+KIRQL WPOFFx64()
+{
+ KIRQL irql = KeRaiseIrqlToDpcLevel();
+ UINT64 cr0 = ReadCR0();
+ cr0 &= ~CR0_WP;
+ WriteCR0(cr0);
+ DisableInterrupts();
+ return irql;
+}
+
+void WPONx64(KIRQL irql)
+{
+ UINT64 cr0 = ReadCR0();
+ cr0 |= CR0_WP;
+ EnableInterrupts();
+ WriteCR0(cr0);
+ KeLowerIrql(irql);
+}
+
+ULONG64 SetIdtAddr(ULONG64 IdtBaseAddr, UCHAR Index, ULONG64 NewAddr)
+{
+ PAVM_KIDTENTRY Pidt = (PAVM_KIDTENTRY)(IdtBaseAddr);
+ Pidt = Pidt + Index;
+ ULONG64 OffsetHigh, OffsetMiddle, OffsetLow, ret;
+
+
+ OffsetHigh = Pidt->OffsetHigh;
+ OffsetHigh = OffsetHigh << 32;
+ OffsetMiddle = Pidt->OffsetMiddle;
+ OffsetMiddle = OffsetMiddle << 16;
+
+ OffsetLow = Pidt->OffsetLow;
+ ret = OffsetHigh + OffsetMiddle + OffsetLow;
+ Pidt->OffsetHigh = NewAddr >> 32;
+ Pidt->OffsetMiddle = NewAddr << 32 >> 48;
+ Pidt->OffsetLow = NewAddr & 0xFFFF;
+ return ret;
+}
+
+//
+// System might triple fault using this method if KVA Shadowing is enabled,
+// Disable through registry before continuing.
+//
+
VOID
NTAPI
AvmpRdtscEmulationHookInterruptEntry(
IN UCHAR Index,
IN ULONG_PTR NewRoutineAddress,
OUT ULONG_PTR* OldRoutineAddress
)
{
AVM_KDESCRIPTOR Idtr;
ReadIDT(&Idtr);
- PAVM_KIDTENTRY Idt = (PAVM_KIDTENTRY)(Idtr.LowPart >> 16 | Idtr.HighPart << 48);
- PAVM_KIDTENTRY IdtAt = &Idt[Index];
-
- DisableInterrupts();
- {
- ULONG_PTR OriginalHandler = (ULONG_PTR)Idt[Index].OffsetLow |
- (ULONG_PTR)Idt[Index].OffsetMiddle << 16 |
- (ULONG_PTR)Idt[Index].OffsetHigh << 32;
+ KIRQL IRQL = WPOFFx64();
- IdtAt->OffsetLow = (USHORT)(NewRoutineAddress);
- IdtAt->OffsetMiddle = (USHORT)(NewRoutineAddress >> 16);
- IdtAt->OffsetHigh = (ULONG) (NewRoutineAddress >> 32);
+ *OldRoutineAddress = SetIdtAddr(Idtr.Base, Index, NewRoutineAddress);
- *OldRoutineAddress = OriginalHandler;
- }
- EnableInterrupts();
+ WPONx64(IRQL);
}
#endif

File Metadata

Mime Type
text/x-diff
Expires
Fri, Mar 14, 10:17 PM (12 h, 2 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
37/03/061874dce1ae5a34b9f1e280a381

Event Timeline