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

Headers of Message logging and tracing. More...

Go to the source code of this file.

Classes

struct  _NOTIFY_RECORD
 The usermode request. More...
struct  _BUFFER_HEADER
 Message buffer structure. More...
struct  _LOG_BUFFER_INFORMATION
 Core-specific buffers. More...

Typedefs

typedef struct _NOTIFY_RECORD NOTIFY_RECORD
 The usermode request.
typedef struct _NOTIFY_RECORDPNOTIFY_RECORD
typedef struct _BUFFER_HEADER BUFFER_HEADER
 Message buffer structure.
typedef struct _BUFFER_HEADERPBUFFER_HEADER
typedef struct _LOG_BUFFER_INFORMATION LOG_BUFFER_INFORMATION
 Core-specific buffers.
typedef struct _LOG_BUFFER_INFORMATIONPLOG_BUFFER_INFORMATION

Functions

BOOLEAN LogReadBuffer (BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 *ReturnedLength)
 Attempt to read the buffer.
VOID LogNotifyUsermodeCallback (PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
 Complete the IRP in IRP Pending state and fill the usermode buffers with pool data.

Variables

CHARg_VmxLogMessage
 VMX buffer for logging messages.
CHARg_VmxTempMessage
 VMX temporary buffer for logging messages.
LOG_BUFFER_INFORMATIONg_MessageBufferInformation
 Global Variable for buffer on all cores.
volatile LONG g_VmxRootLoggingLock
 Vmx-root lock for logging.
volatile LONG g_VmxRootLoggingLockForNonImmBuffers
 Vmx-root lock for logging.
NOTIFY_RECORDg_GlobalNotifyRecord
 Save the state of the thread that waits for messages to deliver to user-mode.
MESSAGE_TRACING_CALLBACKS g_MsgTracingCallbacks
 Global variable that holds callbacks.

Detailed Description

Headers of Message logging and tracing.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2020-04-11

Typedef Documentation

◆ BUFFER_HEADER

typedef struct _BUFFER_HEADER BUFFER_HEADER

Message buffer structure.

◆ LOG_BUFFER_INFORMATION

Core-specific buffers.

◆ NOTIFY_RECORD

typedef struct _NOTIFY_RECORD NOTIFY_RECORD

The usermode request.

◆ PBUFFER_HEADER

typedef struct _BUFFER_HEADER * PBUFFER_HEADER

◆ PLOG_BUFFER_INFORMATION

◆ PNOTIFY_RECORD

typedef struct _NOTIFY_RECORD * PNOTIFY_RECORD

Function Documentation

◆ LogNotifyUsermodeCallback()

VOID LogNotifyUsermodeCallback ( PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2 )

Complete the IRP in IRP Pending state and fill the usermode buffers with pool data.

Parameters
Dpc
DeferredContext
SystemArgument1
SystemArgument2
Returns
VOID
1362{
1363 PNOTIFY_RECORD NotifyRecord;
1364 PIRP Irp;
1365 UINT32 Length;
1366
1367 UNREFERENCED_PARAMETER(Dpc);
1368 UNREFERENCED_PARAMETER(SystemArgument1);
1369 UNREFERENCED_PARAMETER(SystemArgument2);
1370
1371 NotifyRecord = DeferredContext;
1372
1373 ASSERT(NotifyRecord != NULL); // can't be NULL
1374 _Analysis_assume_(NotifyRecord != NULL);
1375
1376 switch (NotifyRecord->Type)
1377 {
1378 case IRP_BASED:
1379 Irp = NotifyRecord->Message.PendingIrp;
1380
1381 if (Irp != NULL)
1382 {
1383 PCHAR OutBuff; // pointer to output buffer
1384 ULONG InBuffLength; // Input buffer length
1385 ULONG OutBuffLength; // Output buffer length
1386 PIO_STACK_LOCATION IrpSp;
1387
1388 //
1389 // Make suree that concurrent calls to notify function never occurs
1390 //
1391 if (!(Irp->CurrentLocation <= Irp->StackCount + 1))
1392 {
1393 PlatformDbgPrint("Err, probably two or more functions called DPC for an object");
1394 return;
1395 }
1396
1398 InBuffLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1399 OutBuffLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1400
1401 if (!InBuffLength || !OutBuffLength)
1402 {
1403 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1404 PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT);
1405 break;
1406 }
1407
1408 //
1409 // Check again that SystemBuffer is not null
1410 //
1411 if (!Irp->AssociatedIrp.SystemBuffer)
1412 {
1413 //
1414 // Buffer is invalid
1415 //
1416 return;
1417 }
1418
1419 OutBuff = Irp->AssociatedIrp.SystemBuffer;
1420 Length = 0;
1421
1422 //
1423 // Read Buffer might be empty (nothing to send)
1424 //
1425 if (!LogReadBuffer(NotifyRecord->CheckVmxRootMessagePool, OutBuff, &Length))
1426 {
1427 //
1428 // we have to return here as there is nothing to send here
1429 //
1430 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1431 PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT);
1432 break;
1433 }
1434
1435 Irp->IoStatus.Information = Length;
1436
1437 Irp->IoStatus.Status = STATUS_SUCCESS;
1438 PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT);
1439 }
1440 break;
1441
1442 case EVENT_BASED:
1443 //
1444 // Signal the Event created in user-mode.
1445 //
1446 PlatformEventSet(NotifyRecord->Message.Event, 0, FALSE);
1447
1448 //
1449 // Dereference the object as we are done with it.
1450 //
1452
1453 break;
1454
1455 default:
1456 ASSERT(FALSE);
1457 break;
1458 }
1459
1460 if (NotifyRecord != NULL)
1461 {
1462 PlatformMemFreePool(NotifyRecord);
1463 }
1464}
BOOLEAN LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 *ReturnedLength)
Attempt to read the buffer.
Definition Logging.c:708
struct _NOTIFY_RECORD * PNOTIFY_RECORD
VOID PlatformDbgPrint(const CHAR *Format,...)
Print a debug message to the kernel debugger.
Definition PlatformDbg.c:26
VOID PlatformObjectDereference(PVOID Object)
Dereference a kernel object, decrementing its reference count.
Definition PlatformEvent.c:25
LONG PlatformEventSet(PKEVENT Event, KPRIORITY Increment, BOOLEAN Wait)
Signal (set) a kernel event object.
Definition PlatformEvent.c:51
PIO_STACK_LOCATION PlatformIoGetCurrentIrpStackLocation(PIRP Irp)
Get the current I/O stack location from an IRP.
Definition PlatformIo.c:25
VOID PlatformIoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
Complete an IRP and release it back to the I/O manager.
Definition PlatformIo.c:50
PVOID PlatformMemFreePool(PVOID BufferAddress)
Frees a memory pool.
Definition PlatformMem.c:269
#define FALSE
Definition BasicTypes.h:113
unsigned int UINT32
Definition BasicTypes.h:54
unsigned long ULONG
Definition BasicTypes.h:31
@ EVENT_BASED
Definition DataTypes.h:288
@ IRP_BASED
Definition DataTypes.h:287
union _NOTIFY_RECORD::@217351000120040342300302212137013326214173270134 Message
PIRP PendingIrp
Definition Logging.h:46
NOTIFY_TYPE Type
Definition Logging.h:41
PKEVENT Event
Definition Logging.h:45
BOOLEAN CheckVmxRootMessagePool
Definition Logging.h:50

◆ LogReadBuffer()

BOOLEAN LogReadBuffer ( BOOLEAN IsVmxRoot,
PVOID BufferToSaveMessage,
UINT32 * ReturnedLength )

Attempt to read the buffer.

Parameters
IsVmxRootDetermine whether you want to read vmx root buffer or vmx non root buffer
BufferToSaveMessageTarget buffer to save the message
ReturnedLengthThe actual length of the buffer that this function used it
Returns
BOOLEAN return of this function shows whether the read was successful or not (e.g FALSE shows there's no new buffer available.)
709{
710 UINT32 Index;
711 BOOLEAN PriorityMessageIsAvailable = FALSE;
712 KIRQL OldIRQL = NULL_ZERO;
713
714 //
715 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
716 // if not we use the windows spinlock
717 //
718 if (IsVmxRoot)
719 {
720 //
721 // Set the index
722 //
723 Index = 1;
724
725 //
726 // Acquire the lock
727 //
729 }
730 else
731 {
732 //
733 // Set the index
734 //
735 Index = 0;
736
737 //
738 // Acquire the lock
739 //
740 PlatformSpinlockAcquire(&g_MessageBufferInformation[Index].BufferLock, &OldIRQL);
741 }
742
743 //
744 // Compute the current buffer to read
745 //
746 BUFFER_HEADER * Header;
747
748 //
749 // Check for priority message
750 //
751 Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER))));
752
753 if (!Header->Valid)
754 {
755 //
756 // Check for regular message
757 //
758 Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))));
759
760 if (!Header->Valid)
761 {
762 //
763 // there is nothing to send
764 //
765
766 //
767 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
768 // if not we use the windows spinlock
769 //
770 if (IsVmxRoot)
771 {
773 }
774 else
775 {
776 //
777 // Release the lock
778 //
779 PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL);
780 }
781
782 return FALSE;
783 }
784 }
785 else
786 {
787 PriorityMessageIsAvailable = TRUE;
788 }
789
790 //
791 // If we reached here, means that there is sth to send
792 //
793
794 //
795 // First copy the header
796 //
797 PlatformWriteMemory(BufferToSaveMessage, &Header->OperationNumber, sizeof(UINT32));
798
799 //
800 // Second, save the buffer contents
801 //
802 PVOID SendingBuffer;
803
804 if (PriorityMessageIsAvailable)
805 {
806 SendingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER));
807 }
808 else
809 {
810 SendingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER));
811 }
812
813 //
814 // Because we want to pass the header of usermode header
815 //
816 PVOID SavingAddress = (PVOID)((UINT64)BufferToSaveMessage + sizeof(UINT32));
817
818 PlatformWriteMemory(SavingAddress, SendingBuffer, Header->BufferLength);
819
820#if ShowMessagesOnDebugger
821
822 //
823 // Means that show just messages
824 //
826 {
827 //
828 // We're in Dpc level here so it's safe to use DbgPrint
829 // DbgPrint limitation is 512 Byte
830 //
831 if (Header->BufferLength > DbgPrintLimitation)
832 {
833 for (SIZE_T i = 0; i <= Header->BufferLength / DbgPrintLimitation; i++)
834 {
835 if (i != 0)
836 {
837 PlatformDbgPrint("%s", (CHAR *)((UINT64)SendingBuffer + (DbgPrintLimitation * i) - 2));
838 }
839 else
840 {
841 PlatformDbgPrint("%s", (CHAR *)((UINT64)SendingBuffer + (DbgPrintLimitation * i)));
842 }
843 }
844 }
845 else
846 {
847 PlatformDbgPrint("%s", (CHAR *)SendingBuffer);
848 }
849 }
850#endif
851
852 //
853 // Finally, set the current index to invalid as we sent it
854 //
855 Header->Valid = FALSE;
856
857 //
858 // Set the length to show as the ReturnedByted in usermode ioctl function + size of header
859 //
860 *ReturnedLength = Header->BufferLength + sizeof(UINT32);
861
862 //
863 // Last step is to clear the current buffer (we can't do it once when CurrentIndexToSend is zero because
864 // there might be multiple messages on the start of the queue that didn't read yet)
865 // we don't free the header
866 //
867 PlatformZeroMemory(SendingBuffer, Header->BufferLength);
868
869 if (PriorityMessageIsAvailable)
870 {
871 //
872 // Check to see whether we passed the index or not
873 //
874 if (g_MessageBufferInformation[Index].CurrentIndexToSendPriority > MaximumPacketsCapacityPriority - 2)
875 {
876 g_MessageBufferInformation[Index].CurrentIndexToSendPriority = 0;
877 }
878 else
879 {
880 //
881 // Increment the next index to read
882 //
883 g_MessageBufferInformation[Index].CurrentIndexToSendPriority = g_MessageBufferInformation[Index].CurrentIndexToSendPriority + 1;
884 }
885 }
886 else
887 {
888 //
889 // Check to see whether we passed the index or not
890 //
891 if (g_MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2)
892 {
893 g_MessageBufferInformation[Index].CurrentIndexToSend = 0;
894 }
895 else
896 {
897 //
898 // Increment the next index to read
899 //
900 g_MessageBufferInformation[Index].CurrentIndexToSend = g_MessageBufferInformation[Index].CurrentIndexToSend + 1;
901 }
902 }
903
904 //
905 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
906 // if not we use the windows spinlock
907 //
908 if (IsVmxRoot)
909 {
911 }
912 else
913 {
914 //
915 // Release the lock
916 //
917 PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL);
918 }
919
920 return TRUE;
921}
LOG_BUFFER_INFORMATION * g_MessageBufferInformation
Global Variable for buffer on all cores.
Definition Logging.h:104
struct _BUFFER_HEADER BUFFER_HEADER
Message buffer structure.
volatile LONG g_VmxRootLoggingLock
Vmx-root lock for logging.
Definition Logging.h:110
VOID PlatformZeroMemory(PVOID Destination, SIZE_T Size)
Zeros a memory block.
Definition PlatformMem.c:155
VOID PlatformWriteMemory(PVOID Address, PVOID Buffer, SIZE_T Size)
Writes data from a buffer to a memory address.
Definition PlatformMem.c:115
VOID PlatformSpinlockRelease(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Release a previously acquired kernel spinlock and restore IRQL.
Definition PlatformSpinlock.c:75
VOID PlatformSpinlockAcquire(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Acquire a kernel spinlock, raising IRQL to DISPATCH_LEVEL.
Definition PlatformSpinlock.c:50
VOID SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:53
VOID SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:162
UCHAR BOOLEAN
Definition BasicTypes.h:35
void * PVOID
Definition BasicTypes.h:56
#define NULL_ZERO
Definition BasicTypes.h:110
#define TRUE
Definition BasicTypes.h:114
char CHAR
Definition BasicTypes.h:33
#define MaximumPacketsCapacity
Default buffer count of packets for message tracing.
Definition Constants.h:171
#define PacketChunkSize
Size of each packet.
Definition Constants.h:187
#define DbgPrintLimitation
limitation of Windows DbgPrint message size
Definition Constants.h:223
#define OPERATION_LOG_NON_IMMEDIATE_MESSAGE
Definition Constants.h:377
#define MaximumPacketsCapacityPriority
Default buffer count of packets for message tracing.
Definition Constants.h:177
UINT32 BufferLength
Definition Logging.h:60
UINT32 OperationNumber
Definition Logging.h:59
BOOLEAN Valid
Definition Logging.h:61

Variable Documentation

◆ g_GlobalNotifyRecord

NOTIFY_RECORD* g_GlobalNotifyRecord

Save the state of the thread that waits for messages to deliver to user-mode.

◆ g_MessageBufferInformation

LOG_BUFFER_INFORMATION* g_MessageBufferInformation

Global Variable for buffer on all cores.

◆ g_MsgTracingCallbacks

MESSAGE_TRACING_CALLBACKS g_MsgTracingCallbacks

Global variable that holds callbacks.

◆ g_VmxLogMessage

CHAR* g_VmxLogMessage

VMX buffer for logging messages.

◆ g_VmxRootLoggingLock

volatile LONG g_VmxRootLoggingLock

Vmx-root lock for logging.

◆ g_VmxRootLoggingLockForNonImmBuffers

volatile LONG g_VmxRootLoggingLockForNonImmBuffers

Vmx-root lock for logging.

◆ g_VmxTempMessage

CHAR* g_VmxTempMessage

VMX temporary buffer for logging messages.