aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/contrib/windows_kernel/libc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'capstone/contrib/windows_kernel/libc.cpp')
-rw-r--r--capstone/contrib/windows_kernel/libc.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/capstone/contrib/windows_kernel/libc.cpp b/capstone/contrib/windows_kernel/libc.cpp
new file mode 100644
index 000000000..ac4a4eb9b
--- /dev/null
+++ b/capstone/contrib/windows_kernel/libc.cpp
@@ -0,0 +1,143 @@
+/**
+ * @file libc.cpp
+ * @author created by: Peter Hlavaty
+ */
+
+#include "libc.h"
+#include <memory>
+#include <Ntintsafe.h>
+
+#pragma warning(push)
+#pragma warning (disable : 4565)
+
+#ifndef _LIBC_POOL_TAG
+#define _LIBC_POOL_TAG 'colM'
+#endif
+
+// very nice for debug forensics!
+struct MEMBLOCK
+{
+ size_t size;
+#pragma warning(push)
+#pragma warning (disable : 4200)
+ __declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
+ char data[0];
+#pragma warning(pop)
+};
+
+EXTERN_C
+__drv_when(return!=0, __drv_allocatesMem(pBlock))
+__checkReturn
+__drv_maxIRQL(DISPATCH_LEVEL)
+__bcount_opt(size)
+void*
+__cdecl malloc(
+ __in size_t size
+ )
+{
+ /* A specially crafted size value can trigger the overflow.
+ If the sum in a value that overflows or underflows the capacity of the type,
+ the function returns nullptr. */
+ size_t number_of_bytes = 0;
+ if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
+ return nullptr;
+ }
+ MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
+ ExAllocatePoolWithTag(
+ NonPagedPoolNxCacheAligned,
+ number_of_bytes,
+ _LIBC_POOL_TAG));
+
+ if (nullptr == pBlock)
+ return nullptr;
+
+ pBlock->size = size;
+ return pBlock->data;
+}
+
+EXTERN_C
+__drv_when(return != 0, __drv_allocatesMem(p))
+__checkReturn
+__drv_maxIRQL(DISPATCH_LEVEL)
+__bcount_opt(size * n)
+void*
+__cdecl calloc(size_t n, size_t size)
+{
+ size_t total = n * size;
+ void *p = malloc(total);
+
+ if (!p) return NULL;
+
+ return memset(p, 0, total);
+}
+
+EXTERN_C
+__drv_when(return!=0, __drv_allocatesMem(inblock))
+__checkReturn
+__drv_maxIRQL(DISPATCH_LEVEL)
+__bcount_opt(size)
+void*
+__cdecl realloc(
+ __in_opt void* ptr,
+ __in size_t size
+ )
+{
+ if (!ptr)
+ return malloc(size);
+
+ std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
+
+ // alloc new block
+ void* mem = malloc(size);
+ if (!mem)
+ return nullptr;
+
+ // copy from old one, not overflow ..
+ memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
+ return mem;
+}
+
+EXTERN_C
+__drv_maxIRQL(DISPATCH_LEVEL)
+void
+__cdecl free(
+ __inout_opt __drv_freesMem(Mem) void* ptr
+ )
+{
+ if (ptr)
+ ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
+}
+
+#pragma warning(pop)
+
+__drv_when(return!=0, __drv_allocatesMem(ptr))
+__checkReturn
+__drv_maxIRQL(DISPATCH_LEVEL)
+__bcount_opt(size)
+void*
+__cdecl operator new(
+ __in size_t size
+ )
+{
+ return malloc(size);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+void
+__cdecl operator delete(
+ __inout void* ptr
+ )
+{
+ free(ptr);
+}
+
+int
+__cdecl vsnprintf(
+ char *buffer,
+ size_t count,
+ const char *format,
+ va_list argptr
+)
+{
+ return vsprintf_s(buffer, count, format, argptr);
+}