HyperDbg Debugger
Loading...
Searching...
No Matches
AddressCheck.c File Reference
#include "pch.h"

Functions

BOOLEAN CheckAddressValidityUsingTsx (CHAR *Address)
 This function checks whether the address is valid or not using Intel TSX.
BOOLEAN CheckAddressCanonicality (UINT64 VAddr, PBOOLEAN IsKernelAddress)
 Checks if the address is canonical based on x86 processor's virtual address width or not.
BOOLEAN CheckAddressPhysical (UINT64 PAddr)
 Checks if the physical address is correct or not based on physical address width.
BOOLEAN CheckAccessValidityAndSafetyWrapper (UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId)
 Check the safety to access the memory wrapper.
BOOLEAN CheckAccessValidityAndSafety (UINT64 TargetAddress, UINT32 Size)
 Check the safety to access the memory.
BOOLEAN CheckAccessValidityAndSafetyByProcessId (UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId)
 Check the safety to access the memory by process ID.
UINT32 CheckAddressMaximumInstructionLength (PVOID Address)
 This function returns the maximum instruction length that can be read from this address.

Function Documentation

◆ CheckAccessValidityAndSafety()

BOOLEAN CheckAccessValidityAndSafety ( UINT64 TargetAddress,
UINT32 Size )

Check the safety to access the memory.

Parameters
TargetAddress
Size
Returns
BOOLEAN
319{
320 return CheckAccessValidityAndSafetyWrapper(TargetAddress, Size, NULL_ZERO);
321}
BOOLEAN CheckAccessValidityAndSafetyWrapper(UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId)
Check the safety to access the memory wrapper.
Definition AddressCheck.c:157
#define NULL_ZERO
Definition BasicTypes.h:110

◆ CheckAccessValidityAndSafetyByProcessId()

BOOLEAN CheckAccessValidityAndSafetyByProcessId ( UINT64 TargetAddress,
UINT32 Size,
UINT32 ProcessId )

Check the safety to access the memory by process ID.

Parameters
TargetAddress
Size
ProcessId
Returns
BOOLEAN
333{
334 return CheckAccessValidityAndSafetyWrapper(TargetAddress, Size, ProcessId);
335}

◆ CheckAccessValidityAndSafetyWrapper()

BOOLEAN CheckAccessValidityAndSafetyWrapper ( UINT64 TargetAddress,
UINT32 Size,
UINT32 ProcessId )

Check the safety to access the memory wrapper.

Parameters
TargetAddress
Size
ProcessIdNULL if the current process is used
Returns
BOOLEAN
158{
159 CR3_TYPE GuestCr3;
160 UINT64 OriginalCr3;
161 BOOLEAN IsKernelAddress;
162 BOOLEAN Result = FALSE;
163
164 //
165 // First, we check if the address is canonical based
166 // on Intel processor's virtual address width
167 //
168 if (!CheckAddressCanonicality(TargetAddress, &IsKernelAddress))
169 {
170 //
171 // No need for further check, address is invalid
172 //
173 Result = FALSE;
174 goto Return;
175 }
176
177 if (ProcessId == NULL_ZERO)
178 {
179 //
180 // Find the current process cr3
181 //
183 }
184 else
185 {
186 //
187 // Find the target process cr3
188 //
189 GuestCr3.Flags = LayoutGetCr3ByProcessId(ProcessId).Flags;
190 }
191
192 //
193 // Move to new cr3
194 //
195 OriginalCr3 = CpuReadCr3();
196 CpuWriteCr3(GuestCr3.Flags);
197
198 //
199 // We'll only check address with TSX if the address is a kernel-mode
200 // address because an exception is thrown if we access user-mode code
201 // from vmx-root mode, thus, TSX will fail the transaction and the
202 // result is not true, so we check each pages' page-table for user-mode
203 // codes in both user-mode and kernel-mode
204 //
205 // if (g_RtmSupport && IsKernelAddress)
206 // {
207 // //
208 // // The guest supports Intel TSX
209 // //
210 // UINT64 AlignedPage = (UINT64)PAGE_ALIGN(TargetAddress);
211 // UINT64 PageCount = ((TargetAddress - AlignedPage) + Size) / PAGE_SIZE;
212 //
213 // for (SIZE_T i = 0; i <= PageCount; i++)
214 // {
215 // UINT64 CheckAddr = AlignedPage + (PAGE_SIZE * i);
216 // if (!CheckAddressValidityUsingTsx(CheckAddr))
217 // {
218 // //
219 // // Address is not valid
220 // //
221 // Result = FALSE;
222 //
223 // goto RestoreCr3;
224 // }
225 // }
226 // }
227
228 //
229 // We've realized that using TSX for address checking is not faster
230 // than the legacy memory checking (traversing the page-tables),
231 // based on our resultsm it's ~50 TSC clock cycles for a valid address
232 // and ~180 TSC clock cycles for an invalid address slower to use TSX
233 // for memory checking, that's why it is deprecated now
234 //
235
236 //
237 // Check if memory is safe and present
238 //
239 UINT64 AddressToCheck = (CHAR *)TargetAddress + Size - ((CHAR *)PAGE_ALIGN(TargetAddress));
240
241 if (AddressToCheck > PAGE_SIZE)
242 {
243 //
244 // Address should be accessed in more than one page
245 //
246 UINT64 ReadSize = AddressToCheck;
247
248 while (Size != 0)
249 {
250 ReadSize = (UINT64)PAGE_ALIGN(TargetAddress + PAGE_SIZE) - TargetAddress;
251
252 if (ReadSize == PAGE_SIZE && Size < PAGE_SIZE)
253 {
254 ReadSize = Size;
255 }
256
257 if (!MemoryMapperCheckIfPageIsPresentByCr3((PVOID)TargetAddress, GuestCr3))
258 {
259 //
260 // Address is not valid
261 //
262 Result = FALSE;
263
264 goto RestoreCr3;
265 }
266
267 /*
268 LogInfo("Addr From : %llx to Addr To : %llx | ReadSize : %llx\n",
269 TargetAddress,
270 TargetAddress + ReadSize,
271 ReadSize);
272 */
273
274 //
275 // Apply the changes to the next addresses (if any)
276 //
277 Size = (UINT32)(Size - ReadSize);
278 TargetAddress = TargetAddress + ReadSize;
279 }
280 }
281 else
282 {
283 if (!MemoryMapperCheckIfPageIsPresentByCr3((PVOID)TargetAddress, GuestCr3))
284 {
285 //
286 // Address is not valid
287 //
288 Result = FALSE;
289
290 goto RestoreCr3;
291 }
292 }
293
294 //
295 // If we've reached here, the address was valid
296 //
297 Result = TRUE;
298
299RestoreCr3:
300
301 //
302 // Move back to original cr3
303 //
304 CpuWriteCr3(OriginalCr3);
305
306Return:
307 return Result;
308}
BOOLEAN CheckAddressCanonicality(UINT64 VAddr, PBOOLEAN IsKernelAddress)
Checks if the address is canonical based on x86 processor's virtual address width or not.
Definition AddressCheck.c:66
_Use_decl_annotations_ BOOLEAN MemoryMapperCheckIfPageIsPresentByCr3(PVOID Va, CR3_TYPE TargetCr3)
This function checks if the page is mapped or not.
Definition MemoryMapper.c:418
ULONG_PTR CpuReadCr3(VOID)
Read CR3.
Definition PlatformIntrinsics.c:100
VOID CpuWriteCr3(ULONG_PTR Cr3Value)
Write CR3.
Definition PlatformIntrinsics.c:119
UCHAR BOOLEAN
Definition BasicTypes.h:35
void * PVOID
Definition BasicTypes.h:56
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
struct _CR3_TYPE CR3_TYPE
CR3 Structure.
unsigned int UINT32
Definition BasicTypes.h:54
char CHAR
Definition BasicTypes.h:33
IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCurrentProcessCr3()
Get cr3 of the target running process.
Definition Layout.c:55
IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCr3ByProcessId(UINT32 ProcessId)
Converts pid to kernel cr3.
Definition Layout.c:24
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80
#define PAGE_ALIGN(Va)
Aligning a page.
Definition common.h:86
UINT64 Flags
Definition BasicTypes.h:239

◆ CheckAddressCanonicality()

BOOLEAN CheckAddressCanonicality ( UINT64 VAddr,
PBOOLEAN IsKernelAddress )

Checks if the address is canonical based on x86 processor's virtual address width or not.

Parameters
VAddrvirtual address to check
IsKernelAddressFilled to show whether the address is a kernel address or user-address

IsKernelAddress wouldn't check for page attributes, it just checks the address convention in Windows

Returns
BOOLEAN
67{
68 UINT64 Addr = (UINT64)VAddr;
69 UINT64 MaxVirtualAddrLowHalf, MinVirtualAddressHighHalf;
70
71 //
72 // Get processor's address width for VA
73 //
74 UINT32 AddrWidth = g_CompatibilityCheck.VirtualAddressWidth;
75
76 //
77 // get max address in lower-half canonical addr space
78 // e.g. if width is 48, then 0x00007FFF_FFFFFFFF
79 //
80 MaxVirtualAddrLowHalf = ((UINT64)1ull << (AddrWidth - 1)) - 1;
81
82 //
83 // get min address in higher-half canonical addr space
84 // e.g., if width is 48, then 0xFFFF8000_00000000
85 //
86 MinVirtualAddressHighHalf = ~MaxVirtualAddrLowHalf;
87
88 //
89 // Check to see if the address in a canonical address
90 //
91 if ((Addr > MaxVirtualAddrLowHalf) && (Addr < MinVirtualAddressHighHalf))
92 {
93 *IsKernelAddress = FALSE;
94 return FALSE;
95 }
96
97 //
98 // Set whether it's a kernel address or not
99 //
100 if (MinVirtualAddressHighHalf < Addr)
101 {
102 *IsKernelAddress = TRUE;
103 }
104 else
105 {
106 *IsKernelAddress = FALSE;
107 }
108
109 return TRUE;
110}
COMPATIBILITY_CHECKS_STATUS g_CompatibilityCheck
Different attributes and compatibility checks of the current processor.
Definition GlobalVariables.h:26

◆ CheckAddressMaximumInstructionLength()

UINT32 CheckAddressMaximumInstructionLength ( PVOID Address)

This function returns the maximum instruction length that can be read from this address.

Parameters
Address
Returns
UINT32
346{
347 UINT64 SizeOfSafeBufferToRead = 0;
348
349 //
350 // Compute the amount of buffer we can read without problem
351 //
352 SizeOfSafeBufferToRead = (UINT64)Address & 0xfff;
353 SizeOfSafeBufferToRead += MAXIMUM_INSTR_SIZE;
354
355 if (SizeOfSafeBufferToRead >= PAGE_SIZE)
356 {
357 SizeOfSafeBufferToRead = SizeOfSafeBufferToRead - PAGE_SIZE;
358
359 //
360 // When we reached here, we're sure the instruction is on the boundary of a
361 // page table, so we have the maximum instruction length to read, but just
362 // to make sure that the instruction is not continued into two pages, we'll
363 // check the validity of the next page
364 //
365 if (CheckAccessValidityAndSafety((UINT64)Address + PAGE_SIZE, sizeof(CHAR)))
366 {
367 //
368 // Address is safe to be read from the next page, so we just extend it
369 // to the MAXIMUM_INSTR_SIZE
370 //
371 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE;
372 }
373 else
374 {
375 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE - SizeOfSafeBufferToRead;
376 }
377 }
378 else
379 {
380 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE;
381 }
382
383 return (UINT32)SizeOfSafeBufferToRead;
384}
BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:318
#define MAXIMUM_INSTR_SIZE
maximum instruction size in Intel
Definition Constants.h:470

◆ CheckAddressPhysical()

BOOLEAN CheckAddressPhysical ( UINT64 PAddr)

Checks if the physical address is correct or not based on physical address width.

Parameters
PAddrPhysical address to check
Returns
BOOLEAN
121{
122 UINT64 Addr = (UINT64)PAddr;
123 UINT64 MaxPA;
124
125 //
126 // Get processor's address width for PS
127 //
128 UINT32 AddrWidth = g_CompatibilityCheck.PhysicalAddressWidth;
129
130 //
131 // get max address for physical address
132 //
133 MaxPA = ((UINT64)1ull << (AddrWidth)) - 1;
134
135 // LogInfo("Max physical address: %llx", MaxPA);
136
137 //
138 // Check to see if the address in a canonical address
139 //
140 if (Addr > MaxPA)
141 {
142 return FALSE;
143 }
144
145 return TRUE;
146}

◆ CheckAddressValidityUsingTsx()

BOOLEAN CheckAddressValidityUsingTsx ( CHAR * Address)

This function checks whether the address is valid or not using Intel TSX.

Parameters
AddressAddress to check
ProcId
Returns
BOOLEAN Returns true if the address is valid; otherwise, false
25{
26 UINT32 Status = 0;
27 BOOLEAN Result = FALSE;
28 CHAR TempContent;
29
30 if ((Status = _xbegin()) == _XBEGIN_STARTED)
31 {
32 //
33 // Try to read the memory
34 //
35 TempContent = *(CHAR *)Address;
36 _xend();
37
38 //
39 // No error, address is valid
40 //
41 Result = TRUE;
42 }
43 else
44 {
45 //
46 // Address is not valid, it aborts the tsx rtm
47 //
48 Result = FALSE;
49 }
50
51 return Result;
52}
#define _XBEGIN_STARTED
Intel TSX Constants.
Definition Common.h:61