aboutsummaryrefslogtreecommitdiff
path: root/CRT
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-07-28 16:53:41 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-07-28 18:27:51 +0200
commit6c602fd542b7f97e3a23ef27c3839656906c98de (patch)
tree31ca34bd5ed53a52ae3181878b9ebbe9c92b15f8 /CRT
parent3a3cbeecc113daf992de838a39569f6c81876dbe (diff)
Fixed ctor/dtor issue allowing use of static qualifiers for non primitives.
* split CRT in a C and C++ part * use "fake" entry point to init CRT and set a DriverUnload routine for de-init * added -Wl,--exclude-all-symbols to DRIVER_LDFLAGS Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'CRT')
-rw-r--r--CRT/DriverThread.cpp137
-rw-r--r--CRT/DriverThread.hpp83
-rw-r--r--CRT/kcrt.c273
-rw-r--r--CRT/kcrt.cpp51
-rw-r--r--CRT/ucrt.cpp10
5 files changed, 554 insertions, 0 deletions
diff --git a/CRT/DriverThread.cpp b/CRT/DriverThread.cpp
new file mode 100644
index 0000000..efc4023
--- /dev/null
+++ b/CRT/DriverThread.cpp
@@ -0,0 +1,137 @@
+#include <DriverThread.hpp>
+
+// Thread
+
+DriverThread::Thread::Thread(void)
+{
+}
+
+DriverThread::Thread::~Thread(void)
+{
+ WaitForTermination();
+}
+
+extern "C" void InterceptorThreadRoutine(PVOID threadContext)
+{
+ DriverThread::Thread * self = (DriverThread::Thread *)threadContext;
+
+ self->m_threadId = PsGetCurrentThreadId();
+ PsTerminateSystemThread(self->m_routine(self->m_threadContext));
+}
+
+NTSTATUS DriverThread::Thread::Start(threadRoutine_t routine, PVOID threadContext)
+{
+ HANDLE threadHandle;
+ NTSTATUS status;
+
+ LockGuard lock(m_mutex);
+ m_routine = routine;
+ m_threadContext = threadContext;
+ status = PsCreateSystemThread(&threadHandle, (ACCESS_MASK)0, NULL, (HANDLE)0, NULL, InterceptorThreadRoutine, this);
+
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ ObReferenceObjectByHandle(threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *)&m_threadObject, NULL);
+ return ZwClose(threadHandle);
+}
+
+NTSTATUS DriverThread::Thread::WaitForTermination(LONGLONG timeout)
+{
+ if (PsGetCurrentThreadId() == m_threadId)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LockGuard lock(m_mutex);
+ if (m_threadObject == nullptr)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ LARGE_INTEGER li_timeout = {.QuadPart = timeout};
+ NTSTATUS status =
+ KeWaitForSingleObject(m_threadObject, Executive, KernelMode, FALSE, (timeout == 0 ? NULL : &li_timeout));
+
+ ObDereferenceObject(m_threadObject);
+ m_threadObject = nullptr;
+ return status;
+}
+
+HANDLE DriverThread::Thread::GetThreadId(void)
+{
+ return m_threadId;
+}
+
+// Spinlock
+
+DriverThread::Spinlock::Spinlock(void)
+{
+ KeInitializeSpinLock(&m_spinLock);
+}
+
+NTSTATUS DriverThread::Spinlock::Acquire(void)
+{
+ return KeAcquireSpinLock(&m_spinLock, &m_oldIrql);
+}
+
+void DriverThread::Spinlock::Release(void)
+{
+ KeReleaseSpinLock(&m_spinLock, m_oldIrql);
+}
+
+KIRQL DriverThread::Spinlock::GetOldIrql(void)
+{
+ return m_oldIrql;
+}
+
+// Semaphore
+
+DriverThread::Semaphore::Semaphore(LONG initialValue, LONG maxValue)
+{
+ KeInitializeSemaphore(&m_semaphore, initialValue, maxValue);
+}
+
+NTSTATUS DriverThread::Semaphore::Wait(LONGLONG timeout)
+{
+ LARGE_INTEGER li_timeout = {.QuadPart = timeout};
+ return KeWaitForSingleObject(&m_semaphore, Executive, KernelMode, FALSE, (timeout == 0 ? NULL : &li_timeout));
+}
+
+LONG DriverThread::Semaphore::Release(LONG adjustment)
+{
+ return KeReleaseSemaphore(&m_semaphore, 0, adjustment, FALSE);
+}
+
+// Mutex
+
+DriverThread::Mutex::Mutex(void)
+{
+}
+
+DriverThread::Mutex::~Mutex(void)
+{
+}
+
+void DriverThread::Mutex::Lock(void)
+{
+ while (m_interlock == 1 || InterlockedCompareExchange(&m_interlock, 1, 0) == 1) {}
+}
+
+void DriverThread::Mutex::Unlock(void)
+{
+ m_interlock = 0;
+}
+
+// LockGuard
+
+DriverThread::LockGuard::LockGuard(Mutex & m) : m_Lock(m)
+{
+ m_Lock.Lock();
+}
+
+DriverThread::LockGuard::~LockGuard(void)
+{
+ m_Lock.Unlock();
+}
diff --git a/CRT/DriverThread.hpp b/CRT/DriverThread.hpp
new file mode 100644
index 0000000..d00db1b
--- /dev/null
+++ b/CRT/DriverThread.hpp
@@ -0,0 +1,83 @@
+#ifndef DDK_THREAD
+#define DDK_THREAD 1
+
+#include <ntddk.h>
+
+extern "C" void InterceptorThreadRoutine(PVOID threadContext);
+
+typedef NTSTATUS (*threadRoutine_t)(PVOID);
+
+namespace DriverThread
+{
+
+class Mutex
+{
+public:
+ Mutex(void);
+ ~Mutex(void);
+
+private:
+ void Lock();
+ void Unlock();
+
+ volatile long int m_interlock;
+
+ friend class LockGuard;
+};
+
+class LockGuard
+{
+public:
+ LockGuard(Mutex & m);
+ ~LockGuard(void);
+
+private:
+ Mutex m_Lock;
+};
+
+class Thread
+{
+public:
+ Thread(void);
+ ~Thread(void);
+ NTSTATUS Start(threadRoutine_t routine, PVOID threadContext);
+ NTSTATUS WaitForTermination(LONGLONG timeout = 0);
+ HANDLE GetThreadId(void);
+
+private:
+ friend void ::InterceptorThreadRoutine(PVOID threadContext);
+
+ HANDLE m_threadId = nullptr;
+ PETHREAD m_threadObject = nullptr;
+ Mutex m_mutex;
+ threadRoutine_t m_routine;
+ PVOID m_threadContext;
+};
+
+class Spinlock
+{
+public:
+ Spinlock(void);
+ NTSTATUS Acquire(void);
+ void Release(void);
+ KIRQL GetOldIrql(void);
+
+private:
+ KIRQL m_oldIrql;
+ KSPIN_LOCK m_spinLock;
+};
+
+class Semaphore
+{
+public:
+ Semaphore(LONG initialValue = 0, LONG maxValue = MAXLONG);
+ NTSTATUS Wait(LONGLONG timeout = 0);
+ LONG Release(LONG adjustment = 1);
+
+private:
+ KSEMAPHORE m_semaphore;
+};
+
+}; // namespace DriverThread
+
+#endif
diff --git a/CRT/kcrt.c b/CRT/kcrt.c
new file mode 100644
index 0000000..ccff181
--- /dev/null
+++ b/CRT/kcrt.c
@@ -0,0 +1,273 @@
+/*
+ * Shameless copy pasta from: https://github.com/sidyhe/dxx
+ * and: https://github.com/liupengs/Mini-CRT
+ * and some minor modifications.
+ */
+
+#include <ntddk.h>
+
+#define KCRT_POOL_DEFAULT_TAG 0xDEADBEEF
+
+extern void (*__CTOR_LIST__)();
+extern void (*__DTOR_LIST__)();
+extern NTSTATUS __cdecl DriverEntry(_In_ struct _DRIVER_OBJECT * DriverObject, _In_ PUNICODE_STRING RegistryPath);
+extern void __cdecl DriverUnload(_In_ struct _DRIVER_OBJECT * DriverObject);
+
+DRIVER_INITIALIZE __cdecl _CRT_DriverEntry;
+DRIVER_UNLOAD __cdecl _CRT_DriverUnload;
+
+typedef void (*__cdecl init_and_deinit_fn)(void);
+typedef void (*__cdecl atexit_func_t)(void);
+
+typedef struct _func_node
+{
+ atexit_func_t func;
+ struct _func_node * next;
+} func_node;
+
+typedef struct _MALLOC_HEADER
+{
+ ULONG32 Tags;
+ ULONG32 _Resv0;
+ ULONG_PTR Size;
+} MALLOC_HEADER, *PMALLOC_HEADER;
+C_ASSERT(sizeof(MALLOC_HEADER) % sizeof(void *) == 0);
+
+static func_node * atexit_list = NULL;
+
+// dynamic memory mgmt
+
+PMALLOC_HEADER GET_MALLOC_HEADER(PVOID ptr)
+{
+ return (MALLOC_HEADER *)((PUCHAR)ptr - sizeof(MALLOC_HEADER));
+}
+
+PVOID GET_MALLOC_ADDRESS(PMALLOC_HEADER header)
+{
+ return (PVOID)((PUCHAR)header + sizeof(MALLOC_HEADER));
+}
+
+ULONG_PTR GET_MALLOC_SIZE(PVOID ptr)
+{
+ PMALLOC_HEADER header = GET_MALLOC_HEADER(ptr);
+
+ if (header->Tags != KCRT_POOL_DEFAULT_TAG)
+ KeBugCheckEx(BAD_POOL_HEADER, 0, 0, 0, 0);
+
+ return header->Size;
+}
+
+// c runtime
+
+static int register_atexit(atexit_func_t func)
+{
+ func_node * node;
+ if (!func)
+ return -1;
+
+ node = (func_node *)malloc(sizeof(func_node));
+
+ if (node == 0)
+ return -1;
+
+ node->func = func;
+ node->next = atexit_list;
+ atexit_list = node;
+ return 0;
+}
+
+int __cdecl atexit(atexit_func_t func)
+{
+ return register_atexit(func);
+}
+
+void __cdecl free(void * ptr)
+{
+ if (ptr)
+ {
+ MALLOC_HEADER * mhdr = GET_MALLOC_HEADER(ptr);
+
+ if (mhdr->Tags != KCRT_POOL_DEFAULT_TAG)
+ KeBugCheckEx(BAD_POOL_HEADER, 0, 0, 0, 0);
+
+ ExFreePool(mhdr);
+ }
+}
+
+void * __cdecl malloc(size_t size)
+{
+ PMALLOC_HEADER mhdr = NULL;
+ const size_t new_size = size + sizeof(MALLOC_HEADER);
+
+ mhdr = (PMALLOC_HEADER)ExAllocatePoolWithTag(NonPagedPool, new_size, KCRT_POOL_DEFAULT_TAG);
+ if (mhdr)
+ {
+ RtlZeroMemory(mhdr, new_size);
+
+ mhdr->Tags = KCRT_POOL_DEFAULT_TAG;
+ mhdr->Size = size;
+ return GET_MALLOC_ADDRESS(mhdr);
+ }
+
+ return NULL;
+}
+
+void * __cdecl realloc(void * ptr, size_t new_size)
+{
+ if (!ptr)
+ {
+ return malloc(new_size);
+ }
+ else if (new_size == 0)
+ {
+ free(ptr);
+ return NULL;
+ }
+ else
+ {
+ size_t old_size = GET_MALLOC_SIZE(ptr);
+
+ if (new_size <= old_size)
+ {
+ return ptr;
+ }
+ else
+ {
+ void * new_ptr = malloc(new_size);
+
+ if (new_ptr)
+ {
+ memcpy(new_ptr, ptr, old_size);
+ free(ptr);
+ return new_ptr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void __cdecl __cxa_pure_virtual(void)
+{
+ // definitly not perfect, but we get at least a notification
+ while (1)
+ {
+ DbgPrint("Pure virtual function call..\n");
+ LARGE_INTEGER li = {.QuadPart = -10000000};
+ KeDelayExecutionThread(KernelMode, TRUE, &li);
+ }
+}
+
+// stolen from musl: https://elixir.bootlin.com/musl/v1.1.9/source/src/math/ceilf.c
+#define FORCE_EVAL(x) \
+ do \
+ { \
+ if (sizeof(x) == sizeof(float)) \
+ { \
+ volatile float __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ else if (sizeof(x) == sizeof(double)) \
+ { \
+ volatile double __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ else \
+ { \
+ volatile long double __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ } while (0)
+
+float __cdecl ceilf(float x)
+{
+ union {
+ float f;
+ UINT32 i;
+ } u = {x};
+ int e = (int)(u.i >> 23 & 0xff) - 0x7f;
+ UINT32 m;
+
+ if (e >= 23)
+ return x;
+ if (e >= 0)
+ {
+ m = 0x007fffff >> e;
+ if ((u.i & m) == 0)
+ return x;
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31 == 0)
+ u.i += m;
+ u.i &= ~m;
+ }
+ else
+ {
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31)
+ u.f = -0.0;
+ else if (u.i << 1)
+ u.f = 1.0;
+ }
+ return u.f;
+}
+
+// functions called in DRIVER_INITIALIZE and DRIVER_UNLOAD
+
+static void __cdecl __ctors(void)
+{
+ unsigned long long int const * const * const l = (unsigned long long int const * const * const)&__CTOR_LIST__;
+ unsigned long long int i = (unsigned long long int)*l;
+ init_and_deinit_fn const * p;
+
+ if (i == (unsigned long long int)-1)
+ {
+ for (i = 1; l[i] != NULL; i++)
+ ;
+ i--;
+ }
+
+ p = (init_and_deinit_fn *)&l[i];
+
+ while (i--)
+ {
+ (**p--)();
+ }
+}
+
+static void __cdecl __dtors(void)
+{
+ func_node * p = atexit_list;
+ for (; p != NULL; p = p->next)
+ {
+ p->func();
+ free(p);
+ }
+ atexit_list = NULL;
+}
+
+void __cdecl KCRT_OnDriverEntry(void)
+{
+ __ctors();
+}
+
+void __cdecl KCRT_OnDriverUnload(void)
+{
+ __dtors();
+}
+
+void __cdecl _CRT_DriverUnload(_In_ struct _DRIVER_OBJECT * DriverObject)
+{
+ DriverUnload(DriverObject);
+
+ KCRT_OnDriverUnload();
+}
+
+NTSTATUS __cdecl _CRT_DriverEntry(_In_ struct _DRIVER_OBJECT * DriverObject, _In_ PUNICODE_STRING RegistryPath)
+{
+ KCRT_OnDriverEntry();
+
+ /* support for service stopping and CRT de-init */
+ DriverObject->DriverUnload = _CRT_DriverUnload;
+
+ return DriverEntry(DriverObject, RegistryPath);
+}
diff --git a/CRT/kcrt.cpp b/CRT/kcrt.cpp
new file mode 100644
index 0000000..32681ab
--- /dev/null
+++ b/CRT/kcrt.cpp
@@ -0,0 +1,51 @@
+/*
+ * Shameless copy pasta from: https://github.com/sidyhe/dxx
+ * and: https://github.com/liupengs/Mini-CRT
+ * and some minor modifications.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+
+// new & delete
+
+void * __cdecl operator new(std::size_t size)
+{
+ return malloc(size);
+}
+
+void * __cdecl operator new[](size_t size)
+{
+ return malloc(size);
+}
+
+void __cdecl operator delete(void * ptr)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete(void * ptr, size_t)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete[](void * ptr, long long unsigned int)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete[](void * ptr)
+{
+ free(ptr);
+}
+
+// EASTL
+
+void * operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+void * operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
diff --git a/CRT/ucrt.cpp b/CRT/ucrt.cpp
new file mode 100644
index 0000000..19ea583
--- /dev/null
+++ b/CRT/ucrt.cpp
@@ -0,0 +1,10 @@
+#include <cstdlib>
+
+void * operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+void * operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}