HyperDbg Debugger
Loading...
Searching...
No Matches
ZydisKernel.c File Reference
#include "pch.h"
#include <ntimage.h>
#include <stdio.h>
#include <stdarg.h>

Functions

NTKERNELAPI PVOID NTAPI RtlPcToFileHeader (_In_ PVOID PcValue, _Out_ PVOID *BaseOfImage)
 
NTKERNELAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader (_In_ PVOID ImageBase)
 
VOID Print (_In_ PCCH Format, _In_...)
 
_Use_decl_annotations_ NTSTATUS DriverEntryTest (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
 

Variables

DRIVER_INITIALIZE DriverEntry
 

Detailed Description

Windows kernel mode driver sample.

This is a Windows kernel mode driver. It links against the kernel mode-compatible version of Zydis. The driver finds its own entry point and decodes and prints the disassembly of this function. To view the log, either attach a kernel debugger or use a tool like Sysinternals DebugView.

Function Documentation

◆ DriverEntryTest()

_Use_decl_annotations_ NTSTATUS DriverEntryTest ( _In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath )
95{
96 PAGED_CODE();
97
98 UNREFERENCED_PARAMETER(RegistryPath);
99
100 if (ZydisGetVersion() != ZYDIS_VERSION)
101 {
102 Print("Invalid zydis version\n");
103 return STATUS_UNKNOWN_REVISION;
104 }
105
106 // Get the driver's image base and PE headers
107 ULONG_PTR imageBase;
108 RtlPcToFileHeader((PVOID)DriverObject->DriverInit, (PVOID *)&imageBase);
109 if (imageBase == 0)
110 return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
111 const PIMAGE_NT_HEADERS ntHeaders = RtlImageNtHeader((PVOID)imageBase);
112 if (ntHeaders == NULL)
113 return STATUS_INVALID_IMAGE_FORMAT;
114
115 // Get the section headers of the INIT section
116 PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
117 PIMAGE_SECTION_HEADER initSection = NULL;
118 for (USHORT i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
119 {
120 if (memcmp(section->Name, "INIT", sizeof("INIT") - 1) == 0)
121 {
122 initSection = section;
123 break;
124 }
125 section++;
126 }
127 if (initSection == NULL)
128 return STATUS_NOT_FOUND;
129
130 // Get the RVAs of the entry point and import directory. If the import directory lies within the INIT section,
131 // stop disassembling when its address is reached. Otherwise, disassemble until the end of the INIT section.
132 const ULONG entryPointRva = (ULONG)((ULONG_PTR)DriverObject->DriverInit - imageBase);
133 const ULONG importDirRva = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
134 SIZE_T length = initSection->VirtualAddress + initSection->SizeOfRawData - entryPointRva;
135 if (importDirRva > entryPointRva && importDirRva > initSection->VirtualAddress &&
136 importDirRva < initSection->VirtualAddress + initSection->SizeOfRawData)
137 length = importDirRva - entryPointRva;
138
139 Print("Driver image base: 0x%p, size: 0x%X\n", (PVOID)imageBase, ntHeaders->OptionalHeader.SizeOfImage);
140 Print("Entry point RVA: 0x%X (0x%p)\n", entryPointRva, DriverObject->DriverInit);
141
142 // Initialize Zydis decoder and formatter
143 ZydisDecoder decoder;
144#ifdef _M_AMD64
145 if (!ZYAN_SUCCESS(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64)))
146#else
147 if (!ZYAN_SUCCESS(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32)))
148#endif
149 return STATUS_DRIVER_INTERNAL_ERROR;
150
151 ZydisFormatter formatter;
152 if (!ZYAN_SUCCESS(ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL)))
153 return STATUS_DRIVER_INTERNAL_ERROR;
154
155 SIZE_T readOffset = 0;
156 ZydisDecodedInstruction instruction;
157 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
158 ZyanStatus status;
159 CHAR printBuffer[128];
160
161 // Start the decode loop
162 while ((status = ZydisDecoderDecodeFull(&decoder,
163 (PVOID)(imageBase + entryPointRva + readOffset),
164 length - readOffset,
165 &instruction,
166 operands)) != ZYDIS_STATUS_NO_MORE_DATA)
167 {
168 NT_ASSERT(ZYAN_SUCCESS(status));
169 if (!ZYAN_SUCCESS(status))
170 {
171 readOffset++;
172 continue;
173 }
174
175 // Format and print the instruction
176 const ZyanU64 instrAddress = (ZyanU64)(imageBase + entryPointRva + readOffset);
177 ZydisFormatterFormatInstruction(
178 &formatter,
179 &instruction,
180 operands,
181 instruction.operand_count_visible,
182 printBuffer,
183 sizeof(printBuffer),
184 instrAddress,
185 NULL);
186 Print("+%-4X 0x%-16llX\t\t%hs\n", (ULONG)readOffset, instrAddress, printBuffer);
187
188 readOffset += instruction.length;
189 }
190
191 // Return an error status so that the driver does not have to be unloaded after running.
192 return STATUS_UNSUCCESSFUL;
193}
unsigned short USHORT
Definition BasicTypes.h:36
char CHAR
Definition BasicTypes.h:31
unsigned long ULONG
Definition BasicTypes.h:37
#define STATUS_UNSUCCESSFUL
Definition Windows.h:172
NTKERNELAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(_In_ PVOID ImageBase)
NTKERNELAPI PVOID NTAPI RtlPcToFileHeader(_In_ PVOID PcValue, _Out_ PVOID *BaseOfImage)
VOID Print(_In_ PCCH Format, _In_...)
Definition ZydisKernel.c:72
NULL()
Definition test-case-generator.py:530

◆ Print()

VOID Print ( _In_ PCCH Format,
_In_...  )
75{
76 CHAR message[512];
77 va_list argList;
78 va_start(argList, Format);
79 const int n = _vsnprintf_s(message, sizeof(message), sizeof(message) - 1, Format, argList);
80 message[n] = '\0';
81 vDbgPrintExWithPrefix("[ZYDIS] ", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, message, argList);
82
83 va_end(argList);
84}

◆ RtlImageNtHeader()

NTKERNELAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader ( _In_ PVOID ImageBase)

◆ RtlPcToFileHeader()

NTKERNELAPI PVOID NTAPI RtlPcToFileHeader ( _In_ PVOID PcValue,
_Out_ PVOID * BaseOfImage )

Variable Documentation

◆ DriverEntry

DRIVER_INITIALIZE DriverEntry