├── hook.png
├── VanguardTrace
├── Signature Scan.hpp
├── VanguardTrace.vcxproj.user
├── Include.hpp
├── Hooks.hpp
├── Vanguard.hpp
├── Native.hpp
├── Hooks.cpp
├── Main.cpp
├── Native.cpp
├── Signature Scan.cpp
├── VanguardTrace.vcxproj.filters
├── Vanguard.cpp
└── VanguardTrace.vcxproj
├── VanguardTrace.sln
├── LICENSE
└── README.md
/hook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/armvirus/VanguardTrace/HEAD/hook.png
--------------------------------------------------------------------------------
/VanguardTrace/Signature Scan.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Scanner
4 | {
5 | PVOID FindPatternImage(PCHAR base, PCHAR pattern, PCHAR mask);
6 | PVOID FindPatternImageExec(PCHAR base, PCHAR pattern, PCHAR mask);
7 | PVOID FindPattern(PCHAR base, DWORD length, PCHAR pattern, PCHAR mask);
8 | }
--------------------------------------------------------------------------------
/VanguardTrace/VanguardTrace.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Off
5 |
6 |
--------------------------------------------------------------------------------
/VanguardTrace/Include.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "Native.hpp"
11 | #include "Signature Scan.hpp"
12 | #include "Vanguard.hpp"
13 | #include "Hooks.hpp"
14 |
15 | #define RVA(Instr, InstrSize) ((ULONG64)Instr + InstrSize + *(LONG*)((ULONG64)Instr + (InstrSize - sizeof(LONG))))
16 | #define DebugPrint(fmt, ...) DbgPrintEx(0, 0, "[VanguardStackTrace] " fmt, ##__VA_ARGS__)
--------------------------------------------------------------------------------
/VanguardTrace/Hooks.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Hooks
4 | {
5 | inline NTSTATUS(*CiCheckSignedFileOg)(void* Buf1, size_t Size, unsigned int a3, __int64 a4, unsigned int a5, __int64 a6, __int64* a7, __int64* a8);
6 |
7 | NTSTATUS CiCheckSignedFileHookVgk(void* Buf1, size_t Size, unsigned int a3, __int64 a4, unsigned int a5, __int64 a6, __int64* a7, __int64* a8);
8 | NTSTATUS ZwDeviceIoControlFileHook(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
9 | }
--------------------------------------------------------------------------------
/VanguardTrace/Vanguard.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct KeyOffsets {
4 | __int64 wordOffset; // Previously key1
5 | __int64 qwordPtrOffset; // Previously key2
6 | __int64 qwordOffset; // Previously key3
7 | __int64 byteCountOffset; // Previously key4
8 | };
9 |
10 | namespace Vanguard
11 | {
12 | void HookVgkImportFunction(std::uintptr_t VanguardBase, std::uintptr_t ImportOffset, std::uintptr_t originalFunctionPtr);
13 | std::uintptr_t DecryptVGKImportFunction(std::uintptr_t VanguardBase, std::uintptr_t ImportOffset);
14 | std::uint32_t findImportOffset(std::uintptr_t VanguardBase, const char* ImportModule, const char* ImportName, std::uint32_t startOffset);
15 | std::uint32_t getImportStartOffset(std::uintptr_t VanguardBase, std::size_t VanguardSize);
16 | }
--------------------------------------------------------------------------------
/VanguardTrace/Native.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | extern "C"
4 | {
5 | NTSTATUS NTAPI ZwQuerySystemInformation(ULONG SystemInformationClass, PVOID SystemInformation,
6 | ULONG SystemInformationLength, PULONG ReturnLength);
7 |
8 | extern "C" NTKERNELAPI
9 | PVOID
10 | NTAPI
11 | RtlFindExportedRoutineByName(
12 | _In_ PVOID ImageBase,
13 | _In_ PCCH RoutineNam
14 | );
15 | }
16 |
17 | namespace Native
18 | {
19 | NTSTATUS getKernelModuleByName(const char *moduleName, std::uintptr_t *moduleStart, std::size_t *moduleSize);
20 | }
21 |
22 | typedef struct _SYSTEM_MODULE_ENTRY {
23 | HANDLE Section;
24 | PVOID MappedBase;
25 | PVOID ImageBase;
26 | ULONG ImageSize;
27 | ULONG Flags;
28 | USHORT LoadOrderIndex;
29 | USHORT InitOrderIndex;
30 | USHORT LoadCount;
31 | USHORT OffsetToFileName;
32 | UCHAR FullPathName[256];
33 | } SYSTEM_MODULE_ENTRY, * PSYSTEM_MODULE_ENTRY;
34 |
35 | typedef struct _SYSTEM_MODULE_INFORMATION {
36 | ULONG Count;
37 | SYSTEM_MODULE_ENTRY Module[1];
38 | } SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
--------------------------------------------------------------------------------
/VanguardTrace.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32901.215
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VanguardTrace", "VanguardTrace\VanguardTrace.vcxproj", "{1E272B48-82A2-4222-97C4-BC6D4FA1CBF6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|x64 = Release|x64
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {1E272B48-82A2-4222-97C4-BC6D4FA1CBF6}.Release|x64.ActiveCfg = Release|x64
14 | {1E272B48-82A2-4222-97C4-BC6D4FA1CBF6}.Release|x64.Build.0 = Release|x64
15 | {1E272B48-82A2-4222-97C4-BC6D4FA1CBF6}.Release|x64.Deploy.0 = Release|x64
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {FF68B84B-D997-4FA3-8258-A9B5E5967AFF}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 armvirus
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/VanguardTrace/Hooks.cpp:
--------------------------------------------------------------------------------
1 | #include "Include.hpp"
2 |
3 | namespace Hooks
4 | {
5 | NTSTATUS CiCheckSignedFileHookVgk(void* Buf1, size_t Size, unsigned int a3, __int64 a4, unsigned int a5, __int64 a6, __int64* a7, __int64* a8)
6 | {
7 | auto ret = CiCheckSignedFileOg(Buf1, Size, a3, a4, a5, a6, a7, a8);
8 |
9 | DebugPrint("[%p] CiCheckSignedFile Called with Buf %p\n", _ReturnAddress(), Buf1);
10 |
11 | return ret == STATUS_INVALID_IMAGE_HASH ? STATUS_SUCCESS : ret;
12 | }
13 |
14 | NTSTATUS ZwDeviceIoControlFileHook(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
15 | {
16 | DebugPrint("ZwDeviceIoControlFile Called From 0x%p\n", _ReturnAddress());
17 | DebugPrint(" - IoControlCode: 0x%p\n", IoControlCode);
18 |
19 | return ZwDeviceIoControlFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength);
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/VanguardTrace/Main.cpp:
--------------------------------------------------------------------------------
1 | #include "Include.hpp"
2 |
3 | NTSTATUS DriverEntry(const PDRIVER_OBJECT driverObject, const PUNICODE_STRING registryPath)
4 | {
5 | DebugPrint("Vanguard Trace Hook Initiating...\n");
6 |
7 | std::uintptr_t moduleBase = 0;
8 | std::size_t moduleSize = 0;
9 |
10 | if (Native::getKernelModuleByName("vgk.sys", &moduleBase, &moduleSize))
11 | return STATUS_NOT_FOUND;
12 |
13 | std::uint32_t startOffset = Vanguard::getImportStartOffset(moduleBase, moduleSize); // 0x816a0;
14 |
15 | DebugPrint("Found startOffset @ 0x%x", startOffset);
16 |
17 | std::uint32_t ExCreateCallbackOffset = Vanguard::findImportOffset(moduleBase, "ntoskrnl.exe", "ExCreateCallback", startOffset);
18 |
19 | DebugPrint("Found ExCreateCallbackOffset @ 0x%x", ExCreateCallbackOffset);
20 |
21 | std::uint32_t CiCheckSignedFileOffset = Vanguard::findImportOffset(moduleBase, "CI.dll", "CiCheckSignedFile", startOffset);
22 |
23 | DebugPrint("Found CiCheckSignedFileOffset @ 0x%x", CiCheckSignedFileOffset);
24 |
25 | *reinterpret_cast(&Hooks::CiCheckSignedFileOg) = Vanguard::DecryptVGKImportFunction(moduleBase, CiCheckSignedFileOffset);
26 |
27 | Vanguard::HookVgkImportFunction(moduleBase, CiCheckSignedFileOffset, reinterpret_cast(&Hooks::CiCheckSignedFileHookVgk));
28 |
29 | return STATUS_SUCCESS;
30 | }
--------------------------------------------------------------------------------
/VanguardTrace/Native.cpp:
--------------------------------------------------------------------------------
1 | #include "Include.hpp"
2 |
3 | namespace Native
4 | {
5 | NTSTATUS getKernelModuleByName(const char* moduleName, std::uintptr_t* moduleStart, std::size_t* moduleSize)
6 | {
7 | if (!moduleStart || !moduleSize)
8 | return STATUS_INVALID_PARAMETER;
9 |
10 | std::size_t size{};
11 | ZwQuerySystemInformation(0xB, nullptr, size, reinterpret_cast(&size));
12 |
13 | const auto listHeader = ExAllocatePool(NonPagedPool, size);
14 | if (!listHeader)
15 | return STATUS_MEMORY_NOT_ALLOCATED;
16 |
17 | if (const auto status = ZwQuerySystemInformation(0xB, listHeader, size, reinterpret_cast(&size)))
18 | return status;
19 |
20 | auto currentModule = reinterpret_cast(listHeader)->Module;
21 | for (std::size_t i{}; i < reinterpret_cast(listHeader)->Count; ++i, ++currentModule)
22 | {
23 | const auto currentModuleName = reinterpret_cast(currentModule->FullPathName + currentModule->OffsetToFileName);
24 | //DebugPrint("currentModuleName %s\n", currentModuleName);
25 | if (!strcmp(moduleName, currentModuleName))
26 | {
27 | *moduleStart = reinterpret_cast(currentModule->ImageBase);
28 | *moduleSize = currentModule->ImageSize;
29 | return STATUS_SUCCESS;
30 | }
31 | }
32 |
33 | return STATUS_NOT_FOUND;
34 | }
35 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VanguardTrace
2 |
3 | ### Decrypting and Intercepting Encrypted Imports of Vanguard's Kernel Driver
4 |
5 | Welcome to VanguardTrace, a tool designed to decrypt and intercept encrypted imports within Vanguard's Kernel Driver.
6 |
7 | ## Overview
8 |
9 | I began my exploration of vgk.sys and its import protection mechanisms. One strategy that immediately occurred to me for gaining insight was to employ a patchguard bypass. By hooking potential imports and capturing their return addresses, I could trace back to where vgk.sys calls these imports. This approach led me directly to their decryption algorithm. With a clear understanding of this algorithm, I proceeded to rewrite it for readability and created the complementary encryption function. Additionally, I developed functions to determine the starting offset of the imports encryption "table" using a simple signature scan, and to retrieve the offset of specific imports of interest.
10 |
11 | ## Features
12 |
13 | - **Decryption**: Decrypt encrypted imports within Vanguard's Kernel Driver.
14 | - **Interception**: Intercept and manipulate encrypted imports.
15 | - **Pointer Encryption**: Encrypt pointers with their encryption routine to assist with intercepting.
16 | - **Automatic Import Table Location**: Automatically locate the start of the encrypted import table using a signature scan.
17 | - **Offset Identification**: Identify the offset of the desired import for easy manipulation/hooking.
18 |
19 | ## Example Usage
20 |
21 | 
22 |
23 | ## License
24 |
25 | This project is licensed under the [MIT License](LICENSE).
26 |
--------------------------------------------------------------------------------
/VanguardTrace/Signature Scan.cpp:
--------------------------------------------------------------------------------
1 | #include "Include.hpp"
2 |
3 | namespace Scanner
4 | {
5 | BOOLEAN CheckMask(PCHAR base, PCHAR pattern, PCHAR mask)
6 | {
7 | for (; *mask; ++base, ++pattern, ++mask)
8 | {
9 | if (*mask == 'x' && *base != *pattern)
10 | {
11 | return FALSE;
12 | }
13 | }
14 |
15 | return TRUE;
16 | }
17 |
18 | PVOID FindPattern(PCHAR base, DWORD length, PCHAR pattern, PCHAR mask)
19 | {
20 | length -= (DWORD)strlen(mask);
21 |
22 | for (DWORD i = 0; i <= length; ++i)
23 | {
24 | PVOID addr = &base[i];
25 | if (CheckMask((PCHAR)addr, pattern, mask))
26 | {
27 | return addr;
28 | }
29 | }
30 |
31 | return 0;
32 | }
33 |
34 | PVOID FindPatternImage(PCHAR base, PCHAR pattern, PCHAR mask)
35 | {
36 | PVOID match = 0;
37 |
38 | PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(base + ((PIMAGE_DOS_HEADER)base)->e_lfanew);
39 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers);
40 |
41 | for (DWORD i = 0; i < headers->FileHeader.NumberOfSections; ++i)
42 | {
43 | PIMAGE_SECTION_HEADER section = §ions[i];
44 |
45 | if (memcmp(section->Name, ".text", 5) == 0)
46 | {
47 | match = FindPattern(base + section->VirtualAddress, section->Misc.VirtualSize, pattern, mask);
48 | if (match)
49 | {
50 | break;
51 | }
52 | }
53 | }
54 |
55 | return match;
56 | }
57 |
58 | PVOID FindPatternImageExec(PCHAR base, PCHAR pattern, PCHAR mask)
59 | {
60 | PVOID match = 0;
61 |
62 | PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(base + ((PIMAGE_DOS_HEADER)base)->e_lfanew);
63 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers);
64 |
65 | for (DWORD i = 0; i < headers->FileHeader.NumberOfSections; ++i)
66 | {
67 | PIMAGE_SECTION_HEADER section = §ions[i];
68 |
69 | if (*(PINT)section->Name == 'EGAP' || memcmp(section->Name, ".text", 5) == 0)
70 | {
71 | match = FindPattern(base + section->VirtualAddress, section->Misc.VirtualSize, pattern, mask);
72 | if (match)
73 | {
74 | break;
75 | }
76 | }
77 | }
78 |
79 | return match;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/VanguardTrace/VanguardTrace.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {8E41214B-6785-4CFE-B992-037D68949A14}
18 | inf;inv;inx;mof;mc;
19 |
20 |
21 |
22 |
23 | Source Files
24 |
25 |
26 | Source Files
27 |
28 |
29 | Source Files
30 |
31 |
32 | Source Files
33 |
34 |
35 | Source Files
36 |
37 |
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Header Files
47 |
48 |
49 | Header Files
50 |
51 |
52 | Header Files
53 |
54 |
55 |
--------------------------------------------------------------------------------
/VanguardTrace/Vanguard.cpp:
--------------------------------------------------------------------------------
1 | #include "Include.hpp"
2 |
3 | namespace Vanguard
4 | {
5 | void HookVgkImportFunction(std::uintptr_t VanguardBase, std::uintptr_t ImportOffset, std::uintptr_t originalFunctionPtr)
6 | {
7 | if (!VanguardBase || !ImportOffset || !originalFunctionPtr)
8 | return;
9 |
10 | KeyOffsets offsets = {
11 | ImportOffset,
12 | ImportOffset + 0x8,
13 | ImportOffset + 0x18,
14 | ImportOffset + 0x20
15 | };
16 |
17 | // Retrieve the original values from the offsets
18 | uintptr_t& wordAtKey1 = *reinterpret_cast(VanguardBase + offsets.wordOffset);
19 | uintptr_t& functionXor = *reinterpret_cast(VanguardBase + offsets.qwordPtrOffset + 8 * HIBYTE(wordAtKey1));
20 | uintptr_t& byteCount = *reinterpret_cast(VanguardBase + offsets.byteCountOffset);
21 | unsigned char byteCountValue = static_cast(byteCount);
22 |
23 | // Reverse the XOR operations for the byteCount part
24 | if (HIBYTE(byteCount) > 0) {
25 | uintptr_t valueAtKey3 = *reinterpret_cast(VanguardBase + offsets.qwordOffset);
26 | for (size_t i = 8 - HIBYTE(byteCount); i < 8; ++i) {
27 | reinterpret_cast(&originalFunctionPtr)[i] ^= reinterpret_cast(valueAtKey3)[i];
28 | }
29 | }
30 |
31 | // Reverse the XOR operations for the main encryption loop
32 | for (int8_t i = byteCountValue - 1; i >= 0; --i) {
33 | uintptr_t xorValue = *reinterpret_cast(VanguardBase + offsets.qwordOffset + 8 * (i & 0xFF));
34 | originalFunctionPtr ^= xorValue;
35 | }
36 |
37 | // Overwrite the original function pointer with the encrypted value
38 | functionXor = originalFunctionPtr;
39 | }
40 |
41 | std::uintptr_t DecryptVGKImportFunction(std::uintptr_t VanguardBase, std::uintptr_t ImportOffset)
42 | {
43 | if (!VanguardBase || !ImportOffset)
44 | return 0;
45 |
46 | KeyOffsets offsets = {
47 | ImportOffset,
48 | ImportOffset + 0x8,
49 | ImportOffset + 0x18,
50 | ImportOffset + 0x20
51 | };
52 |
53 | uintptr_t wordAtKey1 = *reinterpret_cast(VanguardBase + offsets.wordOffset);
54 | if (!wordAtKey1)
55 | return 0;
56 |
57 | uintptr_t functionXor = *reinterpret_cast<__int64*>(VanguardBase + offsets.qwordPtrOffset + 8 * HIBYTE(wordAtKey1));
58 | if (!functionXor)
59 | return 0;
60 |
61 | uintptr_t byteCount = *reinterpret_cast(VanguardBase + offsets.byteCountOffset);
62 | if (byteCount != 1)
63 | return 0;
64 |
65 | unsigned char byteCountValue = static_cast(byteCount);
66 |
67 | for (uint8_t i = 0; i < byteCountValue; ++i) {
68 | uintptr_t xorValue = *reinterpret_cast(VanguardBase + offsets.qwordOffset + 8 * (i & 0xFF));
69 | functionXor ^= xorValue;
70 | }
71 |
72 | if (HIBYTE(byteCount) > 0)
73 | {
74 | uintptr_t valueAtKey3 = *reinterpret_cast(VanguardBase + offsets.qwordOffset);
75 |
76 | for (size_t i = 8 - HIBYTE(byteCount); i < 8; ++i) {
77 | reinterpret_cast(&functionXor)[i] ^= reinterpret_cast(valueAtKey3)[i];
78 | }
79 | }
80 |
81 | return functionXor;
82 | }
83 |
84 | std::uint32_t getImportStartOffset(std::uintptr_t VanguardBase, std::size_t VanguardSize)
85 | {
86 | if (!VanguardBase || !VanguardSize)
87 | return 0;
88 |
89 | // [actual address in first opcode] 66 0F AB D3 44 38 1D ? ? ? ?
90 | // 66 C7 05 ? ? ? ? ? ? 48 63 D5
91 | // 4C 8D 05 ? ? ? ? 48 0F B7 CA
92 |
93 | std::uintptr_t leaStartOffset = reinterpret_cast(Scanner::FindPattern(reinterpret_cast(VanguardBase), VanguardSize, "\x8A\x15\x00\x00\x00\x00\xE9\x00\x00\x00\x00\x48\x98", "xx????x????xx"));
94 | if (!leaStartOffset || !MmIsAddressValid(reinterpret_cast(leaStartOffset)))
95 | return 0;
96 |
97 | std::uintptr_t startOffset = RVA(leaStartOffset, 6);
98 | if (!startOffset || !MmIsAddressValid(reinterpret_cast(startOffset)))
99 | return 0;
100 |
101 | std::uint32_t randomOffset = startOffset - VanguardBase - 1;
102 |
103 | std::uint32_t firstImport = 0;
104 | for (int i = 0;; i++)
105 | {
106 | std::uint32_t Offset = randomOffset - i * 0x28;
107 | std::uintptr_t DecryptedRoutine = Vanguard::DecryptVGKImportFunction(VanguardBase, Offset);
108 | if (!DecryptedRoutine || !MmIsAddressValid(reinterpret_cast(DecryptedRoutine)))
109 | break;
110 |
111 | firstImport = Offset;
112 | }
113 |
114 | return firstImport;
115 | }
116 |
117 | std::uint32_t findImportOffset(std::uintptr_t VanguardBase, const char* ImportModule, const char* ImportName, std::uint32_t startOffset)
118 | {
119 | if (!VanguardBase || !startOffset)
120 | return 0;
121 |
122 | std::uintptr_t importModuleBase{};
123 | std::size_t importModuleSize{};
124 |
125 | if (!NT_SUCCESS(Native::getKernelModuleByName(ImportModule, &importModuleBase, &importModuleSize)))
126 | return 0;
127 |
128 | std::uintptr_t importAddress = reinterpret_cast(RtlFindExportedRoutineByName(reinterpret_cast(importModuleBase), ImportName));
129 | if (!importAddress)
130 | return 0;
131 |
132 | for (int i = 0; ; i++)
133 | {
134 | std::uint32_t Offset = startOffset + i * 0x28;
135 | std::uintptr_t DecryptedRoutine = Vanguard::DecryptVGKImportFunction(VanguardBase, Offset);
136 | if (!DecryptedRoutine || !MmIsAddressValid(reinterpret_cast(DecryptedRoutine)))
137 | break;
138 |
139 | if (importAddress == DecryptedRoutine)
140 | return Offset;
141 | }
142 |
143 | return 0;
144 | }
145 | }
--------------------------------------------------------------------------------
/VanguardTrace/VanguardTrace.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 | Debug
22 | ARM
23 |
24 |
25 | Release
26 | ARM
27 |
28 |
29 | Debug
30 | ARM64
31 |
32 |
33 | Release
34 | ARM64
35 |
36 |
37 |
38 | {1E272B48-82A2-4222-97C4-BC6D4FA1CBF6}
39 | {1bc93793-694f-48fe-9372-81e2b05556fd}
40 | v4.5
41 | 12.0
42 | Debug
43 | Win32
44 | VanguardTrace
45 | $(LatestTargetPlatformVersion)
46 | VanguardTrace
47 |
48 |
49 |
50 | Windows10
51 | true
52 | WindowsKernelModeDriver10.0
53 | Driver
54 | KMDF
55 | Universal
56 |
57 |
58 | Windows10
59 | false
60 | WindowsKernelModeDriver10.0
61 | Driver
62 | KMDF
63 | Universal
64 |
65 |
66 | Windows10
67 | true
68 | WindowsKernelModeDriver10.0
69 | Driver
70 | KMDF
71 | Universal
72 |
73 |
74 | Windows10
75 | false
76 | WindowsKernelModeDriver10.0
77 | Driver
78 | KMDF
79 | Universal
80 | false
81 | 1
82 |
83 |
84 | Windows10
85 | true
86 | WindowsKernelModeDriver10.0
87 | Driver
88 | KMDF
89 | Universal
90 |
91 |
92 | Windows10
93 | false
94 | WindowsKernelModeDriver10.0
95 | Driver
96 | KMDF
97 | Universal
98 |
99 |
100 | Windows10
101 | true
102 | WindowsKernelModeDriver10.0
103 | Driver
104 | KMDF
105 | Universal
106 |
107 |
108 | Windows10
109 | false
110 | WindowsKernelModeDriver10.0
111 | Driver
112 | KMDF
113 | Universal
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | DbgengKernelDebugger
124 |
125 |
126 | DbgengKernelDebugger
127 |
128 |
129 | DbgengKernelDebugger
130 | $(VC_IncludePath);$(IncludePath)
131 |
132 |
133 | DbgengKernelDebugger
134 | $(VC_IncludePath);$(IncludePath)
135 | $(SolutionDir)Output\
136 | $(SolutionDir)VanguardTrace\Bin\
137 | false
138 |
139 |
140 | DbgengKernelDebugger
141 |
142 |
143 | DbgengKernelDebugger
144 |
145 |
146 | DbgengKernelDebugger
147 |
148 |
149 | DbgengKernelDebugger
150 |
151 |
152 |
153 | stdcpp17
154 | TurnOffAllWarnings
155 | false
156 | true
157 |
158 |
159 | DriverEntry
160 |
161 |
162 |
163 |
164 | stdcpp17
165 | TurnOffAllWarnings
166 | false
167 | true
168 | ProgramDatabase
169 |
170 |
171 |
172 | DriverEntry
173 | true
174 | false
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
--------------------------------------------------------------------------------