mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
indentation
This commit is contained in:
parent
49c7ff65f1
commit
3aa74dedfe
23 changed files with 6728 additions and 7041 deletions
|
@ -61,7 +61,7 @@ ExperimentalAutoDetectBinPacking: false
|
|||
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 8
|
||||
IndentWidth: 4
|
||||
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
|
|
170
driver/apc.c
170
driver/apc.c
|
@ -6,30 +6,30 @@
|
|||
VOID
|
||||
GetApcContextByIndex(_Out_ PVOID* Context, _In_ INT Index)
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
*Context = GetApcContextArray()[Index];
|
||||
ReleaseDriverConfigLock();
|
||||
AcquireDriverConfigLock();
|
||||
*Context = GetApcContextArray()[Index];
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
VOID
|
||||
GetApcContext(_Out_ PVOID* Context, _In_ LONG ContextIdentifier)
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PAPC_CONTEXT_HEADER header = GetApcContextArray()[index];
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PAPC_CONTEXT_HEADER header = GetApcContextArray()[index];
|
||||
|
||||
if (!header)
|
||||
continue;
|
||||
if (!header)
|
||||
continue;
|
||||
|
||||
if (header->context_id != ContextIdentifier)
|
||||
continue;
|
||||
if (header->context_id != ContextIdentifier)
|
||||
continue;
|
||||
|
||||
*Context = header;
|
||||
goto unlock;
|
||||
}
|
||||
*Context = header;
|
||||
goto unlock;
|
||||
}
|
||||
unlock:
|
||||
ReleaseDriverConfigLock();
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -41,54 +41,54 @@ unlock:
|
|||
BOOLEAN
|
||||
FreeApcContextStructure(_Out_ PAPC_CONTEXT_HEADER Context)
|
||||
{
|
||||
DEBUG_VERBOSE("All APCs executed, freeing context structure");
|
||||
DEBUG_VERBOSE("All APCs executed, freeing context structure");
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] != Context)
|
||||
continue;
|
||||
if (entry[index] != Context)
|
||||
continue;
|
||||
|
||||
if (Context->count > 0)
|
||||
return FALSE;
|
||||
if (Context->count > 0)
|
||||
return FALSE;
|
||||
|
||||
ImpExFreePoolWithTag(Context, POOL_TAG_APC);
|
||||
entry[index] = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
ImpExFreePoolWithTag(Context, POOL_TAG_APC);
|
||||
entry[index] = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
IncrementApcCount(_In_ LONG ContextId)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER header = NULL;
|
||||
GetApcContext(&header, ContextId);
|
||||
PAPC_CONTEXT_HEADER header = NULL;
|
||||
GetApcContext(&header, ContextId);
|
||||
|
||||
if (!header)
|
||||
return;
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
/* i actually dont think we need this lock here */
|
||||
AcquireDriverConfigLock();
|
||||
header->count += 1;
|
||||
ReleaseDriverConfigLock();
|
||||
/* i actually dont think we need this lock here */
|
||||
AcquireDriverConfigLock();
|
||||
header->count += 1;
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER context = NULL;
|
||||
PAPC_CONTEXT_HEADER context = NULL;
|
||||
|
||||
ImpExFreePoolWithTag(Apc, POOL_TAG_APC);
|
||||
GetApcContext(&context, ContextId);
|
||||
ImpExFreePoolWithTag(Apc, POOL_TAG_APC);
|
||||
GetApcContext(&context, ContextId);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
AcquireDriverConfigLock();
|
||||
context->count -= 1;
|
||||
ReleaseDriverConfigLock();
|
||||
AcquireDriverConfigLock();
|
||||
context->count -= 1;
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -121,49 +121,49 @@ FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId)
|
|||
NTSTATUS
|
||||
QueryActiveApcContextsForCompletion()
|
||||
{
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PAPC_CONTEXT_HEADER entry = NULL;
|
||||
GetApcContextByIndex(&entry, index);
|
||||
AcquireDriverConfigLock();
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PAPC_CONTEXT_HEADER entry = NULL;
|
||||
GetApcContextByIndex(&entry, index);
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
if (!entry)
|
||||
goto increment;
|
||||
if (!entry)
|
||||
goto increment;
|
||||
|
||||
if (entry->count > 0 || entry->allocation_in_progress == TRUE)
|
||||
goto increment;
|
||||
if (entry->count > 0 || entry->allocation_in_progress == TRUE)
|
||||
goto increment;
|
||||
|
||||
switch (entry->context_id) {
|
||||
case APC_CONTEXT_ID_STACKWALK:
|
||||
FreeApcStackwalkApcContextInformation(entry);
|
||||
FreeApcContextStructure(entry);
|
||||
break;
|
||||
}
|
||||
|
||||
increment:
|
||||
ReleaseDriverConfigLock();
|
||||
switch (entry->context_id) {
|
||||
case APC_CONTEXT_ID_STACKWALK:
|
||||
FreeApcStackwalkApcContextInformation(entry);
|
||||
FreeApcContextStructure(entry);
|
||||
break;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
increment:
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
InsertApcContext(_In_ PVOID Context)
|
||||
{
|
||||
if (IsDriverUnloading())
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
if (IsDriverUnloading())
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
AcquireDriverConfigLock();
|
||||
PAPC_CONTEXT_HEADER header = Context;
|
||||
AcquireDriverConfigLock();
|
||||
PAPC_CONTEXT_HEADER header = Context;
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] == NULL) {
|
||||
entry[index] = Context;
|
||||
goto end;
|
||||
}
|
||||
if (entry[index] == NULL) {
|
||||
entry[index] = Context;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
end:
|
||||
ReleaseDriverConfigLock();
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -196,24 +196,24 @@ end:
|
|||
BOOLEAN
|
||||
DrvUnloadFreeAllApcContextStructures()
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] == NULL)
|
||||
continue;
|
||||
if (entry[index] == NULL)
|
||||
continue;
|
||||
|
||||
PAPC_CONTEXT_HEADER context = entry[index];
|
||||
PAPC_CONTEXT_HEADER context = entry[index];
|
||||
|
||||
if (context->count > 0) {
|
||||
ReleaseDriverConfigLock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ImpExFreePoolWithTag(entry, POOL_TAG_APC);
|
||||
if (context->count > 0) {
|
||||
ReleaseDriverConfigLock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ImpExFreePoolWithTag(entry, POOL_TAG_APC);
|
||||
}
|
||||
unlock:
|
||||
ReleaseDriverConfigLock();
|
||||
return TRUE;
|
||||
ReleaseDriverConfigLock();
|
||||
return TRUE;
|
||||
}
|
1344
driver/callbacks.c
1344
driver/callbacks.c
File diff suppressed because it is too large
Load diff
|
@ -16,20 +16,20 @@ typedef void (*PROCESSLIST_CALLBACK_ROUTINE)(
|
|||
#define SHA_256_HASH_LENGTH 32
|
||||
|
||||
typedef struct _DRIVER_LIST_ENTRY {
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
BOOLEAN hashed;
|
||||
BOOLEAN x86;
|
||||
CHAR path[DRIVER_PATH_LENGTH];
|
||||
CHAR text_hash[SHA_256_HASH_LENGTH];
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
BOOLEAN hashed;
|
||||
BOOLEAN x86;
|
||||
CHAR path[DRIVER_PATH_LENGTH];
|
||||
CHAR text_hash[SHA_256_HASH_LENGTH];
|
||||
|
||||
/*
|
||||
* This LIST_ENTRY is to be used for modules where the hashing needs to
|
||||
* be deferred. For example, when x86 modules can't be hashed on driver
|
||||
* load.
|
||||
*/
|
||||
LIST_ENTRY deferred_entry;
|
||||
/*
|
||||
* This LIST_ENTRY is to be used for modules where the hashing needs to
|
||||
* be deferred. For example, when x86 modules can't be hashed on driver
|
||||
* load.
|
||||
*/
|
||||
LIST_ENTRY deferred_entry;
|
||||
|
||||
} DRIVER_LIST_ENTRY, *PDRIVER_LIST_ENTRY;
|
||||
|
||||
|
|
1799
driver/common.h
1799
driver/common.h
File diff suppressed because it is too large
Load diff
144
driver/crypt.c
144
driver/crypt.c
|
@ -14,37 +14,34 @@ STATIC
|
|||
__m256i
|
||||
CryptGenerateSseXorKey()
|
||||
{
|
||||
return _mm256_set_epi64x(XOR_KEY_1, XOR_KEY_2, XOR_KEY_3, XOR_KEY_4);
|
||||
return _mm256_set_epi64x(XOR_KEY_1, XOR_KEY_2, XOR_KEY_3, XOR_KEY_4);
|
||||
}
|
||||
|
||||
VOID
|
||||
CryptEncryptImportsArray(_In_ PUINT64 Array, _In_ UINT32 Entries)
|
||||
{
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
UINT32 block_count = Entries / block_size;
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
UINT32 block_count = Entries / block_size;
|
||||
|
||||
/*
|
||||
* Here we break down the import array into blocks of 32 bytes. Each
|
||||
* block is loaded into an SSE register, xored with the key, and then
|
||||
* copied back into the array.
|
||||
*/
|
||||
for (UINT32 block_index = 0; block_index < block_count; block_index++) {
|
||||
__m256i current_block = {0};
|
||||
__m256i load_block = {0};
|
||||
__m256i xored_block = {0};
|
||||
/*
|
||||
* Here we break down the import array into blocks of 32 bytes. Each
|
||||
* block is loaded into an SSE register, xored with the key, and then
|
||||
* copied back into the array.
|
||||
*/
|
||||
for (UINT32 block_index = 0; block_index < block_count; block_index++) {
|
||||
__m256i current_block = {0};
|
||||
__m256i load_block = {0};
|
||||
__m256i xored_block = {0};
|
||||
|
||||
RtlCopyMemory(¤t_block,
|
||||
&Array[block_index * block_size],
|
||||
sizeof(__m256i));
|
||||
RtlCopyMemory(
|
||||
¤t_block, &Array[block_index * block_size], sizeof(__m256i));
|
||||
|
||||
load_block = _mm256_loadu_si256(¤t_block);
|
||||
xored_block =
|
||||
_mm256_xor_si256(load_block, CryptGenerateSseXorKey());
|
||||
load_block = _mm256_loadu_si256(¤t_block);
|
||||
xored_block = _mm256_xor_si256(load_block, CryptGenerateSseXorKey());
|
||||
|
||||
RtlCopyMemory(&Array[block_index * block_size],
|
||||
&xored_block,
|
||||
sizeof(__m256i));
|
||||
}
|
||||
RtlCopyMemory(
|
||||
&Array[block_index * block_size], &xored_block, sizeof(__m256i));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
|
@ -52,13 +49,13 @@ INLINE
|
|||
__m256i
|
||||
CryptDecryptImportBlock(_In_ PUINT64 Array, _In_ UINT32 BlockIndex)
|
||||
{
|
||||
__m256i load_block = {0};
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
__m256i load_block = {0};
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
|
||||
RtlCopyMemory(
|
||||
&load_block, &Array[BlockIndex * block_size], sizeof(__m256i));
|
||||
RtlCopyMemory(
|
||||
&load_block, &Array[BlockIndex * block_size], sizeof(__m256i));
|
||||
|
||||
return _mm256_xor_si256(load_block, CryptGenerateSseXorKey());
|
||||
return _mm256_xor_si256(load_block, CryptGenerateSseXorKey());
|
||||
}
|
||||
|
||||
STATIC
|
||||
|
@ -69,28 +66,28 @@ CryptFindContainingBlockForArrayIndex(_In_ UINT32 EntryIndex,
|
|||
_Out_ PUINT32 ContainingBlockIndex,
|
||||
_Out_ PUINT32 BlockSubIndex)
|
||||
{
|
||||
UINT32 containing_block = EntryIndex;
|
||||
UINT32 block_index = 0;
|
||||
UINT32 containing_block = EntryIndex;
|
||||
UINT32 block_index = 0;
|
||||
|
||||
if (EntryIndex < BlockSize) {
|
||||
*ContainingBlockIndex = 0;
|
||||
*BlockSubIndex = EntryIndex;
|
||||
return;
|
||||
}
|
||||
if (EntryIndex < BlockSize) {
|
||||
*ContainingBlockIndex = 0;
|
||||
*BlockSubIndex = EntryIndex;
|
||||
return;
|
||||
}
|
||||
|
||||
if (EntryIndex == BlockSize) {
|
||||
*ContainingBlockIndex = 1;
|
||||
*BlockSubIndex = 0;
|
||||
return;
|
||||
}
|
||||
if (EntryIndex == BlockSize) {
|
||||
*ContainingBlockIndex = 1;
|
||||
*BlockSubIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while (containing_block % BlockSize != 0) {
|
||||
containing_block--;
|
||||
block_index++;
|
||||
}
|
||||
while (containing_block % BlockSize != 0) {
|
||||
containing_block--;
|
||||
block_index++;
|
||||
}
|
||||
|
||||
*ContainingBlockIndex = containing_block / BlockSize;
|
||||
*BlockSubIndex = block_index;
|
||||
*ContainingBlockIndex = containing_block / BlockSize;
|
||||
*BlockSubIndex = block_index;
|
||||
}
|
||||
|
||||
UINT64
|
||||
|
@ -98,36 +95,36 @@ CryptDecryptImportsArrayEntry(_In_ PUINT64 Array,
|
|||
_In_ UINT32 Entries,
|
||||
_In_ UINT32 EntryIndex)
|
||||
{
|
||||
__m256i original_block = {0};
|
||||
__m128i original_half = {0};
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
UINT32 containing_block_index = 0;
|
||||
UINT32 block_sub_index = 0;
|
||||
UINT64 pointer = 0;
|
||||
__m256i original_block = {0};
|
||||
__m128i original_half = {0};
|
||||
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
|
||||
UINT32 containing_block_index = 0;
|
||||
UINT32 block_sub_index = 0;
|
||||
UINT64 pointer = 0;
|
||||
|
||||
CryptFindContainingBlockForArrayIndex(
|
||||
EntryIndex, block_size, &containing_block_index, &block_sub_index);
|
||||
CryptFindContainingBlockForArrayIndex(
|
||||
EntryIndex, block_size, &containing_block_index, &block_sub_index);
|
||||
|
||||
original_block = CryptDecryptImportBlock(Array, containing_block_index);
|
||||
original_block = CryptDecryptImportBlock(Array, containing_block_index);
|
||||
|
||||
if (block_sub_index < 2) {
|
||||
original_half = _mm256_extracti128_si256(original_block, 0);
|
||||
if (block_sub_index < 2) {
|
||||
original_half = _mm256_extracti128_si256(original_block, 0);
|
||||
|
||||
if (block_sub_index < 1)
|
||||
pointer = _mm_extract_epi64(original_half, 0);
|
||||
else
|
||||
pointer = _mm_extract_epi64(original_half, 1);
|
||||
}
|
||||
else {
|
||||
original_half = _mm256_extracti128_si256(original_block, 1);
|
||||
if (block_sub_index < 1)
|
||||
pointer = _mm_extract_epi64(original_half, 0);
|
||||
else
|
||||
pointer = _mm_extract_epi64(original_half, 1);
|
||||
}
|
||||
else {
|
||||
original_half = _mm256_extracti128_si256(original_block, 1);
|
||||
|
||||
if (block_sub_index == 2)
|
||||
pointer = _mm_extract_epi64(original_half, 0);
|
||||
else
|
||||
pointer = _mm_extract_epi64(original_half, 1);
|
||||
}
|
||||
if (block_sub_index == 2)
|
||||
pointer = _mm_extract_epi64(original_half, 0);
|
||||
else
|
||||
pointer = _mm_extract_epi64(original_half, 1);
|
||||
}
|
||||
|
||||
return pointer;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -138,9 +135,8 @@ CryptDecryptBufferWithCookie(_In_ PVOID Buffer,
|
|||
_In_ UINT32 BufferSize,
|
||||
_In_ UINT32 Cookie)
|
||||
{
|
||||
PCHAR buffer = (PCHAR)Buffer;
|
||||
|
||||
for (UINT32 index = 0; index < BufferSize; index++) {
|
||||
buffer[index] ^= Cookie;
|
||||
}
|
||||
PCHAR buffer = (PCHAR)Buffer;
|
||||
for (UINT32 index = 0; index < BufferSize; index++) {
|
||||
buffer[index] ^= Cookie;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@ VOID
|
|||
CryptEncryptImportsArray(_In_ PUINT64 Array, _In_ UINT32 Entries);
|
||||
|
||||
UINT64
|
||||
CryptDecryptImportsArrayEntry(_In_ PUINT64 Array, _In_ UINT32 Entries, _In_ UINT32 EntryIndex);
|
||||
CryptDecryptImportsArrayEntry(_In_ PUINT64 Array,
|
||||
_In_ UINT32 Entries,
|
||||
_In_ UINT32 EntryIndex);
|
||||
|
||||
VOID
|
||||
CryptDecryptBufferWithCookie(_In_ PVOID Buffer, _In_ UINT32 BufferSize, _In_ UINT32 Cookie);
|
||||
CryptDecryptBufferWithCookie(_In_ PVOID Buffer,
|
||||
_In_ UINT32 BufferSize,
|
||||
_In_ UINT32 Cookie);
|
||||
|
||||
#endif
|
1002
driver/driver.c
1002
driver/driver.c
File diff suppressed because it is too large
Load diff
129
driver/hv.c
129
driver/hv.c
|
@ -6,7 +6,7 @@
|
|||
#include "io.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
# pragma alloc_text(PAGE, PerformVirtualizationDetection)
|
||||
# pragma alloc_text(PAGE, PerformVirtualizationDetection)
|
||||
#endif
|
||||
|
||||
#define TOTAL_ITERATION_COUNT 20
|
||||
|
@ -25,86 +25,85 @@
|
|||
BOOLEAN
|
||||
APERFMsrTimingCheck()
|
||||
{
|
||||
KAFFINITY new_affinity = {0};
|
||||
KAFFINITY old_affinity = {0};
|
||||
UINT64 old_irql = 0;
|
||||
INT cpuid_result[4];
|
||||
KAFFINITY new_affinity = {0};
|
||||
KAFFINITY old_affinity = {0};
|
||||
UINT64 old_irql = 0;
|
||||
INT cpuid_result[4];
|
||||
|
||||
/*
|
||||
* First thing we do is we lock the current thread to the logical
|
||||
* processor its executing on.
|
||||
*/
|
||||
new_affinity = (KAFFINITY)(1ull << KeGetCurrentProcessorNumber());
|
||||
old_affinity = ImpKeSetSystemAffinityThreadEx(new_affinity);
|
||||
/*
|
||||
* First thing we do is we lock the current thread to the logical
|
||||
* processor its executing on.
|
||||
*/
|
||||
new_affinity = (KAFFINITY)(1ull << KeGetCurrentProcessorNumber());
|
||||
old_affinity = ImpKeSetSystemAffinityThreadEx(new_affinity);
|
||||
|
||||
/*
|
||||
* Once we've locked our thread to the current core, we save the old
|
||||
* irql and raise to HIGH_LEVEL to ensure the chance our thread is
|
||||
* preempted by a thread with a higher IRQL is extremely low.
|
||||
*/
|
||||
old_irql = __readcr8();
|
||||
__writecr8(HIGH_LEVEL);
|
||||
/*
|
||||
* Once we've locked our thread to the current core, we save the old
|
||||
* irql and raise to HIGH_LEVEL to ensure the chance our thread is
|
||||
* preempted by a thread with a higher IRQL is extremely low.
|
||||
*/
|
||||
old_irql = __readcr8();
|
||||
__writecr8(HIGH_LEVEL);
|
||||
|
||||
/*
|
||||
* Then we also disable interrupts, once again making sure our thread
|
||||
* is not preempted.
|
||||
*/
|
||||
_disable();
|
||||
/*
|
||||
* Then we also disable interrupts, once again making sure our thread
|
||||
* is not preempted.
|
||||
*/
|
||||
_disable();
|
||||
|
||||
/*
|
||||
* Once our thread is ready for the test, we read the APERF from the
|
||||
* MSR register and store it. We then execute a CPUID instruction
|
||||
* which we don't really care about and immediately after read the APERF
|
||||
* counter once again and store it in a seperate variable.
|
||||
*/
|
||||
UINT64 aperf_before = __readmsr(IA32_APERF_MSR) << 32;
|
||||
__cpuid(cpuid_result, 1);
|
||||
UINT64 aperf_after = __readmsr(IA32_APERF_MSR) << 32;
|
||||
/*
|
||||
* Once our thread is ready for the test, we read the APERF from the
|
||||
* MSR register and store it. We then execute a CPUID instruction
|
||||
* which we don't really care about and immediately after read the APERF
|
||||
* counter once again and store it in a seperate variable.
|
||||
*/
|
||||
UINT64 aperf_before = __readmsr(IA32_APERF_MSR) << 32;
|
||||
__cpuid(cpuid_result, 1);
|
||||
UINT64 aperf_after = __readmsr(IA32_APERF_MSR) << 32;
|
||||
|
||||
/*
|
||||
* Once we have performed our test, we want to make sure we are not
|
||||
* hogging the cpu time from other threads, so we reverse the initial
|
||||
* preparation process. i.e we first enable interrupts, lower our irql
|
||||
* to the threads previous irql before it was raised and then restore
|
||||
* the threads affinity back to its original affinity.
|
||||
*/
|
||||
_enable();
|
||||
__writecr8(old_irql);
|
||||
ImpKeRevertToUserAffinityThreadEx(old_affinity);
|
||||
/*
|
||||
* Once we have performed our test, we want to make sure we are not
|
||||
* hogging the cpu time from other threads, so we reverse the initial
|
||||
* preparation process. i.e we first enable interrupts, lower our irql
|
||||
* to the threads previous irql before it was raised and then restore
|
||||
* the threads affinity back to its original affinity.
|
||||
*/
|
||||
_enable();
|
||||
__writecr8(old_irql);
|
||||
ImpKeRevertToUserAffinityThreadEx(old_affinity);
|
||||
|
||||
/*
|
||||
* Now the only thing left to do is calculate the change. Now, on some
|
||||
* VMs such as VMWARE the aperf value will be 0, meaning the change will
|
||||
* be 0. This is a dead giveaway we are executing in a VM.
|
||||
*/
|
||||
UINT64 aperf_delta = aperf_after - aperf_before;
|
||||
/*
|
||||
* Now the only thing left to do is calculate the change. Now, on some
|
||||
* VMs such as VMWARE the aperf value will be 0, meaning the change will
|
||||
* be 0. This is a dead giveaway we are executing in a VM.
|
||||
*/
|
||||
UINT64 aperf_delta = aperf_after - aperf_before;
|
||||
|
||||
return aperf_delta == 0 ? TRUE : FALSE;
|
||||
return aperf_delta == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PerformVirtualizationDetection(_Inout_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status =
|
||||
ValidateIrpOutputBuffer(Irp, sizeof(HYPERVISOR_DETECTION_REPORT));
|
||||
NTSTATUS status =
|
||||
ValidateIrpOutputBuffer(Irp, sizeof(HYPERVISOR_DETECTION_REPORT));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
HYPERVISOR_DETECTION_REPORT report = {0};
|
||||
report.aperf_msr_timing_check = APERFMsrTimingCheck();
|
||||
report.invd_emulation_check = TestINVDEmulation();
|
||||
HYPERVISOR_DETECTION_REPORT report = {0};
|
||||
report.aperf_msr_timing_check = APERFMsrTimingCheck();
|
||||
report.invd_emulation_check = TestINVDEmulation();
|
||||
|
||||
Irp->IoStatus.Information = sizeof(HYPERVISOR_DETECTION_REPORT);
|
||||
Irp->IoStatus.Information = sizeof(HYPERVISOR_DETECTION_REPORT);
|
||||
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&report,
|
||||
sizeof(HYPERVISOR_DETECTION_REPORT));
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&report,
|
||||
sizeof(HYPERVISOR_DETECTION_REPORT));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
287
driver/hw.c
287
driver/hw.c
|
@ -67,51 +67,49 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
|
|||
_Out_ PVOID Buffer,
|
||||
_In_ UINT32 BufferLength)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
KEVENT event = {0};
|
||||
IO_STATUS_BLOCK io = {0};
|
||||
PIRP irp = NULL;
|
||||
PIO_STACK_LOCATION io_stack_location = NULL;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
KEVENT event = {0};
|
||||
IO_STATUS_BLOCK io = {0};
|
||||
PIRP irp = NULL;
|
||||
PIO_STACK_LOCATION io_stack_location = NULL;
|
||||
|
||||
if (BufferLength == 0)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
if (BufferLength == 0)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
/*
|
||||
* we dont need to free this IRP as the IO manager will free it when the
|
||||
* request is completed
|
||||
*/
|
||||
irp = IoBuildSynchronousFsdRequest(
|
||||
IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &event, &io);
|
||||
/*
|
||||
* we dont need to free this IRP as the IO manager will free it when the
|
||||
* request is completed
|
||||
*/
|
||||
irp = IoBuildSynchronousFsdRequest(
|
||||
IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &event, &io);
|
||||
|
||||
if (!irp) {
|
||||
DEBUG_ERROR(
|
||||
"IoBuildSynchronousFsdRequest failed with no status.");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
if (!irp) {
|
||||
DEBUG_ERROR("IoBuildSynchronousFsdRequest failed with no status.");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
io_stack_location = IoGetNextIrpStackLocation(irp);
|
||||
io_stack_location->MinorFunction = IRP_MN_READ_CONFIG;
|
||||
io_stack_location->Parameters.ReadWriteConfig.WhichSpace =
|
||||
PCI_WHICHSPACE_CONFIG;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Offset = Offset;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Buffer = Buffer;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Length = BufferLength;
|
||||
io_stack_location = IoGetNextIrpStackLocation(irp);
|
||||
io_stack_location->MinorFunction = IRP_MN_READ_CONFIG;
|
||||
io_stack_location->Parameters.ReadWriteConfig.WhichSpace =
|
||||
PCI_WHICHSPACE_CONFIG;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Offset = Offset;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Buffer = Buffer;
|
||||
io_stack_location->Parameters.ReadWriteConfig.Length = BufferLength;
|
||||
|
||||
status = IoCallDriver(DeviceObject, irp);
|
||||
status = IoCallDriver(DeviceObject, irp);
|
||||
|
||||
if (status = STATUS_PENDING) {
|
||||
KeWaitForSingleObject(
|
||||
&event, Executive, KernelMode, FALSE, NULL);
|
||||
status = io.Status;
|
||||
}
|
||||
if (status = STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
||||
status = io.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("Failed to read configuration space with status %x",
|
||||
status);
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("Failed to read configuration space with status %x",
|
||||
status);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -123,45 +121,44 @@ EnumerateDriverObjectDeviceObjects(_In_ PDRIVER_OBJECT DriverObject,
|
|||
_Out_ PDEVICE_OBJECT** DeviceObjectArray,
|
||||
_Out_ PUINT32 ArrayEntries)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UINT32 object_count = 0;
|
||||
PDEVICE_OBJECT* buffer = NULL;
|
||||
UINT32 buffer_size = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UINT32 object_count = 0;
|
||||
PDEVICE_OBJECT* buffer = NULL;
|
||||
UINT32 buffer_size = 0;
|
||||
|
||||
*DeviceObjectArray = NULL;
|
||||
*DeviceObjectArray = NULL;
|
||||
|
||||
status =
|
||||
IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count);
|
||||
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) {
|
||||
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
buffer_size = object_count * sizeof(UINT64);
|
||||
buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, buffer_size, POOL_TAG_HW);
|
||||
|
||||
if (!buffer)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
status = IoEnumerateDeviceObjectList(
|
||||
DriverObject, buffer, buffer_size, &object_count);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x",
|
||||
status);
|
||||
ExFreePoolWithTag(buffer, POOL_TAG_HW);
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE("EnumerateDriverObjectDeviceObjects: Object Count: %lx",
|
||||
object_count);
|
||||
|
||||
*DeviceObjectArray = buffer;
|
||||
*ArrayEntries = object_count;
|
||||
status = IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count);
|
||||
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) {
|
||||
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
buffer_size = object_count * sizeof(UINT64);
|
||||
buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, buffer_size, POOL_TAG_HW);
|
||||
|
||||
if (!buffer)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
status = IoEnumerateDeviceObjectList(
|
||||
DriverObject, buffer, buffer_size, &object_count);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x",
|
||||
status);
|
||||
ExFreePoolWithTag(buffer, POOL_TAG_HW);
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE("EnumerateDriverObjectDeviceObjects: Object Count: %lx",
|
||||
object_count);
|
||||
|
||||
*DeviceObjectArray = buffer;
|
||||
*ArrayEntries = object_count;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -173,7 +170,7 @@ STATIC
|
|||
BOOLEAN
|
||||
IsDeviceObjectValidPdo(_In_ PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
return DeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE ? TRUE : FALSE;
|
||||
return DeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -197,114 +194,108 @@ NTSTATUS
|
|||
EnumeratePciDeviceObjects(_In_ PCI_DEVICE_CALLBACK CallbackRoutine,
|
||||
_In_opt_ PVOID Context)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UNICODE_STRING pci = RTL_CONSTANT_STRING(L"\\Driver\\pci");
|
||||
PDRIVER_OBJECT pci_driver_object = NULL;
|
||||
PDEVICE_OBJECT* pci_device_objects = NULL;
|
||||
PDEVICE_OBJECT current_device = NULL;
|
||||
UINT32 pci_device_objects_count = 0;
|
||||
USHORT vendor_id = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UNICODE_STRING pci = RTL_CONSTANT_STRING(L"\\Driver\\pci");
|
||||
PDRIVER_OBJECT pci_driver_object = NULL;
|
||||
PDEVICE_OBJECT* pci_device_objects = NULL;
|
||||
PDEVICE_OBJECT current_device = NULL;
|
||||
UINT32 pci_device_objects_count = 0;
|
||||
USHORT vendor_id = 0;
|
||||
|
||||
status = GetDriverObjectByDriverName(&pci, &pci_driver_object);
|
||||
status = GetDriverObjectByDriverName(&pci, &pci_driver_object);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("GetDriverObjectByDriverName failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = EnumerateDriverObjectDeviceObjects(
|
||||
pci_driver_object, &pci_device_objects, &pci_device_objects_count);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"EnumerateDriverObjectDeviceObjects failed with status %x",
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("GetDriverObjectByDriverName failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = EnumerateDriverObjectDeviceObjects(
|
||||
pci_driver_object, &pci_device_objects, &pci_device_objects_count);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("EnumerateDriverObjectDeviceObjects failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (UINT32 index = 0; index < pci_device_objects_count; index++) {
|
||||
current_device = pci_device_objects[index];
|
||||
|
||||
/* make sure we have a valid PDO */
|
||||
if (!IsDeviceObjectValidPdo(current_device)) {
|
||||
ObDereferenceObject(current_device);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (UINT32 index = 0; index < pci_device_objects_count; index++) {
|
||||
current_device = pci_device_objects[index];
|
||||
status = CallbackRoutine(current_device, Context);
|
||||
|
||||
/* make sure we have a valid PDO */
|
||||
if (!IsDeviceObjectValidPdo(current_device)) {
|
||||
ObDereferenceObject(current_device);
|
||||
continue;
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"EnumeratePciDeviceObjects CallbackRoutine failed with status %x",
|
||||
status);
|
||||
|
||||
status = CallbackRoutine(current_device, Context);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"EnumeratePciDeviceObjects CallbackRoutine failed with status %x",
|
||||
status);
|
||||
|
||||
ObDereferenceObject(current_device);
|
||||
}
|
||||
ObDereferenceObject(current_device);
|
||||
}
|
||||
|
||||
end:
|
||||
if (pci_device_objects)
|
||||
ExFreePoolWithTag(pci_device_objects, POOL_TAG_HW);
|
||||
if (pci_device_objects)
|
||||
ExFreePoolWithTag(pci_device_objects, POOL_TAG_HW);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsPciConfigurationSpaceFlagged(_In_ PPCI_COMMON_HEADER Configuration)
|
||||
{
|
||||
for (UINT32 index = 0; index < FLAGGED_DEVICE_ID_COUNT; index++) {
|
||||
if (Configuration->DeviceID == FLAGGED_DEVICE_IDS[index])
|
||||
return TRUE;
|
||||
}
|
||||
for (UINT32 index = 0; index < FLAGGED_DEVICE_ID_COUNT; index++) {
|
||||
if (Configuration->DeviceID == FLAGGED_DEVICE_IDS[index])
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PCI_COMMON_HEADER header = {0};
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PCI_COMMON_HEADER header = {0};
|
||||
|
||||
status = QueryPciDeviceConfigurationSpace(DeviceObject,
|
||||
PCI_VENDOR_ID_OFFSET,
|
||||
&header,
|
||||
sizeof(PCI_COMMON_HEADER));
|
||||
status = QueryPciDeviceConfigurationSpace(
|
||||
DeviceObject, PCI_VENDOR_ID_OFFSET, &header, sizeof(PCI_COMMON_HEADER));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"QueryPciDeviceConfigurationSpace failed with status %x",
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("QueryPciDeviceConfigurationSpace failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (IsPciConfigurationSpaceFlagged(&header)) {
|
||||
DEBUG_VERBOSE(
|
||||
"Flagged DeviceID found. Device: %llx, DeviceId: %lx",
|
||||
(UINT64)DeviceObject,
|
||||
header.DeviceID);
|
||||
}
|
||||
else {
|
||||
DEBUG_VERBOSE("Device: %llx, DeviceID: %lx, VendorID: %lx",
|
||||
DeviceObject,
|
||||
header.DeviceID,
|
||||
header.VendorID);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (IsPciConfigurationSpaceFlagged(&header)) {
|
||||
DEBUG_VERBOSE("Flagged DeviceID found. Device: %llx, DeviceId: %lx",
|
||||
(UINT64)DeviceObject,
|
||||
header.DeviceID);
|
||||
}
|
||||
else {
|
||||
DEBUG_VERBOSE("Device: %llx, DeviceID: %lx, VendorID: %lx",
|
||||
DeviceObject,
|
||||
header.DeviceID,
|
||||
header.VendorID);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ValidatePciDevices()
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
status = EnumeratePciDeviceObjects(PciDeviceQueryCallback, NULL);
|
||||
status = EnumeratePciDeviceObjects(PciDeviceQueryCallback, NULL);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("EnumeratePciDeviceObjects failed with status %x",
|
||||
status);
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("EnumeratePciDeviceObjects failed with status %x", status);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
1028
driver/imports.c
1028
driver/imports.c
File diff suppressed because it is too large
Load diff
2341
driver/integrity.c
2341
driver/integrity.c
File diff suppressed because it is too large
Load diff
|
@ -6,56 +6,55 @@
|
|||
#include "common.h"
|
||||
|
||||
typedef struct _MODULE_DISPATCHER_HEADER {
|
||||
volatile UINT32
|
||||
validated; // if this is > 0, a thread is already using it
|
||||
UINT8 result;
|
||||
volatile UINT32 validated; // if this is > 0, a thread is already using it
|
||||
UINT8 result;
|
||||
|
||||
} MODULE_DISPATCHER_HEADER, *PMODULE_DISPATCHER_HEADER;
|
||||
|
||||
typedef struct _SYSTEM_MODULE_INFORMATION {
|
||||
MODULE_DISPATCHER_HEADER dispatcher_header;
|
||||
RTL_MODULE_EXTENDED_INFO module_information;
|
||||
MODULE_DISPATCHER_HEADER dispatcher_header;
|
||||
RTL_MODULE_EXTENDED_INFO module_information;
|
||||
|
||||
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
|
||||
|
||||
#define VERIFICATION_THREAD_COUNT 4
|
||||
|
||||
typedef struct _SYS_MODULE_VAL_CONTEXT {
|
||||
/* Stores the number of actively executing worker threads */
|
||||
volatile LONG active_thread_count;
|
||||
/* Stores the number of actively executing worker threads */
|
||||
volatile LONG active_thread_count;
|
||||
|
||||
/* determines whether a validation is in progress */
|
||||
volatile LONG active;
|
||||
/* determines whether a validation is in progress */
|
||||
volatile LONG active;
|
||||
|
||||
/* determines whether a validation is complete */
|
||||
volatile LONG complete;
|
||||
/* determines whether a validation is complete */
|
||||
volatile LONG complete;
|
||||
|
||||
/* current count of validated modules */
|
||||
volatile LONG current_count;
|
||||
/* current count of validated modules */
|
||||
volatile LONG current_count;
|
||||
|
||||
/* total count of modules */
|
||||
UINT32 total_count;
|
||||
/* total count of modules */
|
||||
UINT32 total_count;
|
||||
|
||||
/* number of modules to validate in a single sweep */
|
||||
UINT32 block_size;
|
||||
/* number of modules to validate in a single sweep */
|
||||
UINT32 block_size;
|
||||
|
||||
/* pointer to the buffer containing the system module information */
|
||||
PRTL_MODULE_EXTENDED_INFO module_info;
|
||||
/* pointer to the buffer containing the system module information */
|
||||
PRTL_MODULE_EXTENDED_INFO module_info;
|
||||
|
||||
/* pointer to the array of dispatcher info used to synchonize threads */
|
||||
PMODULE_DISPATCHER_HEADER dispatcher_info;
|
||||
/* pointer to the array of dispatcher info used to synchonize threads */
|
||||
PMODULE_DISPATCHER_HEADER dispatcher_info;
|
||||
|
||||
/* array of pointers to work items, used to free work items when
|
||||
* complete */
|
||||
PIO_WORKITEM work_items[VERIFICATION_THREAD_COUNT];
|
||||
/* array of pointers to work items, used to free work items when
|
||||
* complete */
|
||||
PIO_WORKITEM work_items[VERIFICATION_THREAD_COUNT];
|
||||
|
||||
} SYS_MODULE_VAL_CONTEXT, *PSYS_MODULE_VAL_CONTEXT;
|
||||
|
||||
typedef enum _SMBIOS_TABLE_INDEX {
|
||||
SmbiosInformation = 0,
|
||||
SystemInformation,
|
||||
VendorSpecificInformation,
|
||||
ChassisInformation
|
||||
SmbiosInformation = 0,
|
||||
SystemInformation,
|
||||
VendorSpecificInformation,
|
||||
ChassisInformation
|
||||
|
||||
} SMBIOS_TABLE_INDEX;
|
||||
|
||||
|
|
1581
driver/io.c
1581
driver/io.c
File diff suppressed because it is too large
Load diff
44
driver/io.h
44
driver/io.h
|
@ -7,40 +7,40 @@
|
|||
#include "common.h"
|
||||
|
||||
typedef struct _SHARED_MAPPING_INIT {
|
||||
PVOID buffer;
|
||||
SIZE_T size;
|
||||
PVOID buffer;
|
||||
SIZE_T size;
|
||||
|
||||
} SHARED_MAPPING_INIT, *PSHARED_MAPPING_INIT;
|
||||
|
||||
typedef enum _SHARED_STATE_OPERATION_ID {
|
||||
ssRunNmiCallbacks = 0,
|
||||
ssValidateDriverObjects,
|
||||
ssEnumerateHandleTables,
|
||||
ssScanForUnlinkedProcesses,
|
||||
ssPerformModuleIntegrityCheck,
|
||||
ssScanForAttachedThreads,
|
||||
ssScanForEptHooks,
|
||||
ssInitiateDpcStackwalk,
|
||||
ssValidateSystemModules,
|
||||
ssRunNmiCallbacks = 0,
|
||||
ssValidateDriverObjects,
|
||||
ssEnumerateHandleTables,
|
||||
ssScanForUnlinkedProcesses,
|
||||
ssPerformModuleIntegrityCheck,
|
||||
ssScanForAttachedThreads,
|
||||
ssScanForEptHooks,
|
||||
ssInitiateDpcStackwalk,
|
||||
ssValidateSystemModules,
|
||||
|
||||
} SHARED_STATE_OPERATION_ID;
|
||||
|
||||
typedef struct _SHARED_STATE {
|
||||
volatile UINT32 status;
|
||||
volatile UINT16 operation_id;
|
||||
volatile UINT32 status;
|
||||
volatile UINT16 operation_id;
|
||||
|
||||
} SHARED_STATE, *PSHARED_STATE;
|
||||
|
||||
typedef struct _SHARED_MAPPING {
|
||||
volatile LONG work_item_status;
|
||||
PVOID user_buffer;
|
||||
PSHARED_STATE kernel_buffer;
|
||||
PMDL mdl;
|
||||
SIZE_T size;
|
||||
volatile BOOLEAN active;
|
||||
KTIMER timer;
|
||||
KDPC timer_dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
volatile LONG work_item_status;
|
||||
PVOID user_buffer;
|
||||
PSHARED_STATE kernel_buffer;
|
||||
PMDL mdl;
|
||||
SIZE_T size;
|
||||
volatile BOOLEAN active;
|
||||
KTIMER timer;
|
||||
KDPC timer_dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
|
||||
} SHARED_MAPPING, *PSHARED_MAPPING;
|
||||
|
||||
|
|
138
driver/list.c
138
driver/list.c
|
@ -29,8 +29,8 @@
|
|||
VOID
|
||||
ListInit(_Inout_ PSINGLE_LIST_ENTRY Head, _Inout_ PKGUARDED_MUTEX Lock)
|
||||
{
|
||||
ImpKeInitializeGuardedMutex(Lock);
|
||||
Head->Next = NULL;
|
||||
ImpKeInitializeGuardedMutex(Lock);
|
||||
Head->Next = NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -38,14 +38,14 @@ ListInsert(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_Inout_ PSINGLE_LIST_ENTRY NewEntry,
|
||||
_In_ PKGUARDED_MUTEX Lock)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
|
||||
PSINGLE_LIST_ENTRY old_entry = Head->Next;
|
||||
PSINGLE_LIST_ENTRY old_entry = Head->Next;
|
||||
|
||||
Head->Next = NewEntry;
|
||||
NewEntry->Next = old_entry;
|
||||
Head->Next = NewEntry;
|
||||
NewEntry->Next = old_entry;
|
||||
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -59,22 +59,22 @@ ListFreeFirstEntry(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_In_ PKGUARDED_MUTEX Lock,
|
||||
_In_opt_ FREE_LIST_ITEM_CALLBACK CallbackRoutine)
|
||||
{
|
||||
BOOLEAN result = FALSE;
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
BOOLEAN result = FALSE;
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
|
||||
if (Head->Next) {
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
if (Head->Next) {
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
|
||||
if (CallbackRoutine)
|
||||
CallbackRoutine(entry);
|
||||
if (CallbackRoutine)
|
||||
CallbackRoutine(entry);
|
||||
|
||||
Head->Next = Head->Next->Next;
|
||||
ImpExFreePoolWithTag(entry, POOL_TAG_THREAD_LIST);
|
||||
result = TRUE;
|
||||
}
|
||||
Head->Next = Head->Next->Next;
|
||||
ImpExFreePoolWithTag(entry, POOL_TAG_THREAD_LIST);
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
return result;
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -86,31 +86,31 @@ ListRemoveEntry(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
||||
_In_ PKGUARDED_MUTEX Lock)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
|
||||
if (!entry)
|
||||
goto unlock;
|
||||
if (!entry)
|
||||
goto unlock;
|
||||
|
||||
if (entry == Entry) {
|
||||
Head->Next = entry->Next;
|
||||
ImpExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
if (entry == Entry) {
|
||||
Head->Next = entry->Next;
|
||||
ImpExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
while (entry->Next) {
|
||||
if (entry->Next == Entry) {
|
||||
entry->Next = Entry->Next;
|
||||
ImpExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
while (entry->Next) {
|
||||
if (entry->Next == Entry) {
|
||||
entry->Next = Entry->Next;
|
||||
ImpExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
entry = entry->Next;
|
||||
}
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -118,32 +118,32 @@ LookasideListRemoveEntry(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
||||
_In_ PKGUARDED_MUTEX Lock)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
|
||||
PTHREAD_LIST_HEAD head = GetThreadList();
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
PTHREAD_LIST_HEAD head = GetThreadList();
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
|
||||
if (!entry)
|
||||
goto unlock;
|
||||
if (!entry)
|
||||
goto unlock;
|
||||
|
||||
if (entry == Entry) {
|
||||
Head->Next = entry->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, Entry);
|
||||
goto unlock;
|
||||
if (entry == Entry) {
|
||||
Head->Next = entry->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, Entry);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
while (entry->Next) {
|
||||
if (entry->Next == Entry) {
|
||||
entry->Next = Entry->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, Entry);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
while (entry->Next) {
|
||||
if (entry->Next == Entry) {
|
||||
entry->Next = Entry->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, Entry);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
entry = entry->Next;
|
||||
}
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
|
@ -151,22 +151,22 @@ LookasideListFreeFirstEntry(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_In_ PKGUARDED_MUTEX Lock,
|
||||
_In_opt_ FREE_LIST_ITEM_CALLBACK CallbackRoutine)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
ImpKeAcquireGuardedMutex(Lock);
|
||||
|
||||
PTHREAD_LIST_HEAD head = GetThreadList();
|
||||
BOOLEAN result = FALSE;
|
||||
PTHREAD_LIST_HEAD head = GetThreadList();
|
||||
BOOLEAN result = FALSE;
|
||||
|
||||
if (Head->Next) {
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
if (Head->Next) {
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
|
||||
if (CallbackRoutine)
|
||||
CallbackRoutine(entry);
|
||||
if (CallbackRoutine)
|
||||
CallbackRoutine(entry);
|
||||
|
||||
Head->Next = Head->Next->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, entry);
|
||||
result = TRUE;
|
||||
}
|
||||
Head->Next = Head->Next->Next;
|
||||
ExFreeToLookasideListEx(&head->lookaside_list, entry);
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
return result;
|
||||
ImpKeReleaseGuardedMutex(Lock);
|
||||
return result;
|
||||
}
|
2347
driver/modules.c
2347
driver/modules.c
File diff suppressed because it is too large
Load diff
|
@ -8,30 +8,30 @@
|
|||
#include "queue.h"
|
||||
|
||||
typedef struct _APC_OPERATION_ID {
|
||||
int operation_id;
|
||||
int operation_id;
|
||||
|
||||
} APC_OPERATION_ID, *PAPC_OPERATION_ID;
|
||||
|
||||
/* system modules information */
|
||||
|
||||
typedef struct _SYSTEM_MODULES {
|
||||
PVOID address;
|
||||
INT module_count;
|
||||
PVOID address;
|
||||
INT module_count;
|
||||
|
||||
} SYSTEM_MODULES, *PSYSTEM_MODULES;
|
||||
|
||||
#define APC_CONTEXT_ID_STACKWALK 0x1
|
||||
|
||||
typedef struct _APC_CONTEXT_HEADER {
|
||||
LONG context_id;
|
||||
volatile INT count;
|
||||
volatile INT allocation_in_progress;
|
||||
LONG context_id;
|
||||
volatile INT count;
|
||||
volatile INT allocation_in_progress;
|
||||
|
||||
} APC_CONTEXT_HEADER, *PAPC_CONTEXT_HEADER;
|
||||
|
||||
typedef struct _APC_STACKWALK_CONTEXT {
|
||||
APC_CONTEXT_HEADER header;
|
||||
PSYSTEM_MODULES modules;
|
||||
APC_CONTEXT_HEADER header;
|
||||
PSYSTEM_MODULES modules;
|
||||
|
||||
} APC_STACKWALK_CONTEXT, *PAPC_STACKWALK_CONTEXT;
|
||||
|
||||
|
|
900
driver/pool.c
900
driver/pool.c
File diff suppressed because it is too large
Load diff
|
@ -14,52 +14,52 @@
|
|||
VOID
|
||||
QueuePush(_Inout_ PQUEUE_HEAD Head, _In_ PVOID Data)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&Head->lock);
|
||||
ImpKeAcquireGuardedMutex(&Head->lock);
|
||||
|
||||
PQUEUE_NODE temp = ExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(QUEUE_NODE), QUEUE_POOL_TAG);
|
||||
PQUEUE_NODE temp = ExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(QUEUE_NODE), QUEUE_POOL_TAG);
|
||||
|
||||
if (!temp)
|
||||
goto end;
|
||||
if (!temp)
|
||||
goto end;
|
||||
|
||||
Head->entries += 1;
|
||||
Head->entries += 1;
|
||||
|
||||
temp->data = Data;
|
||||
temp->data = Data;
|
||||
|
||||
if (Head->end != NULL)
|
||||
Head->end->next = temp;
|
||||
if (Head->end != NULL)
|
||||
Head->end->next = temp;
|
||||
|
||||
Head->end = temp;
|
||||
Head->end = temp;
|
||||
|
||||
if (Head->start == NULL)
|
||||
Head->start = temp;
|
||||
if (Head->start == NULL)
|
||||
Head->start = temp;
|
||||
|
||||
end:
|
||||
ImpKeReleaseGuardedMutex(&Head->lock);
|
||||
ImpKeReleaseGuardedMutex(&Head->lock);
|
||||
}
|
||||
|
||||
PVOID
|
||||
QueuePop(_Inout_ PQUEUE_HEAD Head)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&Head->lock);
|
||||
ImpKeAcquireGuardedMutex(&Head->lock);
|
||||
|
||||
PVOID data = NULL;
|
||||
PQUEUE_NODE temp = Head->start;
|
||||
PVOID data = NULL;
|
||||
PQUEUE_NODE temp = Head->start;
|
||||
|
||||
if (temp == NULL)
|
||||
goto end;
|
||||
if (temp == NULL)
|
||||
goto end;
|
||||
|
||||
Head->entries = Head->entries - 1;
|
||||
Head->entries = Head->entries - 1;
|
||||
|
||||
data = temp->data;
|
||||
Head->start = temp->next;
|
||||
data = temp->data;
|
||||
Head->start = temp->next;
|
||||
|
||||
if (Head->end == temp)
|
||||
Head->end = NULL;
|
||||
if (Head->end == temp)
|
||||
Head->end = NULL;
|
||||
|
||||
ImpExFreePoolWithTag(temp, QUEUE_POOL_TAG);
|
||||
ImpExFreePoolWithTag(temp, QUEUE_POOL_TAG);
|
||||
|
||||
end:
|
||||
ImpKeReleaseGuardedMutex(&Head->lock);
|
||||
return data;
|
||||
ImpKeReleaseGuardedMutex(&Head->lock);
|
||||
return data;
|
||||
}
|
|
@ -7,10 +7,10 @@
|
|||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
typedef struct QUEUE_HEAD {
|
||||
struct _QUEUE_NODE* start;
|
||||
struct _QUEUE_NODE* end;
|
||||
KGUARDED_MUTEX lock;
|
||||
INT entries;
|
||||
struct _QUEUE_NODE* start;
|
||||
struct _QUEUE_NODE* end;
|
||||
KGUARDED_MUTEX lock;
|
||||
INT entries;
|
||||
|
||||
} QUEUE_HEAD, *PQUEUE_HEAD;
|
||||
|
||||
|
@ -23,25 +23,25 @@ typedef struct QUEUE_HEAD {
|
|||
* of the spinlock.
|
||||
*/
|
||||
typedef struct _REPORT_QUEUE_HEAD {
|
||||
QUEUE_HEAD head;
|
||||
volatile BOOLEAN is_driver_unloading;
|
||||
KGUARDED_MUTEX lock;
|
||||
QUEUE_HEAD head;
|
||||
volatile BOOLEAN is_driver_unloading;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} REPORT_QUEUE_HEAD, *PREPORT_QUEUE_HEAD;
|
||||
|
||||
typedef struct _QUEUE_NODE {
|
||||
struct _QUEUE_NODE* next;
|
||||
PVOID data;
|
||||
struct _QUEUE_NODE* next;
|
||||
PVOID data;
|
||||
|
||||
} QUEUE_NODE, *PQUEUE_NODE;
|
||||
|
||||
typedef struct _GLOBAL_REPORT_QUEUE_HEADER {
|
||||
INT count;
|
||||
INT count;
|
||||
|
||||
} GLOBAL_REPORT_QUEUE_HEADER, *PGLOBAL_REPORT_QUEUE_HEADER;
|
||||
|
||||
typedef struct _REPORT_HEADER {
|
||||
INT report_id;
|
||||
INT report_id;
|
||||
|
||||
} REPORT_HEADER, *PREPORT_HEADER;
|
||||
|
||||
|
|
185
driver/session.c
185
driver/session.c
|
@ -5,180 +5,177 @@
|
|||
/* for now, lets just xor the aes key with our cookie */
|
||||
|
||||
typedef struct _SESSION_INITIATION_PACKET {
|
||||
UINT32 session_cookie;
|
||||
CHAR session_aes_key[AES_128_KEY_SIZE];
|
||||
PVOID protected_process_id;
|
||||
UINT32 session_cookie;
|
||||
CHAR session_aes_key[AES_128_KEY_SIZE];
|
||||
PVOID protected_process_id;
|
||||
|
||||
} SESSION_INITIATION_PACKET, *PSESSION_INITIATION_PACKET;
|
||||
|
||||
VOID
|
||||
SessionInitialiseStructure()
|
||||
{
|
||||
PAGED_CODE();
|
||||
ImpKeInitializeGuardedMutex(&GetActiveSession()->lock);
|
||||
PAGED_CODE();
|
||||
ImpKeInitializeGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionInitialiseCallbackConfiguration()
|
||||
{
|
||||
PAGED_CODE();
|
||||
InitialiseObCallbacksConfiguration(GetActiveSession());
|
||||
PAGED_CODE();
|
||||
InitialiseObCallbacksConfiguration(GetActiveSession());
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionIsActive(_Out_ PBOOLEAN Flag)
|
||||
{
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*Flag = GetActiveSession()->is_session_active;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*Flag = GetActiveSession()->is_session_active;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionGetProcess(_Out_ PEPROCESS* Process)
|
||||
{
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*Process = GetActiveSession()->process;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*Process = GetActiveSession()->process;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionGetProcessId(_Out_ PLONG ProcessId)
|
||||
{
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*ProcessId = GetActiveSession()->km_handle;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
PAGED_CODE();
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*ProcessId = GetActiveSession()->km_handle;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionGetCallbackConfiguration(
|
||||
_Out_ POB_CALLBACKS_CONFIG* CallbackConfiguration)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*CallbackConfiguration = &GetActiveSession()->callback_configuration;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
*CallbackConfiguration = &GetActiveSession()->callback_configuration;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionTerminate()
|
||||
{
|
||||
PAGED_CODE();
|
||||
DEBUG_INFO("Termination active session.");
|
||||
PAGED_CODE();
|
||||
DEBUG_INFO("Termination active session.");
|
||||
|
||||
PACTIVE_SESSION session = GetActiveSession();
|
||||
PACTIVE_SESSION session = GetActiveSession();
|
||||
|
||||
ImpKeAcquireGuardedMutex(&session->lock);
|
||||
session->km_handle = NULL;
|
||||
session->um_handle = NULL;
|
||||
session->process = NULL;
|
||||
session->is_session_active = FALSE;
|
||||
ImpKeReleaseGuardedMutex(&session->lock);
|
||||
ImpKeAcquireGuardedMutex(&session->lock);
|
||||
session->km_handle = NULL;
|
||||
session->um_handle = NULL;
|
||||
session->process = NULL;
|
||||
session->is_session_active = FALSE;
|
||||
ImpKeReleaseGuardedMutex(&session->lock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
SessionInitialise(_In_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PEPROCESS process = NULL;
|
||||
PSESSION_INITIATION_PACKET information = NULL;
|
||||
PACTIVE_SESSION session = GetActiveSession();
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PEPROCESS process = NULL;
|
||||
PSESSION_INITIATION_PACKET information = NULL;
|
||||
PACTIVE_SESSION session = GetActiveSession();
|
||||
|
||||
DEBUG_VERBOSE("Initialising new session.");
|
||||
DEBUG_VERBOSE("Initialising new session.");
|
||||
|
||||
status = ValidateIrpInputBuffer(Irp, sizeof(SESSION_INITIATION_PACKET));
|
||||
status = ValidateIrpInputBuffer(Irp, sizeof(SESSION_INITIATION_PACKET));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateIrpInputBuffer failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateIrpInputBuffer failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
information =
|
||||
(PSESSION_INITIATION_PACKET)Irp->AssociatedIrp.SystemBuffer;
|
||||
information = (PSESSION_INITIATION_PACKET)Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
ImpKeAcquireGuardedMutex(&session->lock);
|
||||
ImpKeAcquireGuardedMutex(&session->lock);
|
||||
|
||||
session->um_handle = information->protected_process_id;
|
||||
session->um_handle = information->protected_process_id;
|
||||
|
||||
/* What if we pass an invalid handle here? not good. */
|
||||
status = ImpPsLookupProcessByProcessId(session->um_handle, &process);
|
||||
/* What if we pass an invalid handle here? not good. */
|
||||
status = ImpPsLookupProcessByProcessId(session->um_handle, &process);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
}
|
||||
if (!NT_SUCCESS(status)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
session->km_handle = ImpPsGetProcessId(process);
|
||||
session->process = process;
|
||||
session->is_session_active = TRUE;
|
||||
session->session_cookie = information->session_cookie;
|
||||
session->km_handle = ImpPsGetProcessId(process);
|
||||
session->process = process;
|
||||
session->is_session_active = TRUE;
|
||||
session->session_cookie = information->session_cookie;
|
||||
|
||||
RtlCopyMemory(session->session_aes_key,
|
||||
information->session_aes_key,
|
||||
AES_128_KEY_SIZE);
|
||||
RtlCopyMemory(session->session_aes_key,
|
||||
information->session_aes_key,
|
||||
AES_128_KEY_SIZE);
|
||||
|
||||
end:
|
||||
ImpKeReleaseGuardedMutex(&session->lock);
|
||||
return status;
|
||||
ImpKeReleaseGuardedMutex(&session->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionTerminateProcess()
|
||||
{
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
ULONG process_id = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
ULONG process_id = 0;
|
||||
|
||||
SessionGetProcessId(&process_id);
|
||||
SessionGetProcessId(&process_id);
|
||||
|
||||
if (!process_id) {
|
||||
DEBUG_ERROR(
|
||||
"Failed to terminate process as process id is null");
|
||||
return;
|
||||
}
|
||||
if (!process_id) {
|
||||
DEBUG_ERROR("Failed to terminate process as process id is null");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we pass a km handle to ZwTerminateProcess and NOT a
|
||||
* usermode handle. */
|
||||
status = ZwTerminateProcess(process_id,
|
||||
STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION);
|
||||
/* Make sure we pass a km handle to ZwTerminateProcess and NOT a
|
||||
* usermode handle. */
|
||||
status = ZwTerminateProcess(process_id,
|
||||
STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
/*
|
||||
* We don't want to clear the process config if
|
||||
* ZwTerminateProcess fails so we can try again.
|
||||
*/
|
||||
DEBUG_ERROR("ZwTerminateProcess failed with status %x", status);
|
||||
return;
|
||||
}
|
||||
/* this wont be needed when procloadstuff is implemented */
|
||||
SessionTerminate();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
/*
|
||||
* We don't want to clear the process config if
|
||||
* ZwTerminateProcess fails so we can try again.
|
||||
*/
|
||||
DEBUG_ERROR("ZwTerminateProcess failed with status %x", status);
|
||||
return;
|
||||
}
|
||||
/* this wont be needed when procloadstuff is implemented */
|
||||
SessionTerminate();
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionIncrementIrpsProcessedCount()
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->irps_processed++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->irps_processed++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionIncrementReportCount()
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->report_count++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->report_count++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
SessionIncrementHeartbeatCount()
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->heartbeat_count++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
|
||||
GetActiveSession()->heartbeat_count++;
|
||||
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
|
||||
}
|
149
driver/thread.c
149
driver/thread.c
|
@ -10,55 +10,55 @@
|
|||
#include "imports.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
# pragma alloc_text(PAGE, DetectThreadsAttachedToProtectedProcess)
|
||||
# pragma alloc_text(PAGE, ValidateThreadsPspCidTableEntry)
|
||||
# pragma alloc_text(PAGE, DetectThreadsAttachedToProtectedProcess)
|
||||
# pragma alloc_text(PAGE, ValidateThreadsPspCidTableEntry)
|
||||
#endif
|
||||
|
||||
BOOLEAN
|
||||
ValidateThreadsPspCidTableEntry(_In_ PETHREAD Thread)
|
||||
{
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
HANDLE thread_id = NULL;
|
||||
PETHREAD thread = NULL;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
HANDLE thread_id = NULL;
|
||||
PETHREAD thread = NULL;
|
||||
|
||||
/*
|
||||
* PsGetThreadId simply returns ETHREAD->Cid.UniqueThread
|
||||
*/
|
||||
thread_id = ImpPsGetThreadId(Thread);
|
||||
|
||||
/*
|
||||
* For each core on the processor, the first x threads equal to x cores
|
||||
* will be assigned a cid equal to its equivalent core. These threads
|
||||
* are generally executing the HLT instruction or some other boring
|
||||
* stuff while the processor is not busy. The reason this is important
|
||||
* is because passing in a handle value of 0 which, even though is a
|
||||
* valid cid, returns a non success status meaning we mark it an invalid
|
||||
* cid entry even though it is. To combat this we simply add a little
|
||||
* check here. The problem is this can be easily bypassed by simply
|
||||
* modifying the ETHREAD->Cid.UniqueThread identifier.. So while it isnt
|
||||
* a perfect detection method for now it's good enough.
|
||||
*/
|
||||
if ((UINT64)thread_id < (UINT64)ImpKeQueryActiveProcessorCount(NULL))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* PsLookupThreadByThreadId will use a threads id to find its cid entry,
|
||||
* and return the pointer contained in the HANDLE_TABLE entry pointing
|
||||
* to the thread object. Meaning if we pass a valid thread id which we
|
||||
* retrieved above and dont receive a STATUS_SUCCESS the cid entry could
|
||||
* potentially be removed or disrupted..
|
||||
*/
|
||||
status = ImpPsLookupThreadByThreadId(thread_id, &thread);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_WARNING(
|
||||
"Failed to lookup thread by id. PspCidTable entry potentially removed.");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* PsGetThreadId simply returns ETHREAD->Cid.UniqueThread
|
||||
*/
|
||||
thread_id = ImpPsGetThreadId(Thread);
|
||||
|
||||
/*
|
||||
* For each core on the processor, the first x threads equal to x cores
|
||||
* will be assigned a cid equal to its equivalent core. These threads
|
||||
* are generally executing the HLT instruction or some other boring
|
||||
* stuff while the processor is not busy. The reason this is important
|
||||
* is because passing in a handle value of 0 which, even though is a
|
||||
* valid cid, returns a non success status meaning we mark it an invalid
|
||||
* cid entry even though it is. To combat this we simply add a little
|
||||
* check here. The problem is this can be easily bypassed by simply
|
||||
* modifying the ETHREAD->Cid.UniqueThread identifier.. So while it isnt
|
||||
* a perfect detection method for now it's good enough.
|
||||
*/
|
||||
if ((UINT64)thread_id < (UINT64)ImpKeQueryActiveProcessorCount(NULL))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* PsLookupThreadByThreadId will use a threads id to find its cid entry,
|
||||
* and return the pointer contained in the HANDLE_TABLE entry pointing
|
||||
* to the thread object. Meaning if we pass a valid thread id which we
|
||||
* retrieved above and dont receive a STATUS_SUCCESS the cid entry could
|
||||
* potentially be removed or disrupted..
|
||||
*/
|
||||
status = ImpPsLookupThreadByThreadId(thread_id, &thread);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_WARNING(
|
||||
"Failed to lookup thread by id. PspCidTable entry potentially removed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -79,55 +79,52 @@ STATIC VOID
|
|||
DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
|
||||
_Inout_opt_ PVOID Context)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
PKAPC_STATE apc_state = NULL;
|
||||
PEPROCESS protected_process = NULL;
|
||||
PKAPC_STATE apc_state = NULL;
|
||||
PEPROCESS protected_process = NULL;
|
||||
|
||||
SessionGetProcess(&protected_process);
|
||||
SessionGetProcess(&protected_process);
|
||||
|
||||
if (!protected_process)
|
||||
return;
|
||||
if (!protected_process)
|
||||
return;
|
||||
|
||||
apc_state = (PKAPC_STATE)((UINT64)ThreadListEntry->thread +
|
||||
KTHREAD_APC_STATE_OFFSET);
|
||||
apc_state = (PKAPC_STATE)((UINT64)ThreadListEntry->thread +
|
||||
KTHREAD_APC_STATE_OFFSET);
|
||||
|
||||
/*
|
||||
* We don't care if a thread owned by our protected process is attached
|
||||
*
|
||||
* todo: this is filterless and will just report anything, need to have
|
||||
* a look into what processes actually attach to real games
|
||||
*/
|
||||
if (!(apc_state->Process == protected_process &&
|
||||
ThreadListEntry->owning_process != protected_process)) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* We don't care if a thread owned by our protected process is attached
|
||||
*
|
||||
* todo: this is filterless and will just report anything, need to have
|
||||
* a look into what processes actually attach to real games
|
||||
*/
|
||||
if (!(apc_state->Process == protected_process &&
|
||||
ThreadListEntry->owning_process != protected_process)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_WARNING("Thread is attached to our protected process: %llx",
|
||||
(UINT64)ThreadListEntry->thread);
|
||||
DEBUG_WARNING("Thread is attached to our protected process: %llx",
|
||||
(UINT64)ThreadListEntry->thread);
|
||||
|
||||
PATTACH_PROCESS_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(ATTACH_PROCESS_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
PATTACH_PROCESS_REPORT report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(ATTACH_PROCESS_REPORT), REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_ILLEGAL_ATTACH_PROCESS;
|
||||
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
||||
report->thread_address = ThreadListEntry->thread;
|
||||
report->report_code = REPORT_ILLEGAL_ATTACH_PROCESS;
|
||||
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
||||
report->thread_address = ThreadListEntry->thread;
|
||||
|
||||
if (!NT_SUCCESS(
|
||||
IrpQueueCompleteIrp(report, sizeof(ATTACH_PROCESS_REPORT))))
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(report, sizeof(ATTACH_PROCESS_REPORT))))
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||
}
|
||||
|
||||
VOID
|
||||
DetectThreadsAttachedToProtectedProcess()
|
||||
{
|
||||
PAGED_CODE();
|
||||
DEBUG_VERBOSE("Detecting threads attached to our process...");
|
||||
EnumerateThreadListWithCallbackRoutine(
|
||||
DetectAttachedThreadsProcessCallback, NULL);
|
||||
PAGED_CODE();
|
||||
DEBUG_VERBOSE("Detecting threads attached to our process...");
|
||||
EnumerateThreadListWithCallbackRoutine(DetectAttachedThreadsProcessCallback,
|
||||
NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue