I trying make a code example where i want insert in a arrylist only process names that still not exists in this list, my trouble that show here is that comes bsod in the following line. This following code is based on usermode version present in this answer (https://stackoverflow.com/questions/49765716/c-how-make-a-arraylist-implementation-compatible-with-unicode-string-data/49765864#49765864). Before i tried make with same usermode code of arraylist, but already that some routines not is avaiable in kernel mode i decided use somes similar like ExAllocatePoolWithTag (malloc/calloc), RtlFreeUnicodeString (void FreeUString()), RtlDuplicateUnicodeString,this last can be better change to RtlUnicodeStringCopy already that RtlDuplicateUnicodeString is not always exported in Windows.
FAULTING_SOURCE_LINE_NUMBER: 128
FAULTING_SOURCE_CODE:
124: {
125: int index = 0;
126: while (index <= list->current)
127: {
> 128: if (e->data->Length == list->elements[index].data->Length &&
129: 0 == wcsncmp(e->data->Buffer,
130: list->elements[index].data->Buffer,
131: list->elements[index].data->Length))
132: return index;
133: index++;
Here is a minimal and compilable example:
#include <ntddk.h>
#include <windef.h>
#define NTOSAPI __declspec(dllimport)
NTSTATUS NTAPI RtlDuplicateUnicodeString(IN ULONG Flags, IN PCUNICODE_STRING SourceString, OUT PUNICODE_STRING DestinationString);
///////////////////////////////////// START ARRAYLIST /////////////////////////////////////////
typedef unsigned char uint8_t;
typedef struct
{
UNICODE_STRING *data;
}Element;
typedef struct
{
int current;
int size;
int increment_rate;
Element *elements;
}ArrayList;
void FreeUString(UNICODE_STRING *src)
{
RtlFreeUnicodeString(src);
src->Length = src->MaximumLength = 0;
}
void initWithSizeAndIncRate(ArrayList const list, int size, int rate)
{
list->size = size;
list->increment_rate = rate;
list->elements = (Element)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘Fo’);
list->current = -1;
}
void initWithSize(ArrayList *const list, int size)
{
initWithSizeAndIncRate(list, size, 50);
}
void init(ArrayList *const list)
{
initWithSize(list, 100);
}
void arraryCopy(void dest, int dIndex, const void src, int sIndex, int len, int destLen, size_t size)
{
uint8_t udest = (uint8_t)dest;
uint8_t usrc = (uint8_t)src;
dIndex *= size;
sIndex *= size;
len *= size;
destLen *= size;
if (src != dest)
{
memcpy(&udest[dIndex], &usrc[sIndex], len);
}
else
{
if (dIndex > sIndex)
{
uint8_t tmp = (uint8_t)ExAllocatePoolWithTag(NonPagedPool, size, ‘F’);
memcpy(tmp, &udest[dIndex], (destLen - dIndex));
memcpy(&udest[dIndex], &usrc[sIndex], len);
memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
ExFreePoolWithTag(tmp, ‘F’);
}
else if (sIndex > dIndex)
{
memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
}
else
return;
}
}
void clear(ArrayList const list)
{
while (list->current >= 0)
{
FreeUString(list->elements[list->current].data);
list->current–;
}
}
void wide(ArrayList const list)
{
list->size += list->increment_rate;
Element newArr = (Element)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘T’);
arraryCopy(newArr, 0, list->elements, 0, list->current, list->size, sizeof(Element));
//ExFreePoolWithTag(list->elements, ‘Foo’);
list->elements = newArr;
}
int add(ArrayList *const list, Element *e)
{
UNICODE_STRING *dest = { NULL };
NTSTATUS status = STATUS_SUCCESS;
if (++list->current < list->size)
{
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);
list->elements[list->current].data = dest;
return 1;
}
else
{
wide(list);
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);
list->elements[list->current].data = dest;
return 1;
}
return 0;
}
int indexOf(const ArrayList *const list, Element *e)
{
int index = 0;
while (index <= list->current)
{
if (e->data->Length == list->elements[index].data->Length &&
0 == wcsncmp(e->data->Buffer,
list->elements[index].data->Buffer,
list->elements[index].data->Length))
return index;
index++;
}
return 0;
}
void clean(ArrayList *list)
{
ExFreePoolWithTag(list->elements, ‘Fo’);
}
ArrayList list;
Element e;
///////////////////////////////// END ARRAYLIST ///////////////////////////////////
typedef enum _THREAD_STATE {
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE;
typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
LONG WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;
typedef struct SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
DWORD BasePriority;
HANDLE ProcessId;
HANDLE ParentProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VMCounters;
IO_COUNTERS IOCounters;
SYSTEM_THREAD Threads[1];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemProcessInformation = 5,
SystemCallCountInformation = 6,
SystemDeviceInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemFlagsInformation = 9,
SystemCallTimeInformation = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemStackTraceInformation = 13,
SystemPagedPoolInformation = 14,
SystemNonPagedPoolInformation = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemVdmBopInformation = 20,
SystemFileCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemDpcBehaviorInformation = 24,
SystemFullMemoryInformation = 25,
SystemLoadGdiDriverInformation = 26,
SystemUnloadGdiDriverInformation = 27,
SystemTimeAdjustmentInformation = 28,
SystemSummaryMemoryInformation = 29,
SystemMirrorMemoryInformation = 30,
SystemPerformanceTraceInformation = 31,
SystemObsolete0 = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemExtendServiceTableInformation = 38,
SystemPrioritySeperation = 39,
SystemVerifierAddDriverInformation = 40,
SystemVerifierRemoveDriverInformation = 41,
SystemProcessorIdleInformation = 42,
SystemLegacyDriverInformation = 43,
SystemCurrentTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemTimeSlipNotification = 46,
SystemSessionCreate = 47,
SystemSessionDetach = 48,
SystemSessionInformation = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemVerifierThunkExtend = 52,
SystemSessionProcessInformation = 53,
SystemLoadGdiDriverInSystemSpace = 54,
SystemNumaProcessorMap = 55,
SystemPrefetcherInformation = 56,
SystemExtendedProcessInformation = 57,
SystemRecommendedSharedDataAlignment = 58,
SystemComPlusPackage = 59,
SystemNumaAvailableMemory = 60,
SystemProcessorPowerInformation = 61,
SystemEmulationBasicInformation = 62,
SystemEmulationProcessorInformation = 63,
SystemExtendedHandleInformation = 64,
SystemLostDelayedWriteInformation = 65,
SystemBigPoolInformation = 66,
SystemSessionPoolTagInformation = 67,
SystemSessionMappedViewInformation = 68,
SystemHotpatchInformation = 69,
SystemObjectSecurityMode = 70,
SystemWatchdogTimerHandler = 71,
SystemWatchdogTimerInformation = 72,
SystemLogicalProcessorInformation = 73,
SystemWow64SharedInformation = 74,
SystemRegisterFirmwareTableInformationHandler = 75,
SystemFirmwareTableInformation = 76,
SystemModuleInformationEx = 77,
SystemVerifierTriageInformation = 78,
SystemSuperfetchInformation = 79,
SystemMemoryListInformation = 80,
SystemFileCacheInformationEx = 81,
MaxSystemInfoClass = 82
} SYSTEM_INFORMATION_CLASS;
NTOSAPI NTSTATUS NTAPI ZwQuerySystemInformation(/IN/ SYSTEM_INFORMATION_CLASS SystemInformationClass, /IN OUT/ PVOID SystemInformation, /IN/ ULONG SystemInformationLength, /OUT/ PULONG ReturnLength OPTIONAL);
NTSTATUS EnumProcesses()
{
NTSTATUS status;
ULONG cb = 0x8000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
PVOID buf = ExAllocatePoolWithTag(PagedPool, cb, ‘tset’);
if (buf)
{
if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union Data {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
union Data data;
data.pv = buf;
ULONG NextEntryOffset = 0;
do
{
data.pb += NextEntryOffset;
DbgPrint(“%d %wZ\n”, data.pspi->ProcessId, &data.pspi->ImageName);
e.data = &data.pspi->ImageName;
int i = indexOf(&list, &e);
if (i > 0)
{
DbgPrint(“process already in list \n”);
}
else
{
add(&list, &e);
}
} while (NextEntryOffset = data.pspi->NextEntryOffset);
}
ExFreePoolWithTag(buf, ‘tset’);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
clean(&list);
return status;
}
void EnumProcUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint(“Goodbye from EnumProc!\n”);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
init(&list);
EnumProcesses();
DriverObject->DriverUnload = EnumProcUnload;
DbgPrint(“Hello from EnumProc!\n”);
return STATUS_SUCCESS;
}</windef.h></ntddk.h>