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

◆ 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 //
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
UINT32 VirtualAddressWidth
Definition CompatibilityChecks.h:30

◆ CheckAddressMaximumInstructionLength()

UINT32 CheckAddressMaximumInstructionLength ( PVOID Address)

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

Parameters
Address
Returns
UINT32
307{
308 UINT64 SizeOfSafeBufferToRead = 0;
309
310 //
311 // Compute the amount of buffer we can read without problem
312 //
313 SizeOfSafeBufferToRead = (UINT64)Address & 0xfff;
314 SizeOfSafeBufferToRead += MAXIMUM_INSTR_SIZE;
315
316 if (SizeOfSafeBufferToRead >= PAGE_SIZE)
317 {
318 SizeOfSafeBufferToRead = SizeOfSafeBufferToRead - PAGE_SIZE;
319
320 //
321 // When we reached here, we're sure the instruction is on the boundary of a
322 // page table, so we have the maximum instruction length to read, but just
323 // to make sure that the instruction is not continued into two pages, we'll
324 // check the validity of the next page
325 //
327 {
328 //
329 // Address is safe to be read from the next page, so we just extend it
330 // to the MAXIMUM_INSTR_SIZE
331 //
332 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE;
333 }
334 else
335 {
336 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE - SizeOfSafeBufferToRead;
337 }
338 }
339 else
340 {
341 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE;
342 }
343
344 return (UINT32)SizeOfSafeBufferToRead;
345}
BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:156
#define MAXIMUM_INSTR_SIZE
maximum instruction size in Intel
Definition Constants.h:468
UINT64 Address
Definition HyperDbgScriptImports.h:67

◆ 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 //
129
130 //
131 // get max address for physical address
132 //
133 MaxPA = ((UINT64)1ull << (AddrWidth - 1)) - 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}
UINT32 PhysicalAddressWidth
Definition CompatibilityChecks.h:31

◆ CheckAddressValidityUsingTsx()

BOOLEAN CheckAddressValidityUsingTsx ( CHAR * Address)

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

Parameters
AddressAddress to check
UINT32ProcId
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:213