NTSTATUS validatePePointer(PVOID pImageBase, PVOID pArbitraryPtr, ULONGLONG accessLength, BOOLEAN isNewImage){ UNREFERENCED_PARAMETER(accessLength); MEMORY_BASIC_VLM_INFORMATION vlmImageInfo; ULONGLONG returnLen = 0; NTSTATUS status = 0; static ULONGLONG peSize = 0; if (!peSize || isNewImage){ status = NtQueryVirtualMemory(INVALID_HANDLE_VALUE, pImageBase, MemoryBasicVlmInformation, &vlmImageInfo, sizeof(MEMORY_BASIC_VLM_INFORMATION), &returnLen); if (status) return status; peSize = vlmImageInfo.SizeOfImage; } ///The viability of this pointer validation is based on three assumptions: ///1. Each mapped section of the image is at least readable (R) without guard (+G). ///2. There don't exist any free pages between two sections of the same image. if ((pImageBase < ALIGN_DOWN_POINTER(pArbitraryPtr, PVOID)) && (((PUCHAR)ALIGN_UP_POINTER(pArbitraryPtr, PVOID) + accessLength) < ((PUCHAR)pImageBase + peSize))) return STATUS_SUCCESS; return STATUS_INVALID_ADDRESS; }
VOID NTAPI IopLogWorker(IN PVOID Parameter) { PELF_API_MSG Message; PIO_ERROR_LOG_MESSAGE ErrorMessage; PLIST_ENTRY ListEntry; PERROR_LOG_ENTRY LogEntry; PIO_ERROR_LOG_PACKET Packet; PCHAR StringBuffer; ULONG RemainingLength; PDRIVER_OBJECT DriverObject; ULONG DriverNameLength = 0, DeviceNameLength; UNICODE_STRING DriverNameString; NTSTATUS Status; UCHAR Buffer[256]; POBJECT_NAME_INFORMATION ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; POBJECT_NAME_INFORMATION PoolObjectNameInfo = NULL; ULONG ReturnedLength, MessageLength; PWCHAR p; ULONG ExtraStringLength; PAGED_CODE(); /* Connect to the port */ if (!IopConnectLogPort()) return; /* Allocate the message */ Message = ExAllocatePool(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH); if (!Message) { /* Couldn't allocate, try again */ IopRestartLogWorker(); return; } /* Copy the message */ RtlZeroMemory(Message, sizeof(ELF_API_MSG)); /* Get the actual I/O Structure */ ErrorMessage = &Message->IoErrorMessage; /* Start loop */ while (TRUE) { /* Get an entry */ ListEntry = IopGetErrorLogEntry(); if (!ListEntry) break; LogEntry = CONTAINING_RECORD(ListEntry, ERROR_LOG_ENTRY, ListEntry); /* Get pointer to the log packet */ Packet = (PIO_ERROR_LOG_PACKET)((ULONG_PTR)LogEntry + sizeof(ERROR_LOG_ENTRY)); /* Calculate the total length of the message only */ MessageLength = sizeof(IO_ERROR_LOG_MESSAGE) - sizeof(ERROR_LOG_ENTRY) - sizeof(IO_ERROR_LOG_PACKET) + LogEntry->Size; /* Copy the packet */ RtlCopyMemory(&ErrorMessage->EntryData, Packet, LogEntry->Size - sizeof(ERROR_LOG_ENTRY)); /* Set the timestamp and time */ ErrorMessage->TimeStamp = LogEntry->TimeStamp; ErrorMessage->Type = IO_TYPE_ERROR_MESSAGE; /* Check if this message has any strings */ if (Packet->NumberOfStrings) { /* String buffer is after the current strings */ StringBuffer = (PCHAR)&ErrorMessage->EntryData + Packet->StringOffset; } else { /* Otherwise, string buffer is at the end */ StringBuffer = (PCHAR)ErrorMessage + MessageLength; } /* Align the buffer */ StringBuffer = ALIGN_UP_POINTER(StringBuffer, WCHAR); /* Set the offset for the driver's name to the current buffer */ ErrorMessage->DriverNameOffset = (ULONG)(StringBuffer - (PCHAR)ErrorMessage); /* Check how much space we have left for the device string */ RemainingLength = (ULONG)((ULONG_PTR)Message + IO_ERROR_LOG_MESSAGE_LENGTH - (ULONG_PTR)StringBuffer); /* Now check if there is a driver object */ DriverObject = LogEntry->DriverObject; if (DriverObject) { /* Check if the driver has a name */ if (DriverObject->DriverName.Buffer) { /* Use its name */ DriverNameString.Buffer = DriverObject->DriverName.Buffer; DriverNameLength = DriverObject->DriverName.Length; } else DriverNameString.Buffer = NULL; /* Check if there isn't a valid name*/ if (!DriverNameLength) { /* Query the name directly */ Status = ObQueryNameString(DriverObject, ObjectNameInfo, sizeof(Buffer), &ReturnedLength); if (!(NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length)) { /* We don't have a name */ DriverNameLength = 0; } } } else { /* Use default name */ DriverNameString.Buffer = L"Application Popup"; DriverNameLength = (ULONG)wcslen(DriverNameString.Buffer) * sizeof(WCHAR); } /* Check if we have a driver name by here */ if (DriverNameLength) { /* Skip to the end of the driver's name */ p = &DriverNameString.Buffer[DriverNameLength / sizeof(WCHAR)]; /* Now we'll walk backwards and assume the minimum size */ DriverNameLength = sizeof(WCHAR); p--; while ((*p != L'\\') && (p != DriverNameString.Buffer)) { /* No backslash found, keep going */ p--; DriverNameLength += sizeof(WCHAR); } /* Now we probably hit the backslash itself, skip past it */ if (*p == L'\\') { p++; DriverNameLength -= sizeof(WCHAR); } /* * Now make sure that the driver name fits in our buffer, minus 3 * NULL chars, and copy the name in our string buffer */ DriverNameLength = min(DriverNameLength, RemainingLength - 3 * sizeof(UNICODE_NULL)); RtlCopyMemory(StringBuffer, p, DriverNameLength); } /* Null-terminate the driver name */ *((PWSTR)(StringBuffer + DriverNameLength)) = L'\0'; DriverNameLength += sizeof(WCHAR); /* Go to the next string buffer position */ StringBuffer += DriverNameLength; RemainingLength -= DriverNameLength; /* Update the string offset and check if we have a device object */ ErrorMessage->EntryData.StringOffset = (USHORT) ((ULONG_PTR)StringBuffer - (ULONG_PTR)ErrorMessage); if (LogEntry->DeviceObject) { /* We do, query its name */ Status = ObQueryNameString(LogEntry->DeviceObject, ObjectNameInfo, sizeof(Buffer), &ReturnedLength); if (!NT_SUCCESS(Status) || (ObjectNameInfo->Name.Length == 0)) { /* Setup an empty name */ ObjectNameInfo->Name.Length = 0; ObjectNameInfo->Name.Buffer = L""; /* Check if we failed because our buffer wasn't large enough */ if (Status == STATUS_INFO_LENGTH_MISMATCH) { /* Then we'll allocate one... we really want this name! */ PoolObjectNameInfo = ExAllocatePoolWithTag(PagedPool, ReturnedLength, TAG_IO); if (PoolObjectNameInfo) { /* Query it again */ ObjectNameInfo = PoolObjectNameInfo; Status = ObQueryNameString(LogEntry->DeviceObject, ObjectNameInfo, ReturnedLength, &ReturnedLength); if (NT_SUCCESS(Status)) { /* Success, update the information */ ObjectNameInfo->Name.Length = 100 - (USHORT)DriverNameLength; } } } } } else { /* No device object, setup an empty name */ ObjectNameInfo->Name.Length = 0; ObjectNameInfo->Name.Buffer = L""; } /* * Now make sure that the device name fits in our buffer, minus 2 * NULL chars, and copy the name in our string buffer */ DeviceNameLength = min(ObjectNameInfo->Name.Length, RemainingLength - 2 * sizeof(UNICODE_NULL)); RtlCopyMemory(StringBuffer, ObjectNameInfo->Name.Buffer, DeviceNameLength); /* Null-terminate the device name */ *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0'; DeviceNameLength += sizeof(WCHAR); /* Free the buffer if we had one */ if (PoolObjectNameInfo) { ExFreePool(PoolObjectNameInfo); PoolObjectNameInfo = NULL; ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; } /* Go to the next string buffer position */ ErrorMessage->EntryData.NumberOfStrings++; StringBuffer += DeviceNameLength; RemainingLength -= DeviceNameLength; /* Check if we have any extra strings */ if (Packet->NumberOfStrings) { /* Find out the size of the extra strings */ ExtraStringLength = LogEntry->Size - sizeof(ERROR_LOG_ENTRY) - Packet->StringOffset; /* Make sure that the extra strings fit in our buffer */ if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL))) { /* They wouldn't, so set normalize the length */ MessageLength -= ExtraStringLength - RemainingLength; ExtraStringLength = RemainingLength - sizeof(UNICODE_NULL); } /* Now copy the extra strings */ RtlCopyMemory(StringBuffer, (PCHAR)Packet + Packet->StringOffset, ExtraStringLength); /* Null-terminate them */ *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0'; } /* Set the driver name length */ ErrorMessage->DriverNameLength = (USHORT)DriverNameLength; /* Update the message length to include the device and driver names */ MessageLength += DeviceNameLength + DriverNameLength; ErrorMessage->Size = (USHORT)MessageLength; /* Now update it again, internally, for the size of the actual LPC */ MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) - FIELD_OFFSET(ELF_API_MSG, Unknown[0])); /* Set the total and data lengths */ Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) + MessageLength); Message->h.u1.s1.DataLength = (USHORT)(MessageLength); /* Send the message */ Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message); if (!NT_SUCCESS(Status)) { /* Requeue log message and restart the worker */ ExInterlockedInsertTailList(&IopErrorLogListHead, &LogEntry->ListEntry, &IopLogListLock); IopLogWorkerRunning = FALSE; IopRestartLogWorker(); break; } /* Dereference the device object */ if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject); if (DriverObject) ObDereferenceObject(LogEntry->DriverObject); /* Update size */ InterlockedExchangeAdd(&IopTotalLogSize, -(LONG)(LogEntry->Size - sizeof(ERROR_LOG_ENTRY))); } /* Free the LPC Message */ ExFreePool(Message); }
static pool_t *pool_create(int size,int num_elems) { pool_t *pool=calloc(1,sizeof(pool_t)); pool->size=ALIGN_UP_POINTER(size);; pool_addelems(pool,num_elems); return pool; }