diff --git a/drv_entry.cpp b/drv_entry.cpp index 5e18836..41f637c 100644 --- a/drv_entry.cpp +++ b/drv_entry.cpp @@ -3,17 +3,25 @@ // // -#include -#include -#include +#include "scn.hpp" +#include "shithook.hpp" +#include "sha1.hpp" +#include "md5.hpp" // // game cheat offset flash backs... // #define EAC_VM_HANDLE_OFFSET 0xE93D +#define EAC_SHA1_OFFSET 0x4C00 +#define EAC_MD5_OFFSET 0x37378 +#define EAC_CRC32_OFFSET 0x27C8C #define EAC_IMAGE_BASE 0x140000000 +#define DBG_PRINT(format, ...) \ + DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, \ + "[vmhook-eac [core number = %d]]" format, KeGetCurrentProcessorNumber(), __VA_ARGS__) + // // vm handler indexes for READQ... // @@ -26,13 +34,21 @@ u8 readq_idxs[] = { 247, 215, 169, 159, 71, 60, 55, 43, 23 }; u8 readdw_idxs[] = { 218, 180, 179, 178, 163, 137, 92, 22, 12 }; +// +// vm handler indexes for READB +// + +u8 readb_idxs[] = { 249, 231, 184, 160, 88, 85, 48, 9, 2 }; + vm::hook_t* g_vmhook = nullptr; vm::handler::table_t* g_vm_table = nullptr; +u64 __image_base = 0u, __image_size = 0u, __image_clone = 0u; +inline_hook_t __crc32_hook, __sha1_hook, __md5_hook; void* operator new( u64 size -) + ) { // // Could have also used ExAllocatePoolZero... @@ -44,14 +60,34 @@ operator new( void operator delete ( - void* ptr, + void* ptr, u64 size -) + ) { UNREFERENCED_PARAMETER(size); ExFreePool(ptr); } +__declspec(noinline) +void hook_sha1( + void *data, unsigned int len, void* result +) +{ + sha1_ctx ctx; + sha1_init(&ctx); + + if (scn::read_only(__image_base, (u64)data)) + { + DBG_PRINT("sha1 hash data = 0x%p, len = 0x%x, result = 0x%p\n", data, len, result); + sha1_update(&ctx, (unsigned char*)__image_clone + (((u64)data) - __image_base), len); + sha1_final((unsigned char*)result, &ctx); + return; + } + + sha1_update(&ctx, (unsigned char*) data, len); + sha1_final((unsigned char*)result, &ctx); +} + void image_loaded( PUNICODE_STRING image_name, @@ -65,8 +101,8 @@ image_loaded( if (!pid && wcsstr(image_name->Buffer, L"EasyAntiCheat.sys")) { - if (g_vmhook && g_vm_table) - delete g_vmhook, delete g_vm_table; + if (g_vmhook && g_vm_table && __image_clone) + delete g_vmhook, delete g_vm_table, ExFreePool((void*)__image_clone); // // allocate memory for a g_vmhook, g_vm_table and then zero it... @@ -123,34 +159,46 @@ image_loaded( auto image_base = reinterpret_cast(image_info->ImageBase); auto handler_table_ptr = reinterpret_cast(image_base + EAC_VM_HANDLE_OFFSET); + __image_clone = reinterpret_cast(ExAllocatePool(NonPagedPool, image_info->ImageSize)); + RtlCopyMemory((void*)__image_clone, (void*)image_base, image_info->ImageSize); + g_vm_table = new vm::handler::table_t(handler_table_ptr, _edit_entry); g_vmhook = new vm::hook_t(image_base, EAC_IMAGE_BASE, _decrypt_handler, _encrypt_handler, g_vm_table); + __image_base = image_base, __image_size = image_info->ImageSize; + + const auto callback = [](vm::registers* regs, u8 handler_idx) + { + const auto read_addr = reinterpret_cast(regs->rbp)[0]; + + // shoot the tires right off the virtualized integrity checks in about 2 lines of code... + if (scn::read_only(__image_base, read_addr)) + { + DBG_PRINT(" READ(Q/DW/B) EasyAntiCheat.sys+0x%x\n", (read_addr - __image_base)); + reinterpret_cast(regs->rbp)[0] = __image_clone + (read_addr - __image_base); + } + }; // install hooks on READQ virtual machine handlers... for (auto idx = 0u; idx < sizeof readq_idxs; ++idx) - { - g_vm_table->set_callback(readq_idxs[idx], - [](vm::registers* regs, u8 handler_idx) - { - DbgPrint("> READQ, reading address = 0x%p\n", reinterpret_cast(regs->rbp)[0]); - } - ); - } + g_vm_table->set_callback(readq_idxs[idx], callback); + // install hooks on READDW virtual machine handlers... for (auto idx = 0u; idx < sizeof readdw_idxs; ++idx) - { - g_vm_table->set_callback(readdw_idxs[idx], - [](vm::registers* regs, u8 handler_idx) - { - DbgPrint("> READDW, reading address = 0x%p\n", reinterpret_cast(regs->rbp)[0]); - } - ); - } + g_vm_table->set_callback(readdw_idxs[idx], callback); + + // install hooks on READB virtual machine handlers... + for (auto idx = 0u; idx < sizeof readb_idxs; ++idx) + g_vm_table->set_callback(readb_idxs[idx], callback); // // hooks all vm handlers and starts callbacks... // g_vmhook->start(); + + // hook on sha1... + make_inline_hook(&__sha1_hook, + reinterpret_cast( + image_base + EAC_SHA1_OFFSET), &hook_sha1, true); } } @@ -184,6 +232,6 @@ DriverEntry( // entry called from ZwSwapCert... // This is because ZwSwapCert will cause the system to crash... // - DbgPrint("> Registering ImageLoad Callbacks...\n"); + DBG_PRINT("> Registering ImageLoad Callbacks...\n"); return PsSetLoadImageNotifyRoutine(&image_loaded); } \ No newline at end of file diff --git a/scn.cpp b/scn.cpp new file mode 100644 index 0000000..670601e --- /dev/null +++ b/scn.cpp @@ -0,0 +1,29 @@ +#include "scn.hpp" + +namespace scn +{ + bool read_only(u64 image_base, u64 ptr) + { + auto dos_header = reinterpret_cast(image_base); + auto nt_header = reinterpret_cast( + reinterpret_cast(dos_header) + dos_header->e_lfanew); + + auto section_count = nt_header->FileHeader.NumberOfSections; + auto sections = reinterpret_cast( + reinterpret_cast(nt_header) + sizeof(u32) + sizeof(IMAGE_FILE_HEADER) + + nt_header->FileHeader.SizeOfOptionalHeader); + + + // for each section try and find the section that contains this pointer... + for (auto idx = 0u; idx < section_count; ++idx) + // if the section contains this pointer... + if (ptr >= sections[idx].VirtualAddress + image_base && + ptr < sections[idx].VirtualAddress + image_base + sections[idx].Misc.VirtualSize) + // returns true if the section isnt discardable and isnt writeable (I.E in memory and readonly)... + return !(sections[idx].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) && + !(sections[idx].Characteristics & IMAGE_SCN_MEM_WRITE); + + // pointer isnt inside of the driver... + return false; + } +} \ No newline at end of file diff --git a/scn.hpp b/scn.hpp new file mode 100644 index 0000000..3d60b9f --- /dev/null +++ b/scn.hpp @@ -0,0 +1,121 @@ +#pragma once +#include +#include +#include + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +namespace scn +{ + typedef struct _IMAGE_DOS_HEADER + { + /* 0x0000 */ unsigned short e_magic; + /* 0x0002 */ unsigned short e_cblp; + /* 0x0004 */ unsigned short e_cp; + /* 0x0006 */ unsigned short e_crlc; + /* 0x0008 */ unsigned short e_cparhdr; + /* 0x000a */ unsigned short e_minalloc; + /* 0x000c */ unsigned short e_maxalloc; + /* 0x000e */ unsigned short e_ss; + /* 0x0010 */ unsigned short e_sp; + /* 0x0012 */ unsigned short e_csum; + /* 0x0014 */ unsigned short e_ip; + /* 0x0016 */ unsigned short e_cs; + /* 0x0018 */ unsigned short e_lfarlc; + /* 0x001a */ unsigned short e_ovno; + /* 0x001c */ unsigned short e_res[4]; + /* 0x0024 */ unsigned short e_oemid; + /* 0x0026 */ unsigned short e_oeminfo; + /* 0x0028 */ unsigned short e_res2[10]; + /* 0x003c */ long e_lfanew; + } IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER; /* size: 0x0040 */ + + typedef struct _IMAGE_FILE_HEADER + { + /* 0x0000 */ unsigned short Machine; + /* 0x0002 */ unsigned short NumberOfSections; + /* 0x0004 */ unsigned long TimeDateStamp; + /* 0x0008 */ unsigned long PointerToSymbolTable; + /* 0x000c */ unsigned long NumberOfSymbols; + /* 0x0010 */ unsigned short SizeOfOptionalHeader; + /* 0x0012 */ unsigned short Characteristics; + } IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER; /* size: 0x0014 */ + + typedef struct _IMAGE_DATA_DIRECTORY + { + /* 0x0000 */ unsigned long VirtualAddress; + /* 0x0004 */ unsigned long Size; + } IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; /* size: 0x0008 */ + + typedef struct _IMAGE_OPTIONAL_HEADER64 + { + /* 0x0000 */ unsigned short Magic; + /* 0x0002 */ unsigned char MajorLinkerVersion; + /* 0x0003 */ unsigned char MinorLinkerVersion; + /* 0x0004 */ unsigned long SizeOfCode; + /* 0x0008 */ unsigned long SizeOfInitializedData; + /* 0x000c */ unsigned long SizeOfUninitializedData; + /* 0x0010 */ unsigned long AddressOfEntryPoint; + /* 0x0014 */ unsigned long BaseOfCode; + /* 0x0018 */ unsigned __int64 ImageBase; + /* 0x0020 */ unsigned long SectionAlignment; + /* 0x0024 */ unsigned long FileAlignment; + /* 0x0028 */ unsigned short MajorOperatingSystemVersion; + /* 0x002a */ unsigned short MinorOperatingSystemVersion; + /* 0x002c */ unsigned short MajorImageVersion; + /* 0x002e */ unsigned short MinorImageVersion; + /* 0x0030 */ unsigned short MajorSubsystemVersion; + /* 0x0032 */ unsigned short MinorSubsystemVersion; + /* 0x0034 */ unsigned long Win32VersionValue; + /* 0x0038 */ unsigned long SizeOfImage; + /* 0x003c */ unsigned long SizeOfHeaders; + /* 0x0040 */ unsigned long CheckSum; + /* 0x0044 */ unsigned short Subsystem; + /* 0x0046 */ unsigned short DllCharacteristics; + /* 0x0048 */ unsigned __int64 SizeOfStackReserve; + /* 0x0050 */ unsigned __int64 SizeOfStackCommit; + /* 0x0058 */ unsigned __int64 SizeOfHeapReserve; + /* 0x0060 */ unsigned __int64 SizeOfHeapCommit; + /* 0x0068 */ unsigned long LoaderFlags; + /* 0x006c */ unsigned long NumberOfRvaAndSizes; + /* 0x0070 */ struct _IMAGE_DATA_DIRECTORY DataDirectory[16]; + } IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64; /* size: 0x00f0 */ + + typedef struct _IMAGE_NT_HEADERS64 + { + /* 0x0000 */ unsigned long Signature; + /* 0x0004 */ struct _IMAGE_FILE_HEADER FileHeader; + /* 0x0018 */ struct _IMAGE_OPTIONAL_HEADER64 OptionalHeader; + } IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64; /* size: 0x0108 */ + + typedef struct _IMAGE_SECTION_HEADER + { + /* 0x0000 */ unsigned char Name[8]; + union + { + union + { + /* 0x0008 */ unsigned long PhysicalAddress; + /* 0x0008 */ unsigned long VirtualSize; + }; /* size: 0x0004 */ + } /* size: 0x0004 */ Misc; + /* 0x000c */ unsigned long VirtualAddress; + /* 0x0010 */ unsigned long SizeOfRawData; + /* 0x0014 */ unsigned long PointerToRawData; + /* 0x0018 */ unsigned long PointerToRelocations; + /* 0x001c */ unsigned long PointerToLinenumbers; + /* 0x0020 */ unsigned short NumberOfRelocations; + /* 0x0022 */ unsigned short NumberOfLinenumbers; + /* 0x0024 */ unsigned long Characteristics; + } IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER; /* size: 0x0028 */ + + /// + /// returns true if the ptr pointers to something in a section + /// that is read only... + /// + /// module base of the driver... + /// a valid pointer that lands inside of the driver... + /// returns true if the ptr pointers to something in a section that is read only + bool read_only(u64 image_base, u64 ptr); +} \ No newline at end of file diff --git a/sha1.hpp b/sha1.hpp new file mode 100644 index 0000000..346fcd1 --- /dev/null +++ b/sha1.hpp @@ -0,0 +1,316 @@ +#pragma once + +/* + SHA-1 in C + By Steve Reid + 100% Public Domain + */ + +using uint32_t = unsigned int; + +typedef struct _sha1_ctx +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} sha1_ctx, * psha1_ctx; + +void sha1_transform( + uint32_t state[5], + const unsigned char buffer[64] +); + +void sha1_init( + sha1_ctx* context +); + +void sha1_update( + sha1_ctx* context, + const unsigned char* data, + uint32_t len +); + +void sha1_final( + unsigned char digest[20], + sha1_ctx* context +); + +void sha1( + char* hash_out, + const char* str, + int len); + + +#define SHA1HANDSOFF + +#include +#include + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void sha1_transform( + uint32_t state[5], + const unsigned char buffer[64] +) +{ + uint32_t a, b, c, d, e; + + typedef union + { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void sha1_init( + sha1_ctx* context +) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void sha1_update( + sha1_ctx* context, + const unsigned char* data, + uint32_t len +) +{ + uint32_t i; + + uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64 - j)); + sha1_transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) + { + sha1_transform(context->state, &data[i]); + } + j = 0; + } + else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void sha1_final( + unsigned char digest[20], + sha1_ctx* context +) +{ + unsigned i; + + unsigned char finalcount[8]; + + unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char* fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char)t + } +#else + for (i = 0; i < 8; i++) + { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } +#endif + c = 0200; + sha1_update(context, &c, 1); + while ((context->count[0] & 504) != 448) + { + c = 0000; + sha1_update(context, &c, 1); + } + sha1_update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void sha1( + char* hash_out, + const char* str, + int len) +{ + sha1_ctx ctx; + unsigned int ii; + + sha1_init(&ctx); + for (ii = 0; ii < len; ii += 1) + sha1_update(&ctx, (const unsigned char*)str + ii, 1); + sha1_final((unsigned char*)hash_out, &ctx); + hash_out[20] = '\0'; +} \ No newline at end of file diff --git a/shithook.hpp b/shithook.hpp new file mode 100644 index 0000000..d26fdb2 --- /dev/null +++ b/shithook.hpp @@ -0,0 +1,75 @@ +#pragma once +#include + +typedef struct _inline_hook_t +{ + unsigned char code[14]; + unsigned char jmp_code[14]; + + void* address; + void* hook_address; +} inline_hook_t, * pinline_hook_t; + +void make_inline_hook(pinline_hook_t, void*, void*, bool); +void enable_inline_hook(pinline_hook_t); +void disable_inline_hook(pinline_hook_t); + +inline void make_inline_hook(pinline_hook_t hook, void* hook_from, void* hook_to, bool install) +{ + unsigned char jmp_code[14] = + { + 0xff, 0x25, 0x0, 0x0, 0x0, 0x0, // jmp QWORD PTR[rip + 0x0] + + // jmp address... + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0 + }; + + // save original bytes, and hook related addresses.... + hook->address = hook_from; + hook->hook_address = hook_to; + memcpy(hook->code, hook_from, sizeof hook->code); + + // setup hook... + memcpy(jmp_code + 6, &hook_to, sizeof hook_to); + memcpy(hook->jmp_code, jmp_code, sizeof jmp_code); + if (install) enable_inline_hook(hook); +} + +inline void enable_inline_hook(pinline_hook_t hook) +{ + { + auto cr0 = __readcr0(); + cr0 &= 0xfffffffffffeffff; + __writecr0(cr0); + _disable(); + } + + memcpy(hook->address, hook->jmp_code, sizeof hook->jmp_code); + + { + auto cr0 = __readcr0(); + cr0 |= 0x10000; + _enable(); + __writecr0(cr0); + } +} + +inline void disable_inline_hook(pinline_hook_t hook) +{ + { + auto cr0 = __readcr0(); + cr0 &= 0xfffffffffffeffff; + __writecr0(cr0); + _disable(); + } + + memcpy(hook->address, hook->code, sizeof hook->code); + + { + auto cr0 = __readcr0(); + cr0 |= 0x10000; + _enable(); + __writecr0(cr0); + } +} diff --git a/unknown.png b/unknown.png new file mode 100644 index 0000000..ce11174 Binary files /dev/null and b/unknown.png differ diff --git a/vmhook-eac.sys b/vmhook-eac.sys new file mode 100644 index 0000000..d8d6888 Binary files /dev/null and b/vmhook-eac.sys differ diff --git a/vmhook-eac.vcxproj b/vmhook-eac.vcxproj index 0af24c9..2ede5ea 100644 --- a/vmhook-eac.vcxproj +++ b/vmhook-eac.vcxproj @@ -71,9 +71,14 @@ + + + + + diff --git a/vmhook-eac.vcxproj.filters b/vmhook-eac.vcxproj.filters index 2b23e1d..9aa0900 100644 --- a/vmhook-eac.vcxproj.filters +++ b/vmhook-eac.vcxproj.filters @@ -17,11 +17,26 @@ Source Files + + Source Files + Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files +