HyperDbg Debugger
Loading...
Searching...
No Matches
DebuggerCommands.h File Reference

Commands for debugger. More...

Go to the source code of this file.

Functions

BOOLEAN DebuggerCommandReadRegisters (GUEST_REGS *Regs, PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest)
 read registers
BOOLEAN DebuggerCommandReadMemory (PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer, PSIZE_T ReturnSize)
 Read memory for different commands.
BOOLEAN DebuggerCommandReadMemoryVmxRoot (PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR *UserBuffer, UINT32 *ReturnSize)
 Read memory for different commands from vmxroot mode.
BOOLEAN DebuggerCommandEditMemoryVmxRoot (PDEBUGGER_EDIT_MEMORY EditMemRequest)
 Edit physical and virtual memory on vmxroot mode.
BOOLEAN DebuggerCommandBringPagein (PDEBUGGER_PAGE_IN_REQUEST PageinRequest)
 routines for the .pagein command
NTSTATUS DebuggerReadOrWriteMsr (PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UINT64 *UserBuffer, PSIZE_T ReturnSize)
 Perform rdmsr, wrmsr commands.
NTSTATUS DebuggerCommandEditMemory (PDEBUGGER_EDIT_MEMORY EditMemRequest)
 Edit physical and virtual memory.
NTSTATUS DebuggerCommandSearchMemory (PDEBUGGER_SEARCH_MEMORY SearchMemRequest)
 Start searching memory.
NTSTATUS DebuggerCommandFlush (PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest)
 Perform the flush requests to vmx-root and vmx non-root buffers.
NTSTATUS DebuggerCommandSignalExecutionState (PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL DebuggerFinishedExecutionRequest)
 Perform the command finished signal.
NTSTATUS DebuggerCommandSendMessage (PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER DebuggerSendUsermodeMessageRequest)
 Send the user-mode buffer to debugger.
NTSTATUS DebuggerCommandSendGeneralBufferToDebugger (PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER DebuggeeBufferRequest)
 Send general buffers from the debuggee to the debugger.
NTSTATUS DebuggerCommandReservePreallocatedPools (PDEBUGGER_PREALLOC_COMMAND PreallocRequest)
 Reserve and allocate pre-allocated buffers.
NTSTATUS DebuggerCommandPreactivateFunctionality (PDEBUGGER_PREACTIVATE_COMMAND PreactivateRequest)
 Preactivate a special functionality.
BOOLEAN SearchAddressWrapper (PUINT64 AddressToSaveResults, PDEBUGGER_SEARCH_MEMORY SearchMemRequest, UINT64 StartAddress, UINT64 EndAddress, BOOLEAN IsDebuggeePaused, PUINT32 CountOfMatchedCases)
 The wrapper to check for validity of addresses and call the search routines for both physical and virtual memory.

Detailed Description

Commands for debugger.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)

This file contains general commands that are implemented for debugger These command mostly start without "!" or "."

Version
0.1
Date
2020-04-10

Function Documentation

◆ DebuggerCommandBringPagein()

BOOLEAN DebuggerCommandBringPagein ( PDEBUGGER_PAGE_IN_REQUEST PageinRequest)

routines for the .pagein command

Parameters
PageinRequest
Returns
BOOLEAN
1533{
1534 //
1535 // *** Perform the injection here ***
1536 //
1537 LogInfo("Page-request is received!");
1538
1539 //
1540 // Adjust the flags for showing the successful #PF injection
1541 //
1543
1544 return TRUE;
1545}
#define TRUE
Definition BasicTypes.h:114
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71
UINT32 KernelStatus
Definition RequestStructures.h:109

◆ DebuggerCommandEditMemory()

NTSTATUS DebuggerCommandEditMemory ( PDEBUGGER_EDIT_MEMORY EditMemRequest)

Edit physical and virtual memory.

Parameters
EditMemRequestedit memory request
Returns
NTSTATUS
491{
492 UINT32 LengthOfEachChunk = 0;
493 PVOID DestinationAddress = 0;
494 PVOID SourceAddress = 0;
495
496 //
497 // set chunk size in each modification
498 //
499 if (EditMemRequest->ByteSize == EDIT_BYTE)
500 {
501 LengthOfEachChunk = 1;
502 }
503 else if (EditMemRequest->ByteSize == EDIT_DWORD)
504 {
505 LengthOfEachChunk = 4;
506 }
507 else if (EditMemRequest->ByteSize == EDIT_QWORD)
508 {
509 LengthOfEachChunk = 8;
510 }
511 else
512 {
513 //
514 // Invalid parameter
515 //
517 return STATUS_UNSUCCESSFUL;
518 }
519
520 //
521 // Check if address is valid or not valid (virtual address)
522 //
523 if (EditMemRequest->MemoryType == EDIT_VIRTUAL_MEMORY)
524 {
525 if (EditMemRequest->ProcessId == HANDLE_TO_UINT32(PsGetCurrentProcessId()) && VirtualAddressToPhysicalAddress((PVOID)EditMemRequest->Address) == 0)
526 {
527 //
528 // It's an invalid address in current process
529 //
531 return STATUS_UNSUCCESSFUL;
532 }
533 else if (VirtualAddressToPhysicalAddressByProcessId((PVOID)EditMemRequest->Address, EditMemRequest->ProcessId) == 0)
534 {
535 //
536 // It's an invalid address in another process
537 //
539 return STATUS_UNSUCCESSFUL;
540 }
541
542 //
543 // Edit the memory
544 //
545 for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
546 {
547 DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
548 SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
549
550 //
551 // Instead of directly accessing the memory we use the MemoryMapperWriteMemorySafe
552 // It is because the target page might be read-only so we can make it writable
553 //
554
555 // RtlCopyBytes(DestinationAddress, SourceAddress, LengthOfEachChunk);
556 MemoryMapperWriteMemoryUnsafe((UINT64)DestinationAddress, SourceAddress, LengthOfEachChunk, EditMemRequest->ProcessId);
557 }
558 }
559 else if (EditMemRequest->MemoryType == EDIT_PHYSICAL_MEMORY)
560 {
561 //
562 // Check whether the physical address
563 //
564 if (!CheckAddressPhysical(EditMemRequest->Address))
565 {
566 EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS;
567 return STATUS_UNSUCCESSFUL;
568 }
569
570 //
571 // Edit the physical memory
572 //
573 for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
574 {
575 DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
576 SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
577
578 // MemoryMapperWriteMemorySafeByPhysicalAddress((UINT64)DestinationAddress, (UINT64)SourceAddress, LengthOfEachChunk);
579 // WritePhysicalMemoryUsingMapIoSpace((PVOID)SourceAddress, (PVOID)DestinationAddress, LengthOfEachChunk);
580
581 if (MemoryManagerWritePhysicalMemoryNormal((PVOID)DestinationAddress, (PVOID)SourceAddress, (SIZE_T)LengthOfEachChunk) == FALSE)
582 {
583 EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS;
584 return STATUS_UNSUCCESSFUL;
585 }
586 }
587 }
588 else
589 {
590 //
591 // Invalid parameter
592 //
594 return STATUS_UNSUCCESSFUL;
595 }
596
597 //
598 // Set the results
599 //
601
602 return STATUS_SUCCESS;
603}
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
#define STATUS_UNSUCCESSFUL
Definition Windows.h:172
void * PVOID
Definition BasicTypes.h:56
#define FALSE
Definition BasicTypes.h:113
unsigned int UINT32
Definition BasicTypes.h:54
#define DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS
error, an invalid address is specified based on another process's cr3 in !e* or e* commands
Definition ErrorCodes.h:114
#define DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS
error, an invalid address is specified based on current cr3 in !e* or e* commands
Definition ErrorCodes.h:106
#define DEBUGGER_ERROR_INVALID_ADDRESS
error, invalid address specified for debugger
Definition ErrorCodes.h:63
#define DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER
error, invalid parameters in !e* e* commands
Definition ErrorCodes.h:99
@ EDIT_PHYSICAL_MEMORY
Definition RequestStructures.h:483
@ EDIT_VIRTUAL_MEMORY
Definition RequestStructures.h:482
@ EDIT_QWORD
Definition RequestStructures.h:494
@ EDIT_DWORD
Definition RequestStructures.h:493
@ EDIT_BYTE
Definition RequestStructures.h:492
#define SIZEOF_DEBUGGER_EDIT_MEMORY
Definition RequestStructures.h:474
IMPORT_EXPORT_VMM BOOLEAN MemoryManagerWritePhysicalMemoryNormal(PVOID TargetAddress, PVOID UserBuffer, SIZE_T Size)
Write process memory.
Definition MemoryManager.c:232
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperWriteMemoryUnsafe(_Inout_ UINT64 Destination, _In_ PVOID Source, _In_ SIZE_T SizeToWrite, _In_ UINT32 TargetProcessId)
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddress(_In_ PVOID VirtualAddress)
Converts Virtual Address to Physical Address.
Definition Conversion.c:154
IMPORT_EXPORT_VMM BOOLEAN CheckAddressPhysical(UINT64 PAddr)
Checks if the physical address is correct or not based on physical address width.
Definition AddressCheck.c:120
IMPORT_EXPORT_VMM UINT64 VirtualAddressToPhysicalAddressByProcessId(_In_ PVOID VirtualAddress, _In_ UINT32 ProcessId)
UINT32 Result
Definition RequestStructures.h:503
UINT64 Address
Definition RequestStructures.h:504
DEBUGGER_EDIT_MEMORY_TYPE MemoryType
Definition RequestStructures.h:506
UINT32 CountOf64Chunks
Definition RequestStructures.h:508
UINT32 ProcessId
Definition RequestStructures.h:505
DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize
Definition RequestStructures.h:507

◆ DebuggerCommandEditMemoryVmxRoot()

BOOLEAN DebuggerCommandEditMemoryVmxRoot ( PDEBUGGER_EDIT_MEMORY EditMemRequest)

Edit physical and virtual memory on vmxroot mode.

Parameters
EditMemRequestedit memory request
Returns
NTSTATUS
613{
614 UINT32 LengthOfEachChunk = 0;
615 PVOID DestinationAddress = 0;
616 PVOID SourceAddress = 0;
617
618 //
619 // THIS FUNCTION IS SAFE TO BE CALLED FROM VMX-ROOT
620 //
621
622 //
623 // set chunk size in each modification
624 //
625 if (EditMemRequest->ByteSize == EDIT_BYTE)
626 {
627 LengthOfEachChunk = 1;
628 }
629 else if (EditMemRequest->ByteSize == EDIT_DWORD)
630 {
631 LengthOfEachChunk = 4;
632 }
633 else if (EditMemRequest->ByteSize == EDIT_QWORD)
634 {
635 LengthOfEachChunk = 8;
636 }
637 else
638 {
639 //
640 // Invalid parameter
641 //
643 return FALSE;
644 }
645
646 if (EditMemRequest->MemoryType == EDIT_VIRTUAL_MEMORY)
647 {
648 //
649 // Check whether the virtual memory is available in the current
650 // memory layout and also is present in the RAM
651 //
652 if (!CheckAccessValidityAndSafety(EditMemRequest->Address,
653 EditMemRequest->ByteSize * EditMemRequest->CountOf64Chunks))
654 {
655 EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS;
656 return FALSE;
657 }
658
659 //
660 // Edit the memory
661 //
662 for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
663 {
664 DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
665 SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
666
667 //
668 // Instead of directly accessing the memory we use the MemoryMapperWriteMemorySafeOnTargetProcess
669 // It is because the target page might be read-only so we can make it writable
670 //
671
672 // RtlCopyBytes(DestinationAddress, SourceAddress, LengthOfEachChunk);
673 MemoryMapperWriteMemorySafeOnTargetProcess((UINT64)DestinationAddress, SourceAddress, LengthOfEachChunk);
674 }
675 }
676 else if (EditMemRequest->MemoryType == EDIT_PHYSICAL_MEMORY)
677 {
678 //
679 // Check whether the physical address
680 //
681 if (!CheckAddressPhysical(EditMemRequest->Address))
682 {
683 EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS;
684 return FALSE;
685 }
686
687 //
688 // Edit the physical memory
689 //
690 for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
691 {
692 DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
693 SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
694
695 MemoryMapperWriteMemorySafeByPhysicalAddress((UINT64)DestinationAddress, (UINT64)SourceAddress, LengthOfEachChunk);
696 }
697 }
698 else
699 {
700 //
701 // Invalid parameter
702 //
704 return FALSE;
705 }
706
707 //
708 // Set the results
709 //
711 return TRUE;
712}
IMPORT_EXPORT_VMM BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:318
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperWriteMemorySafeOnTargetProcess(_Inout_ UINT64 Destination, _In_ PVOID Source, _In_ SIZE_T Size)
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperWriteMemorySafeByPhysicalAddress(_Inout_ UINT64 DestinationPa, _In_ UINT64 Source, _In_ SIZE_T SizeToWrite)

◆ DebuggerCommandFlush()

NTSTATUS DebuggerCommandFlush ( PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest)

Perform the flush requests to vmx-root and vmx non-root buffers.

Parameters
DebuggerFlushBuffersRequestRequest to flush the buffers
Returns
NTSTATUS
1293{
1294 //
1295 // We try to flush buffers for both vmx-root and regular kernel buffer
1296 //
1297 DebuggerFlushBuffersRequest->CountOfMessagesThatSetAsReadFromVmxRoot = LogMarkAllAsRead(TRUE);
1299 DebuggerFlushBuffersRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1300
1301 return STATUS_SUCCESS;
1302}
IMPORT_EXPORT_HYPERLOG UINT32 LogMarkAllAsRead(BOOLEAN IsVmxRoot)
Mark all buffers as read.
Definition Logging.c:569
UINT32 CountOfMessagesThatSetAsReadFromVmxRoot
Definition RequestStructures.h:321
UINT32 CountOfMessagesThatSetAsReadFromVmxNonRoot
Definition RequestStructures.h:322
UINT32 KernelStatus
Definition RequestStructures.h:320

◆ DebuggerCommandPreactivateFunctionality()

NTSTATUS DebuggerCommandPreactivateFunctionality ( PDEBUGGER_PREACTIVATE_COMMAND PreactivateRequest)

Preactivate a special functionality.

Parameters
PreactivateRequestRequest details of preactivation
Returns
NTSTATUS
1501{
1502 switch (PreactivateRequest->Type)
1503 {
1505
1506 //
1507 // Request for enabling the mode mechanism
1508 //
1510
1511 break;
1512
1513 default:
1514
1516 return STATUS_UNSUCCESSFUL;
1517 }
1518
1519 PreactivateRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1520
1521 return STATUS_SUCCESS;
1522}
#define DEBUGGER_ERROR_COULD_NOT_FIND_PREACTIVATION_TYPE
error, could not find the type of preactivation
Definition ErrorCodes.h:507
@ DEBUGGER_PREACTIVATE_COMMAND_TYPE_MODE
Definition RequestStructures.h:217
IMPORT_EXPORT_VMM BOOLEAN ConfigureInitializeExecTrapOnAllProcessors()
routines for initializing user-mode, kernel-mode exec trap
Definition Configuration.c:32
UINT32 KernelStatus
Definition RequestStructures.h:231
DEBUGGER_PREACTIVATE_COMMAND_TYPE Type
Definition RequestStructures.h:230

◆ DebuggerCommandReadMemory()

BOOLEAN DebuggerCommandReadMemory ( PDEBUGGER_READ_MEMORY ReadMemRequest,
PVOID UserBuffer,
PSIZE_T ReturnSize )

Read memory for different commands.

Parameters
ReadMemRequestrequest structure for reading memory
UserBufferuser buffer to copy the memory
ReturnSizesize that should be returned to user mode buffers
Returns
BOOLEAN
75{
76 UINT32 Pid;
77 UINT32 Size;
78 UINT64 Address;
80 BOOLEAN Is32BitProcess = FALSE;
81
82 //
83 // Adjust the parameters
84 //
85 Pid = ReadMemRequest->Pid;
86 Size = ReadMemRequest->Size;
87 Address = ReadMemRequest->Address;
88 MemType = ReadMemRequest->MemoryType;
89
90 if (Size && Address != (UINT64)NULL)
91 {
93 (PVOID)Address,
94 MemType,
95 (PVOID)UserBuffer,
96 Size,
97 ReturnSize))
98 {
99 //
100 // Reading memory was successful
101 //
102
103 //
104 // *** Now, we check whether this a disassembly request for a virtual address
105 // or not, if so, we'll detect whether the target process is 32-bit or 64-bit ***
106 //
107
108 //
109 // Check if the address is on a 32-bit mode process or not (just in case of disassembling)
110 //
111 if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->GetAddressMode)
112 {
113 //
114 // Check if the address is in the canonical range for kernel space
115 //
116 if (ReadMemRequest->Address >= 0xFFFF800000000000 && ReadMemRequest->Address <= 0xFFFFFFFFFFFFFFFF)
117 {
118 //
119 // The address is in the range of canonical kernel space, so it's 64-bit process
120 //
122 }
123 else
124 {
125 //
126 // The address is in the user-mode and the memory type is a virtual address
127 // for disassembly, so we have to query whether the target process is a
128 // 32-bit process or a 64-bit process
129 //
130 if (UserAccessIsWow64Process((HANDLE)ReadMemRequest->Pid, &Is32BitProcess))
131 {
132 if (Is32BitProcess)
133 {
135 }
136 else
137 {
139 }
140 }
141 else
142 {
143 //
144 // We couldn't determine the type of process, let's assume that it's a
145 // 64-bit process by default
146 //
148 }
149 }
150 }
151
152 //
153 // Anyway, the read was successful
154 //
156 return TRUE;
157 }
158 else
159 {
160 //
161 // Reading memory was not successful
162 //
164 return FALSE;
165 }
166 }
167 else
168 {
169 //
170 // Parameters are invalid
171 //
173 return FALSE;
174 }
175}
BOOLEAN UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit.
Definition UserAccess.c:753
UCHAR BOOLEAN
Definition BasicTypes.h:35
#define DEBUGGER_ERROR_READING_MEMORY_INVALID_PARAMETER
error, for reading from memory in case of invalid parameters
Definition ErrorCodes.h:405
enum _DEBUGGER_READ_MEMORY_TYPE DEBUGGER_READ_MEMORY_TYPE
different type of addresses
@ DEBUGGER_READ_ADDRESS_MODE_32_BIT
Definition RequestStructures.h:265
@ DEBUGGER_READ_ADDRESS_MODE_64_BIT
Definition RequestStructures.h:266
@ DEBUGGER_READ_VIRTUAL_ADDRESS
Definition RequestStructures.h:256
IMPORT_EXPORT_VMM BOOLEAN MemoryManagerReadProcessMemoryNormal(HANDLE PID, PVOID Address, DEBUGGER_READ_MEMORY_TYPE MemType, PVOID UserBuffer, SIZE_T Size, PSIZE_T ReturnSize)
Read process memory.
Definition MemoryManager.c:86
UINT32 KernelStatus
Definition RequestStructures.h:301
UINT32 Size
Definition RequestStructures.h:295
UINT32 Pid
Definition RequestStructures.h:293
DEBUGGER_READ_MEMORY_ADDRESS_MODE AddressMode
Definition RequestStructures.h:297
BOOLEAN GetAddressMode
Definition RequestStructures.h:296
DEBUGGER_READ_MEMORY_TYPE MemoryType
Definition RequestStructures.h:298
UINT64 Address
Definition RequestStructures.h:294

◆ DebuggerCommandReadMemoryVmxRoot()

BOOLEAN DebuggerCommandReadMemoryVmxRoot ( PDEBUGGER_READ_MEMORY ReadMemRequest,
UCHAR * UserBuffer,
UINT32 * ReturnSize )

Read memory for different commands from vmxroot mode.

Parameters
ReadMemRequestrequest structure for reading memory
UserBufferuser buffer to copy the memory
ReturnSizesize that should be returned to user mode buffers
Returns
BOOLEAN
187{
188 UINT32 Pid;
189 UINT32 Size;
190 UINT64 Address;
191 UINT64 OffsetInUserBuffer;
193 BOOLEAN Is32BitProcess = FALSE;
194 PLIST_ENTRY TempList = 0;
195
196 Pid = ReadMemRequest->Pid;
197 Size = ReadMemRequest->Size;
198 Address = ReadMemRequest->Address;
199 MemType = ReadMemRequest->MemoryType;
200
201 //
202 // read memory safe
203 //
204 if (MemType == DEBUGGER_READ_PHYSICAL_ADDRESS)
205 {
206 //
207 // Check whether the physical memory is valid or not
208 //
209 if (!CheckAddressPhysical(Address))
210 {
212 return FALSE;
213 }
214
215 MemoryMapperReadMemorySafeByPhysicalAddress(Address, (UINT64)UserBuffer, Size);
216 }
217 else if (MemType == DEBUGGER_READ_VIRTUAL_ADDRESS)
218 {
219 //
220 // Check whether the virtual memory is available in the current
221 // memory layout and also is present in the RAM
222 //
223 if (!CheckAccessValidityAndSafety(Address, Size))
224 {
226 return FALSE;
227 }
228
229 //
230 // Read memory safely
231 //
232 MemoryMapperReadMemorySafeOnTargetProcess(Address, UserBuffer, Size);
233
234 //
235 // Check if the target memory is filled with breakpoint of the 'bp' commands
236 // if the memory is changed due to this command, then we'll changes it to
237 // the previous byte
238 //
239
240 //
241 // Iterate through the breakpoint list
242 //
243 TempList = &g_BreakpointsListHead;
244
245 while (&g_BreakpointsListHead != TempList->Flink)
246 {
247 TempList = TempList->Flink;
248 PDEBUGGEE_BP_DESCRIPTOR CurrentBreakpointDesc = CONTAINING_RECORD(TempList, DEBUGGEE_BP_DESCRIPTOR, BreakpointsList);
249
250 if (CurrentBreakpointDesc->Address >= Address && CurrentBreakpointDesc->Address <= Address + Size)
251 {
252 //
253 // The address is found, we have to swap the byte if the target
254 // byte is 0xcc
255 //
256
257 //
258 // Find the address location at user buffer
259 //
260 OffsetInUserBuffer = CurrentBreakpointDesc->Address - Address;
261
262 if (UserBuffer[OffsetInUserBuffer] == 0xcc)
263 {
264 UserBuffer[OffsetInUserBuffer] = CurrentBreakpointDesc->PreviousByte;
265 }
266 }
267 }
268 }
269 else
270 {
272 return FALSE;
273 }
274
275 //
276 // Check if the address is on a 32-bit mode process or not (just in case of disassembling)
277 //
278 if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->GetAddressMode)
279 {
280 //
281 // Check if the address is in the canonical range for kernel space
282 //
283 if (ReadMemRequest->Address >= 0xFFFF800000000000 && ReadMemRequest->Address <= 0xFFFFFFFFFFFFFFFF)
284 {
285 //
286 // The address is in the range of canonical kernel space, so it's 64-bit process
287 //
289 }
290 else
291 {
292 //
293 // The address is in the user-mode and the memory type is a virtual address
294 // for disassembly, so we have to query whether the target process is a
295 // 32-bit process or a 64-bit process
296 //
297 if (UserAccessIsWow64ProcessByEprocess(PsGetCurrentProcess(), &Is32BitProcess))
298 {
299 if (Is32BitProcess)
300 {
302 }
303 else
304 {
306 }
307 }
308 else
309 {
310 //
311 // We couldn't determine the type of process, let's assume that it's a
312 // 64-bit process by default
313 //
315 }
316 }
317 }
318
319 //
320 // Set the final status of memory read as it was successful
321 //
323 *ReturnSize = Size;
324
325 return TRUE;
326}
BOOLEAN UserAccessIsWow64ProcessByEprocess(PEPROCESS SourceProcess, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit by using EPROCESS pointer.
Definition UserAccess.c:711
#define DEBUGGER_ERROR_MEMORY_TYPE_INVALID
error, memory type is invalid
Definition ErrorCodes.h:214
#define DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS
error, invalid physical address
Definition ErrorCodes.h:540
@ DEBUGGER_READ_PHYSICAL_ADDRESS
Definition RequestStructures.h:255
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafeByPhysicalAddress(_In_ UINT64 PaAddressToRead, _Inout_ UINT64 BufferToSaveMemory, _In_ SIZE_T SizeToRead)
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafeOnTargetProcess(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead)
LIST_ENTRY g_BreakpointsListHead
List header of breakpoints for debugger-mode.
Definition Global.h:139
struct _DEBUGGEE_BP_DESCRIPTOR DEBUGGEE_BP_DESCRIPTOR
The structure of storing breakpoints.
struct _DEBUGGEE_BP_DESCRIPTOR * PDEBUGGEE_BP_DESCRIPTOR
#define CONTAINING_RECORD(address, type, field)
Definition nt-list.h:36
BYTE PreviousByte
Definition State.h:82
UINT64 Address
Definition State.h:76

◆ DebuggerCommandReadRegisters()

BOOLEAN DebuggerCommandReadRegisters ( GUEST_REGS * Regs,
PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest )

read registers

Parameters
Regs
ReadRegisterRequest
Returns
BOOLEAN
25{
26 GUEST_EXTRA_REGISTERS ERegs = {0};
27
28 if (ReadRegisterRequest->RegisterId == DEBUGGEE_SHOW_ALL_REGISTERS)
29 {
30 //
31 // Add General purpose registers
32 //
33 memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)),
34 Regs,
35 sizeof(GUEST_REGS));
36
37 //
38 // Read Extra registers
39 //
48
49 //
50 // copy at the end of ReadRegisterRequest structure
51 //
52 memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)),
53 &ERegs,
54 sizeof(GUEST_EXTRA_REGISTERS));
55 }
56 else
57 {
58 ReadRegisterRequest->Value = DebuggerGetRegValueWrapper(Regs, ReadRegisterRequest->RegisterId);
59 }
60
61 return TRUE;
62}
UINT64 DebuggerGetRegValueWrapper(PGUEST_REGS GuestRegs, UINT32 RegId)
A wrapper for GetRegValue() in script-engine.
Definition Debugger.c:21
unsigned short UINT16
Definition BasicTypes.h:53
char CHAR
Definition BasicTypes.h:33
#define DEBUGGEE_SHOW_ALL_REGISTERS
for reading all registers in r command.
Definition Constants.h:793
struct _DEBUGGEE_REGISTER_READ_DESCRIPTION DEBUGGEE_REGISTER_READ_DESCRIPTION
Register Descriptor Structure to use in r command.
@ REGISTER_CS
Definition ScriptEngineCommonDefinitions.h:396
@ REGISTER_RIP
Definition ScriptEngineCommonDefinitions.h:418
@ REGISTER_FS
Definition ScriptEngineCommonDefinitions.h:394
@ REGISTER_SS
Definition ScriptEngineCommonDefinitions.h:397
@ REGISTER_GS
Definition ScriptEngineCommonDefinitions.h:395
@ REGISTER_ES
Definition ScriptEngineCommonDefinitions.h:393
@ REGISTER_RFLAGS
Definition ScriptEngineCommonDefinitions.h:398
@ REGISTER_DS
Definition ScriptEngineCommonDefinitions.h:392
UINT32 RegisterId
Definition RequestStructures.h:1617
UINT64 Value
Definition RequestStructures.h:1618
struct for extra registers
Definition BasicTypes.h:208
UINT16 FS
Definition BasicTypes.h:211
UINT16 ES
Definition BasicTypes.h:213
UINT64 RFLAGS
Definition BasicTypes.h:215
UINT64 RIP
Definition BasicTypes.h:216
UINT16 DS
Definition BasicTypes.h:210
UINT16 SS
Definition BasicTypes.h:214
UINT16 GS
Definition BasicTypes.h:212
UINT16 CS
Definition BasicTypes.h:209
Definition BasicTypes.h:136

◆ DebuggerCommandReservePreallocatedPools()

NTSTATUS DebuggerCommandReservePreallocatedPools ( PDEBUGGER_PREALLOC_COMMAND PreallocRequest)

Reserve and allocate pre-allocated buffers.

Parameters
PreallocRequestRequest details of needed buffers to be reserved
Returns
NTSTATUS
1377{
1378 switch (PreallocRequest->Type)
1379 {
1381
1382 //
1383 // Request pages to be allocated for thread interception mechanism
1384 //
1386 PreallocRequest->Count,
1388
1389 break;
1390
1392
1393 //
1394 // Perform the allocations for the '!monitor' command
1395 //
1397
1398 break;
1399
1401
1402 //
1403 // Perform the allocations for the '!epthook' command
1404 //
1406
1407 break;
1408
1410
1411 //
1412 // All the prealloc requests of regular EPT hooks are needed for the '!epthook2'
1413 //
1415
1416 break;
1417
1419
1420 //
1421 // Request pages to be allocated for regular instant events
1422 //
1424 PreallocRequest->Count,
1426
1427 //
1428 // Request pages to be allocated for regular instant events's actions
1429 //
1431 PreallocRequest->Count,
1433
1434 break;
1435
1437
1438 //
1439 // Request pages to be allocated for big instant events
1440 //
1442 PreallocRequest->Count,
1444
1445 //
1446 // Request pages to be allocated for big instant events's actions
1447 //
1449 PreallocRequest->Count,
1451
1452 break;
1453
1455
1456 //
1457 // Request pages to be allocated for regular safe buffer ($buffer) for events
1458 //
1460 PreallocRequest->Count,
1462
1463 break;
1464
1466
1467 //
1468 // Request pages to be allocated for big safe buffer ($buffer) for events
1469 //
1471 PreallocRequest->Count,
1473
1474 break;
1475
1476 default:
1477
1479 return STATUS_UNSUCCESSFUL;
1480 }
1481
1482 //
1483 // Invalidate and perform the allocations as we're in PASSIVE_LEVEL
1484 //
1486
1488
1489 return STATUS_SUCCESS;
1490}
BOOLEAN PoolManagerCheckAndPerformAllocationAndDeallocation()
This function performs allocations from VMX non-root based on g_RequestNewAllocation.
Definition PoolManager.c:320
BOOLEAN PoolManagerRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
Request to allocate new buffers.
Definition PoolManager.c:436
struct _USERMODE_DEBUGGING_THREAD_HOLDER USERMODE_DEBUGGING_THREAD_HOLDER
The holder for detail of each thread in process.
#define BIG_INSTANT_EVENT_ACTION_BUFFER
Pre-allocated size for a big action + custom code or script buffer.
Definition Constants.h:308
#define REGULAR_INSTANT_EVENT_REQUESTED_SAFE_BUFFER
Pre-allocated size for a regular requested safe buffer.
Definition Constants.h:314
#define REGULAR_INSTANT_EVENT_ACTION_BUFFER
Pre-allocated size for a regular action + custom code or script buffer.
Definition Constants.h:302
#define REGULAR_INSTANT_EVENT_CONDITIONAL_BUFFER
Pre-allocated size for a regular event + conditions buffer.
Definition Constants.h:290
#define BIG_INSTANT_EVENT_CONDITIONAL_BUFFER
Pre-allocated size for a big event + conditions buffer.
Definition Constants.h:296
#define BIG_INSTANT_EVENT_REQUESTED_SAFE_BUFFER
Pre-allocated size for a big requested safe buffer.
Definition Constants.h:320
@ PROCESS_THREAD_HOLDER
Definition DataTypes.h:79
@ INSTANT_REGULAR_SAFE_BUFFER_FOR_EVENTS
Definition DataTypes.h:92
@ INSTANT_BIG_SAFE_BUFFER_FOR_EVENTS
Definition DataTypes.h:93
@ INSTANT_BIG_EVENT_BUFFER
Definition DataTypes.h:85
@ INSTANT_BIG_EVENT_ACTION_BUFFER
Definition DataTypes.h:87
@ INSTANT_REGULAR_EVENT_ACTION_BUFFER
Definition DataTypes.h:86
@ INSTANT_REGULAR_EVENT_BUFFER
Definition DataTypes.h:84
#define DEBUGGER_ERROR_COULD_NOT_FIND_ALLOCATION_TYPE
error, could not find the type of allocation
Definition ErrorCodes.h:282
@ DEBUGGER_PREALLOC_COMMAND_TYPE_MONITOR
Definition RequestStructures.h:184
@ DEBUGGER_PREALLOC_COMMAND_TYPE_EPTHOOK2
Definition RequestStructures.h:186
@ DEBUGGER_PREALLOC_COMMAND_TYPE_BIG_EVENT
Definition RequestStructures.h:188
@ DEBUGGER_PREALLOC_COMMAND_TYPE_REGULAR_EVENT
Definition RequestStructures.h:187
@ DEBUGGER_PREALLOC_COMMAND_TYPE_THREAD_INTERCEPTION
Definition RequestStructures.h:183
@ DEBUGGER_PREALLOC_COMMAND_TYPE_BIG_SAFE_BUFFER
Definition RequestStructures.h:190
@ DEBUGGER_PREALLOC_COMMAND_TYPE_REGULAR_SAFE_BUFFER
Definition RequestStructures.h:189
@ DEBUGGER_PREALLOC_COMMAND_TYPE_EPTHOOK
Definition RequestStructures.h:185
IMPORT_EXPORT_VMM VOID ConfigureEptHookAllocateExtraHookingPagesForMemoryMonitorsAndExecEptHooks(UINT32 Count)
Allocate (reserve) extra pages for storing details of page hooks for memory monitor and regular hidde...
Definition Configuration.c:229
IMPORT_EXPORT_VMM VOID ConfigureEptHookReservePreallocatedPoolsForEptHooks(UINT32 Count)
Allocate (reserve) pages for storing EPT hooks page hooks.
Definition Configuration.c:241
DEBUGGER_PREALLOC_COMMAND_TYPE Type
Definition RequestStructures.h:203
UINT32 KernelStatus
Definition RequestStructures.h:205
UINT32 Count
Definition RequestStructures.h:204

◆ DebuggerCommandSearchMemory()

NTSTATUS DebuggerCommandSearchMemory ( PDEBUGGER_SEARCH_MEMORY SearchMemRequest)

Start searching memory.

Parameters
SearchMemRequestRequest to search memory
Returns
NTSTATUS
1192{
1193 PUINT64 SearchResultsStorage = NULL;
1194 PUINT64 UsermodeBuffer = NULL;
1195 UINT64 AddressFrom = 0;
1196 UINT64 AddressTo = 0;
1197 UINT64 CurrentValue = 0;
1198 UINT32 ResultsIndex = 0;
1199 UINT32 CountOfResults = 0;
1200
1201 //
1202 // Check if process id is valid or not
1203 //
1204 if (SearchMemRequest->ProcessId != HANDLE_TO_UINT32(PsGetCurrentProcessId()) && !CommonIsProcessExist(SearchMemRequest->ProcessId))
1205 {
1206 return STATUS_INVALID_PARAMETER;
1207 }
1208
1209 //
1210 // User-mode buffer is same as SearchMemRequest
1211 //
1212 UsermodeBuffer = (UINT64 *)SearchMemRequest;
1213
1214 //
1215 // We store the user-mode data in a separate variable because
1216 // we will use them later when we Zeroed the SearchMemRequest
1217 //
1218 AddressFrom = SearchMemRequest->Address;
1219 AddressTo = SearchMemRequest->Address + SearchMemRequest->Length;
1220
1221 //
1222 // We support up to MaximumSearchResults search results
1223 //
1224 SearchResultsStorage = PlatformMemAllocateZeroedNonPagedPool(MaximumSearchResults * sizeof(UINT64));
1225
1226 if (SearchResultsStorage == NULL)
1227 {
1228 //
1229 // Not enough memory
1230 //
1231 return STATUS_INSUFFICIENT_RESOURCES;
1232 }
1233
1234 //
1235 // Call the wrapper
1236 //
1237 SearchAddressWrapper(SearchResultsStorage, SearchMemRequest, AddressFrom, AddressTo, FALSE, &CountOfResults);
1238
1239 //
1240 // In this point, we to store the results (if any) to the user-mode
1241 // buffer SearchMemRequest itself is the user-mode buffer and we also
1242 // checked from the previous function that the output buffer is at
1243 // least SearchMemRequest bigger or equal to MaximumSearchResults * sizeof(UINT64)
1244 // so we need to clear everything here, and also we should keep in mind that
1245 // SearchMemRequest is no longer valid
1246 //
1247 RtlZeroMemory(SearchMemRequest, MaximumSearchResults * sizeof(UINT64));
1248
1249 //
1250 // It's time to move the results from our temporary buffer to the user-mode
1251 // buffer, also there is something that we should check and that's the fact
1252 // that we used aligned page addresses so the results should be checked to
1253 // see whether the results are between the user's entered addresses or not
1254 //
1255 for (SIZE_T i = 0; i < MaximumSearchResults; i++)
1256 {
1257 CurrentValue = SearchResultsStorage[i];
1258
1259 if (CurrentValue == (UINT64)NULL)
1260 {
1261 //
1262 // Nothing left to move
1263 //
1264 break;
1265 }
1266
1267 if (CurrentValue >= AddressFrom && CurrentValue <= AddressTo)
1268 {
1269 //
1270 // Move the variable
1271 //
1272 UsermodeBuffer[ResultsIndex] = CurrentValue;
1273 ResultsIndex++;
1274 }
1275 }
1276
1277 //
1278 // Free the results pool
1279 //
1280 PlatformMemFreePool(SearchResultsStorage);
1281
1282 return STATUS_SUCCESS;
1283}
BOOLEAN SearchAddressWrapper(PUINT64 AddressToSaveResults, PDEBUGGER_SEARCH_MEMORY SearchMemRequest, UINT64 StartAddress, UINT64 EndAddress, BOOLEAN IsDebuggeePaused, PUINT32 CountOfMatchedCases)
The wrapper to check for validity of addresses and call the search routines for both physical and vir...
Definition DebuggerCommands.c:1019
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocates zeroed non-paged pool memory.
Definition PlatformMem.c:248
PVOID PlatformMemFreePool(PVOID BufferAddress)
Frees a memory pool.
Definition PlatformMem.c:269
#define MaximumSearchResults
maximum results that will be returned by !s* s* command
Definition Constants.h:516
BOOLEAN CommonIsProcessExist(UINT32 ProcId)
Checks whether the process with ProcId exists or not.
Definition Common.c:24
NULL()
Definition test-case-generator.py:530
UINT64 Length
Definition RequestStructures.h:548
UINT32 ProcessId
Definition RequestStructures.h:549
UINT64 Address
Definition RequestStructures.h:547

◆ DebuggerCommandSendGeneralBufferToDebugger()

NTSTATUS DebuggerCommandSendGeneralBufferToDebugger ( PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER DebuggeeBufferRequest)

Send general buffers from the debuggee to the debugger.

Parameters
DebuggeeBufferRequestRequest to buffer that will be sent to the debugger
Returns
NTSTATUS
1354{
1355 //
1356 // It's better to send the signal from vmx-root mode to avoid deadlock
1357 //
1359 (UINT64)DebuggeeBufferRequest,
1360 0,
1361 0);
1362
1363 DebuggeeBufferRequest->KernelResult = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1364
1365 return STATUS_SUCCESS;
1366}
#define DEBUGGER_VMCALL_SEND_GENERAL_BUFFER_TO_DEBUGGER
VMCALL to send general buffers from debuggee user-mode to the debugger.
Definition DebuggerVmcalls.h:49
IMPORT_EXPORT_VMM NTSTATUS VmFuncVmxVmcall(UINT64 VmcallNumber, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3)
Export for running VMX VMCALLs.
Definition Export.c:957
UINT32 KernelResult
Definition RequestStructures.h:409

◆ DebuggerCommandSendMessage()

NTSTATUS DebuggerCommandSendMessage ( PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER DebuggerSendUsermodeMessageRequest)

Send the user-mode buffer to debugger.

Parameters
DebuggerSendUsermodeMessageRequestRequest to send message to debugger
Returns
NTSTATUS
1332{
1333 //
1334 // It's better to send the signal from vmx-root mode to avoid deadlock
1335 //
1337 (UINT64)DebuggerSendUsermodeMessageRequest + (SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER),
1338 DebuggerSendUsermodeMessageRequest->Length,
1339 0);
1340
1341 DebuggerSendUsermodeMessageRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1342
1343 return STATUS_SUCCESS;
1344}
#define DEBUGGER_VMCALL_SEND_MESSAGES_TO_DEBUGGER
VMCALL to send messages to the debugger.
Definition DebuggerVmcalls.h:42
#define SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER
Definition RequestStructures.h:420
UINT32 KernelStatus
Definition RequestStructures.h:429
UINT32 Length
Definition RequestStructures.h:430

◆ DebuggerCommandSignalExecutionState()

NTSTATUS DebuggerCommandSignalExecutionState ( PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL DebuggerFinishedExecutionRequest)

Perform the command finished signal.

Parameters
DebuggerFinishedExecutionRequestRequest to signal debuggee about execution state
Returns
NTSTATUS
1313{
1314 //
1315 // It's better to send the signal from vmx-root mode
1316 //
1318
1319 DebuggerFinishedExecutionRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1320
1321 return STATUS_SUCCESS;
1322}
#define DEBUGGER_VMCALL_SIGNAL_DEBUGGER_EXECUTION_FINISHED
VMCALL to signal debugger that debuggee finished execution of the command.
Definition DebuggerVmcalls.h:36
UINT32 KernelStatus
Definition RequestStructures.h:390

◆ DebuggerReadOrWriteMsr()

NTSTATUS DebuggerReadOrWriteMsr ( PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest,
UINT64 * UserBuffer,
PSIZE_T ReturnSize )

Perform rdmsr, wrmsr commands.

Parameters
ReadOrWriteMsrRequestMsr read/write request
UserBufferuser buffer to save the results
ReturnSizereturn size to user-mode buffers
Returns
NTSTATUS
338{
339 NTSTATUS Status;
340 ULONG ProcessorsCount;
341
342 ProcessorsCount = KeQueryActiveProcessorCount(0);
343
344 //
345 // We don't check whether the MSR is in valid range of hardware or not
346 // because the user might send a non-valid MSR which means sth to the
347 // Windows or VMM, e.g the range specified for VMMs in Hyper-v
348 //
349
350 if (ReadOrWriteMsrRequest->ActionType == DEBUGGER_MSR_WRITE)
351 {
352 //
353 // Set Msr to be applied on the target cores
354 //
356 {
357 //
358 // Means that we should apply it on all cores
359 //
360 for (SIZE_T i = 0; i < ProcessorsCount; i++)
361 {
362 g_DbgState[i].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
363 g_DbgState[i].MsrState.Value = ReadOrWriteMsrRequest->Value;
364 }
365 //
366 // Broadcast to all cores to change their Msrs
367 //
368 KeGenericCallDpc(DpcRoutineWriteMsrToAllCores, 0x0);
369 }
370 else
371 {
372 //
373 // We have to change a single core's msr
374 //
375
376 //
377 // Check if the core number is not invalid
378 //
379 if (ReadOrWriteMsrRequest->CoreNumber >= ProcessorsCount)
380 {
381 return STATUS_INVALID_PARAMETER;
382 }
383 //
384 // Otherwise it's valid
385 //
386 g_DbgState[ReadOrWriteMsrRequest->CoreNumber].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
387 g_DbgState[ReadOrWriteMsrRequest->CoreNumber].MsrState.Value = ReadOrWriteMsrRequest->Value;
388
389 //
390 // Execute it on a single core
391 //
392 Status = DpcRoutineRunTaskOnSingleCore(ReadOrWriteMsrRequest->CoreNumber, (PVOID)DpcRoutinePerformWriteMsr, NULL);
393
394 *ReturnSize = 0;
395 return Status;
396 }
397
398 //
399 // It's an wrmsr, nothing to return
400 //
401 *ReturnSize = 0;
402 return STATUS_SUCCESS;
403 }
404 else if (ReadOrWriteMsrRequest->ActionType == DEBUGGER_MSR_READ)
405 {
406 //
407 // Set Msr to be applied on the target cores
408 //
410 {
411 //
412 // Means that we should apply it on all cores
413 //
414 for (SIZE_T i = 0; i < ProcessorsCount; i++)
415 {
416 g_DbgState[i].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
417 }
418
419 //
420 // Broadcast to all cores to read their Msrs
421 //
422 KeGenericCallDpc(DpcRoutineReadMsrToAllCores, 0x0);
423
424 //
425 // When we reach here, all processors read their shits
426 // so we have to fill that fucking buffer for user mode
427 //
428 for (SIZE_T i = 0; i < ProcessorsCount; i++)
429 {
430 UserBuffer[i] = g_DbgState[i].MsrState.Value;
431 }
432
433 //
434 // It's an rdmsr we have to return a value for all cores
435 //
436
437 *ReturnSize = sizeof(UINT64) * ProcessorsCount;
438 return STATUS_SUCCESS;
439 }
440 else
441 {
442 //
443 // Apply to one core
444 //
445
446 //
447 // Check if the core number is not invalid
448 //
449 if (ReadOrWriteMsrRequest->CoreNumber >= ProcessorsCount)
450 {
451 *ReturnSize = 0;
452 return STATUS_INVALID_PARAMETER;
453 }
454 //
455 // Otherwise it's valid
456 //
457 g_DbgState[ReadOrWriteMsrRequest->CoreNumber].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
458
459 //
460 // Execute it on a single core
461 //
462 Status = DpcRoutineRunTaskOnSingleCore(ReadOrWriteMsrRequest->CoreNumber, (PVOID)DpcRoutinePerformReadMsr, NULL);
463
464 if (Status != STATUS_SUCCESS)
465 {
466 *ReturnSize = 0;
467 return Status;
468 }
469 //
470 // Restore the result to the usermode
471 //
472 UserBuffer[0] = g_DbgState[ReadOrWriteMsrRequest->CoreNumber].MsrState.Value;
473
474 *ReturnSize = sizeof(UINT64);
475 return STATUS_SUCCESS;
476 }
477 }
478
479 *ReturnSize = 0;
480 return STATUS_UNSUCCESSFUL;
481}
unsigned long ULONG
Definition BasicTypes.h:31
#define DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES
Read and write MSRs to all cores.
Definition Constants.h:727
@ DEBUGGER_MSR_READ
Definition RequestStructures.h:450
@ DEBUGGER_MSR_WRITE
Definition RequestStructures.h:451
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
NTSTATUS DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredContext)
This function synchronize the function execution for a single core You should only used it for one co...
Definition DpcRoutines.c:35
VOID DpcRoutinePerformWriteMsr(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Broadcast msr write.
Definition DpcRoutines.c:128
VOID DpcRoutinePerformReadMsr(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Broadcast msr read.
Definition DpcRoutines.c:160
VOID DpcRoutineWriteMsrToAllCores(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Broadcast Msr Write.
Definition DpcRoutines.c:192
VOID DpcRoutineReadMsrToAllCores(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Broadcast Msr read.
Definition DpcRoutines.c:221
UINT32 CoreNumber
Definition RequestStructures.h:461
DEBUGGER_MSR_ACTION_TYPE ActionType
Definition RequestStructures.h:464
UINT64 Msr
Definition RequestStructures.h:460
UINT64 Value
Definition RequestStructures.h:465

◆ SearchAddressWrapper()

BOOLEAN SearchAddressWrapper ( PUINT64 AddressToSaveResults,
PDEBUGGER_SEARCH_MEMORY SearchMemRequest,
UINT64 StartAddress,
UINT64 EndAddress,
BOOLEAN IsDebuggeePaused,
PUINT32 CountOfMatchedCases )

The wrapper to check for validity of addresses and call the search routines for both physical and virtual memory.

This function can be called from vmx-root mode The address between start address and end address will be checked to make a contiguous address

Parameters
AddressToSaveResultsAddress to save the search results
SearchMemRequestrequest structure of searching memory
StartAddressstart address of searching based on target process
EndAddressstart address of searching based on target process
IsDebuggeePausedSet to true when the search is performed in the debugger mode
CountOfMatchedCasesNumber of matched cases
Returns
BOOLEAN Whether there was any error or not
1025{
1026 CR3_TYPE CurrentProcessCr3;
1027 UINT64 BaseAddress = 0;
1028 UINT64 RealPhysicalAddress = 0;
1029 UINT64 TempValue = (UINT64)NULL;
1030 UINT64 TempStartAddress = (UINT64)NULL;
1031 BOOLEAN DoesBaseAddrSaved = FALSE;
1032 BOOLEAN SearchResult = FALSE;
1033
1034 //
1035 // Reset the count of matched cases
1036 //
1037 *CountOfMatchedCases = 0;
1038
1039 if (SearchMemRequest->MemoryType == SEARCH_VIRTUAL_MEMORY)
1040 {
1041 //
1042 // It's a virtual address search
1043 //
1044
1045 //
1046 // Align the page and search with alignment
1047 //
1048 TempStartAddress = StartAddress;
1049 StartAddress = (UINT64)PAGE_ALIGN(StartAddress);
1050
1051 if (IsDebuggeePaused)
1052 {
1053 //
1054 // Switch to new process's memory layout
1055 //
1057 }
1058 else
1059 {
1060 //
1061 // Switch to new process's memory layout
1062 //
1063 CurrentProcessCr3 = SwitchToProcessMemoryLayout(SearchMemRequest->ProcessId);
1064 }
1065
1066 //
1067 // We will try to find a contigues address
1068 //
1069 while (StartAddress < EndAddress)
1070 {
1071 //
1072 // Check if address is valid or not
1073 // Generally, we can use VirtualAddressToPhysicalAddressByProcessId
1074 // but let's not change the cr3 multiple times
1075 //
1076 TempValue = VirtualAddressToPhysicalAddress((PVOID)StartAddress);
1077
1078 if (TempValue != 0)
1079 {
1080 //
1081 // Address is valid, let's add a page size to it
1082 // nothing to do
1083 //
1084 if (!DoesBaseAddrSaved)
1085 {
1086 BaseAddress = TempStartAddress;
1087 DoesBaseAddrSaved = TRUE;
1088 }
1089 }
1090 else
1091 {
1092 //
1093 // Address is not valid anymore
1094 //
1095 break;
1096 }
1097
1098 //
1099 // Make the start address ready for next address
1100 //
1101 StartAddress += PAGE_SIZE;
1102 }
1103
1104 //
1105 // Restore the original process
1106 //
1107 SwitchToPreviousProcess(CurrentProcessCr3);
1108
1109 //
1110 // All of the address chunk was valid
1111 //
1112 if (DoesBaseAddrSaved && StartAddress > BaseAddress)
1113 {
1114 SearchResult = PerformSearchAddress(AddressToSaveResults,
1115 SearchMemRequest,
1116 BaseAddress,
1117 EndAddress,
1118 IsDebuggeePaused,
1119 CountOfMatchedCases);
1120 }
1121 else
1122 {
1123 //
1124 // There was an error, address was probably not contiguous
1125 //
1126 return FALSE;
1127 }
1128 }
1129 else if (SearchMemRequest->MemoryType == SEARCH_PHYSICAL_MEMORY)
1130 {
1131 //
1132 // when we reached here, we know that it's a valid physical memory,
1133 // so we change the structure and pass it as a virtual address to
1134 // the search function
1135 //
1136 RealPhysicalAddress = SearchMemRequest->Address;
1137
1138 //
1139 // Change the start address
1140 //
1141 if (IsDebuggeePaused)
1142 {
1143 SearchMemRequest->Address = PhysicalAddressToVirtualAddressOnTargetProcess((PVOID)StartAddress);
1144 EndAddress = PhysicalAddressToVirtualAddressOnTargetProcess((PVOID)EndAddress);
1145 }
1146 else if (SearchMemRequest->ProcessId == HANDLE_TO_UINT32(PsGetCurrentProcessId()))
1147 {
1148 SearchMemRequest->Address = PhysicalAddressToVirtualAddress(StartAddress);
1149 EndAddress = PhysicalAddressToVirtualAddress(EndAddress);
1150 }
1151 else
1152 {
1153 SearchMemRequest->Address = PhysicalAddressToVirtualAddressByProcessId((PVOID)StartAddress,
1154 SearchMemRequest->ProcessId);
1155 EndAddress = PhysicalAddressToVirtualAddressByProcessId((PVOID)EndAddress,
1156 SearchMemRequest->ProcessId);
1157 }
1158
1159 //
1160 // Change the type of memory
1161 //
1163
1164 //
1165 // Call the wrapper
1166 //
1167 SearchResult = PerformSearchAddress(AddressToSaveResults,
1168 SearchMemRequest,
1169 SearchMemRequest->Address,
1170 EndAddress,
1171 IsDebuggeePaused,
1172 CountOfMatchedCases);
1173
1174 //
1175 // Restore the previous state
1176 //
1177 SearchMemRequest->MemoryType = SEARCH_PHYSICAL_MEMORY;
1178 SearchMemRequest->Address = RealPhysicalAddress;
1179 }
1180
1181 return SearchResult;
1182}
BOOLEAN PerformSearchAddress(UINT64 *AddressToSaveResults, PDEBUGGER_SEARCH_MEMORY SearchMemRequest, UINT64 StartAddress, UINT64 EndAddress, BOOLEAN IsDebuggeePaused, PUINT32 CountOfMatchedCases)
Search on virtual memory (not work on physical memory).
Definition DebuggerCommands.c:733
struct _CR3_TYPE CR3_TYPE
CR3 Structure.
@ SEARCH_PHYSICAL_FROM_VIRTUAL_MEMORY
Definition RequestStructures.h:525
@ SEARCH_PHYSICAL_MEMORY
Definition RequestStructures.h:523
@ SEARCH_VIRTUAL_MEMORY
Definition RequestStructures.h:524
IMPORT_EXPORT_VMM VOID SwitchToPreviousProcess(_In_ CR3_TYPE PreviousProcess)
IMPORT_EXPORT_VMM UINT64 PhysicalAddressToVirtualAddressOnTargetProcess(_In_ PVOID PhysicalAddress)
IMPORT_EXPORT_VMM CR3_TYPE SwitchToProcessMemoryLayout(_In_ UINT32 ProcessId)
IMPORT_EXPORT_VMM UINT64 PhysicalAddressToVirtualAddress(_In_ UINT64 PhysicalAddress)
IMPORT_EXPORT_VMM CR3_TYPE SwitchToProcessMemoryLayoutByCr3(_In_ CR3_TYPE TargetCr3)
IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCurrentProcessCr3()
Get cr3 of the target running process.
Definition Layout.c:55
IMPORT_EXPORT_VMM UINT64 PhysicalAddressToVirtualAddressByProcessId(_In_ PVOID PhysicalAddress, _In_ UINT32 ProcessId)
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80
#define PAGE_ALIGN(Va)
Aligning a page.
Definition common.h:86
DEBUGGER_SEARCH_MEMORY_TYPE MemoryType
Definition RequestStructures.h:550