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

char * VmxLogMessage
 VMX buffer for logging messages.
 
char * VmxTempMessage
 VMX temporary buffer for logging messages.
 
LOG_BUFFER_INFORMATIONMessageBufferInformation
 Global Variable for buffer on all cores.
 
volatile LONG VmxRootLoggingLock
 Vmx-root lock for logging.
 
volatile LONG 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
1351{
1352 PNOTIFY_RECORD NotifyRecord;
1353 PIRP Irp;
1354 UINT32 Length;
1355
1356 UNREFERENCED_PARAMETER(Dpc);
1357 UNREFERENCED_PARAMETER(SystemArgument1);
1358 UNREFERENCED_PARAMETER(SystemArgument2);
1359
1360 NotifyRecord = DeferredContext;
1361
1362 ASSERT(NotifyRecord != NULL); // can't be NULL
1363 _Analysis_assume_(NotifyRecord != NULL);
1364
1365 switch (NotifyRecord->Type)
1366 {
1367 case IRP_BASED:
1368 Irp = NotifyRecord->Message.PendingIrp;
1369
1370 if (Irp != NULL)
1371 {
1372 PCHAR OutBuff; // pointer to output buffer
1373 ULONG InBuffLength; // Input buffer length
1374 ULONG OutBuffLength; // Output buffer length
1375 PIO_STACK_LOCATION IrpSp;
1376
1377 //
1378 // Make suree that concurrent calls to notify function never occurs
1379 //
1380 if (!(Irp->CurrentLocation <= Irp->StackCount + 1))
1381 {
1382 DbgPrint("Err, probably two or more functions called DPC for an object");
1383 return;
1384 }
1385
1386 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1387 InBuffLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1388 OutBuffLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1389
1390 if (!InBuffLength || !OutBuffLength)
1391 {
1392 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1393 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1394 break;
1395 }
1396
1397 //
1398 // Check again that SystemBuffer is not null
1399 //
1400 if (!Irp->AssociatedIrp.SystemBuffer)
1401 {
1402 //
1403 // Buffer is invalid
1404 //
1405 return;
1406 }
1407
1408 OutBuff = Irp->AssociatedIrp.SystemBuffer;
1409 Length = 0;
1410
1411 //
1412 // Read Buffer might be empty (nothing to send)
1413 //
1414 if (!LogReadBuffer(NotifyRecord->CheckVmxRootMessagePool, OutBuff, &Length))
1415 {
1416 //
1417 // we have to return here as there is nothing to send here
1418 //
1419 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1420 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1421 break;
1422 }
1423
1424 Irp->IoStatus.Information = Length;
1425
1426 Irp->IoStatus.Status = STATUS_SUCCESS;
1427 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1428 }
1429 break;
1430
1431 case EVENT_BASED:
1432 //
1433 // Signal the Event created in user-mode.
1434 //
1435 KeSetEvent(NotifyRecord->Message.Event, 0, FALSE);
1436
1437 //
1438 // Dereference the object as we are done with it.
1439 //
1440 ObDereferenceObject(NotifyRecord->Message.Event);
1441
1442 break;
1443
1444 default:
1445 ASSERT(FALSE);
1446 break;
1447 }
1448
1449 if (NotifyRecord != NULL)
1450 {
1451 PlatformMemFreePool(NotifyRecord);
1452 }
1453}
#define FALSE
Definition BasicTypes.h:54
unsigned int UINT32
Definition BasicTypes.h:48
unsigned long ULONG
Definition BasicTypes.h:37
@ EVENT_BASED
Definition DataTypes.h:256
@ IRP_BASED
Definition DataTypes.h:255
BOOLEAN LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 *ReturnedLength)
Attempt to read the buffer.
Definition Logging.c:697
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
The usermode request.
Definition Logging.h:40
PIRP PendingIrp
Definition Logging.h:46
NOTIFY_TYPE Type
Definition Logging.h:41
union _NOTIFY_RECORD::@55 Message
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.)
698{
699 UINT32 Index;
700 BOOLEAN PriorityMessageIsAvailable = FALSE;
701 KIRQL OldIRQL = NULL_ZERO;
702
703 //
704 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
705 // if not we use the windows spinlock
706 //
707 if (IsVmxRoot)
708 {
709 //
710 // Set the index
711 //
712 Index = 1;
713
714 //
715 // Acquire the lock
716 //
718 }
719 else
720 {
721 //
722 // Set the index
723 //
724 Index = 0;
725
726 //
727 // Acquire the lock
728 //
729 KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL);
730 }
731
732 //
733 // Compute the current buffer to read
734 //
735 BUFFER_HEADER * Header;
736
737 //
738 // Check for priority message
739 //
741
742 if (!Header->Valid)
743 {
744 //
745 // Check for regular message
746 //
748
749 if (!Header->Valid)
750 {
751 //
752 // there is nothing to send
753 //
754
755 //
756 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
757 // if not we use the windows spinlock
758 //
759 if (IsVmxRoot)
760 {
762 }
763 else
764 {
765 //
766 // Release the lock
767 //
768 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
769 }
770
771 return FALSE;
772 }
773 }
774 else
775 {
776 PriorityMessageIsAvailable = TRUE;
777 }
778
779 //
780 // If we reached here, means that there is sth to send
781 //
782
783 //
784 // First copy the header
785 //
786 RtlCopyBytes(BufferToSaveMessage, &Header->OperationNumber, sizeof(UINT32));
787
788 //
789 // Second, save the buffer contents
790 //
791 PVOID SendingBuffer;
792
793 if (PriorityMessageIsAvailable)
794 {
796 }
797 else
798 {
800 }
801
802 //
803 // Because we want to pass the header of usermode header
804 //
805 PVOID SavingAddress = (PVOID)((UINT64)BufferToSaveMessage + sizeof(UINT32));
806
807 RtlCopyBytes(SavingAddress, SendingBuffer, Header->BufferLength);
808
809#if ShowMessagesOnDebugger
810
811 //
812 // Means that show just messages
813 //
815 {
816 //
817 // We're in Dpc level here so it's safe to use DbgPrint
818 // DbgPrint limitation is 512 Byte
819 //
820 if (Header->BufferLength > DbgPrintLimitation)
821 {
822 for (size_t i = 0; i <= Header->BufferLength / DbgPrintLimitation; i++)
823 {
824 if (i != 0)
825 {
826 DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i) - 2));
827 }
828 else
829 {
830 DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i)));
831 }
832 }
833 }
834 else
835 {
836 DbgPrint("%s", (char *)SendingBuffer);
837 }
838 }
839#endif
840
841 //
842 // Finally, set the current index to invalid as we sent it
843 //
844 Header->Valid = FALSE;
845
846 //
847 // Set the length to show as the ReturnedByted in usermode ioctl function + size of header
848 //
849 *ReturnedLength = Header->BufferLength + sizeof(UINT32);
850
851 //
852 // Last step is to clear the current buffer (we can't do it once when CurrentIndexToSend is zero because
853 // there might be multiple messages on the start of the queue that didn't read yet)
854 // we don't free the header
855 //
856 RtlZeroMemory(SendingBuffer, Header->BufferLength);
857
858 if (PriorityMessageIsAvailable)
859 {
860 //
861 // Check to see whether we passed the index or not
862 //
863 if (MessageBufferInformation[Index].CurrentIndexToSendPriority > MaximumPacketsCapacityPriority - 2)
864 {
866 }
867 else
868 {
869 //
870 // Increment the next index to read
871 //
873 }
874 }
875 else
876 {
877 //
878 // Check to see whether we passed the index or not
879 //
880 if (MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2)
881 {
883 }
884 else
885 {
886 //
887 // Increment the next index to read
888 //
890 }
891 }
892
893 //
894 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
895 // if not we use the windows spinlock
896 //
897 if (IsVmxRoot)
898 {
900 }
901 else
902 {
903 //
904 // Release the lock
905 //
906 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
907 }
908
909 return TRUE;
910}
UCHAR BOOLEAN
Definition BasicTypes.h:39
#define NULL_ZERO
Definition BasicTypes.h:51
#define TRUE
Definition BasicTypes.h:55
unsigned __int64 UINT64
Definition BasicTypes.h:21
#define MaximumPacketsCapacity
Default buffer count of packets for message tracing.
Definition Constants.h:163
#define PacketChunkSize
Size of each packet.
Definition Constants.h:179
#define DbgPrintLimitation
limitation of Windows DbgPrint message size
Definition Constants.h:215
#define OPERATION_LOG_NON_IMMEDIATE_MESSAGE
Definition Constants.h:369
#define MaximumPacketsCapacityPriority
Default buffer count of packets for message tracing.
Definition Constants.h:169
volatile LONG VmxRootLoggingLock
Vmx-root lock for logging.
Definition Logging.h:110
struct _BUFFER_HEADER BUFFER_HEADER
Message buffer structure.
LOG_BUFFER_INFORMATION * MessageBufferInformation
Global Variable for buffer on all cores.
Definition Logging.h:104
void SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:52
void SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:158
Message buffer structure.
Definition Logging.h:58
UINT32 BufferLength
Definition Logging.h:60
UINT32 OperationNumber
Definition Logging.h:59
BOOLEAN Valid
Definition Logging.h:61
UINT32 CurrentIndexToSend
Definition Logging.h:82
UINT64 BufferStartAddress
Definition Logging.h:79
UINT64 BufferStartAddressPriority
Definition Logging.h:88
UINT32 CurrentIndexToSendPriority
Definition Logging.h:91

Variable Documentation

◆ g_GlobalNotifyRecord

NOTIFY_RECORD* g_GlobalNotifyRecord

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

◆ g_MsgTracingCallbacks

MESSAGE_TRACING_CALLBACKS g_MsgTracingCallbacks

Global variable that holds callbacks.

◆ MessageBufferInformation

LOG_BUFFER_INFORMATION* MessageBufferInformation

Global Variable for buffer on all cores.

◆ VmxLogMessage

char* VmxLogMessage

VMX buffer for logging messages.

◆ VmxRootLoggingLock

volatile LONG VmxRootLoggingLock

Vmx-root lock for logging.

◆ VmxRootLoggingLockForNonImmBuffers

volatile LONG VmxRootLoggingLockForNonImmBuffers

Vmx-root lock for logging.

◆ VmxTempMessage

char* VmxTempMessage

VMX temporary buffer for logging messages.