diff options
Diffstat (limited to 'capstone/windows')
-rw-r--r-- | capstone/windows/README | 1 | ||||
-rw-r--r-- | capstone/windows/winkernel_mm.c | 128 | ||||
-rw-r--r-- | capstone/windows/winkernel_mm.h | 23 |
3 files changed, 152 insertions, 0 deletions
diff --git a/capstone/windows/README b/capstone/windows/README new file mode 100644 index 000000000..8d3ccbec9 --- /dev/null +++ b/capstone/windows/README @@ -0,0 +1 @@ +This directory contains code specific to Windows platforms. diff --git a/capstone/windows/winkernel_mm.c b/capstone/windows/winkernel_mm.c new file mode 100644 index 000000000..a9f87ce26 --- /dev/null +++ b/capstone/windows/winkernel_mm.c @@ -0,0 +1,128 @@ +/* Capstone Disassembly Engine */ +/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */ + +#include "winkernel_mm.h" +#include <ntddk.h> +#include <Ntintsafe.h> + +// A pool tag for memory allocation +static const ULONG CS_WINKERNEL_POOL_TAG = 'kwsC'; + + +// A structure to implement realloc() +typedef struct _CS_WINKERNEL_MEMBLOCK { + size_t size; // A number of bytes allocated + __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) + char data[ANYSIZE_ARRAY]; // An address returned to a caller +} CS_WINKERNEL_MEMBLOCK; + + +// free() +void CAPSTONE_API cs_winkernel_free(void *ptr) +{ + if (ptr) { + ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG); + } +} + +// malloc() +void * CAPSTONE_API cs_winkernel_malloc(size_t size) +{ + // Disallow zero length allocation because they waste pool header space and, + // in many cases, indicate a potential validation issue in the calling code. + NT_ASSERT(size); + + // FP; a use of NonPagedPool is required for Windows 7 support +#pragma prefast(suppress : 30030) // Allocating executable POOL_TYPE memory + size_t number_of_bytes = 0; + CS_WINKERNEL_MEMBLOCK *block = NULL; + // 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 NULL. + if (!NT_SUCCESS(RtlSizeTAdd(size, FIELD_OFFSET(CS_WINKERNEL_MEMBLOCK, data), &number_of_bytes))) { + return NULL; + } + block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag( + NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG); + if (!block) { + return NULL; + } + block->size = size; + + return block->data; +} + +// calloc() +void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size) +{ + size_t total = n * size; + + void *new_ptr = cs_winkernel_malloc(total); + if (!new_ptr) { + return NULL; + } + + return RtlFillMemory(new_ptr, total, 0); +} + +// realloc() +void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size) +{ + void *new_ptr = NULL; + size_t current_size = 0; + size_t smaller_size = 0; + + if (!ptr) { + return cs_winkernel_malloc(size); + } + + new_ptr = cs_winkernel_malloc(size); + if (!new_ptr) { + return NULL; + } + + current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size; + smaller_size = (current_size < size) ? current_size : size; + RtlCopyMemory(new_ptr, ptr, smaller_size); + cs_winkernel_free(ptr); + + return new_ptr; +} + +// vsnprintf(). _vsnprintf() is available for drivers, but it differs from +// vsnprintf() in a return value and when a null-terminator is set. +// cs_winkernel_vsnprintf() takes care of those differences. +#pragma warning(push) +// Banned API Usage : _vsnprintf is a Banned API as listed in dontuse.h for +// security purposes. +#pragma warning(disable : 28719) +int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) +{ + int result = _vsnprintf(buffer, count, format, argptr); + + // _vsnprintf() returns -1 when a string is truncated, and returns "count" + // when an entire string is stored but without '\0' at the end of "buffer". + // In both cases, null-terminator needs to be added manually. + if (result == -1 || (size_t)result == count) { + buffer[count - 1] = '\0'; + } + + if (result == -1) { + // In case when -1 is returned, the function has to get and return a number + // of characters that would have been written. This attempts so by retrying + // the same conversion with temp buffer that is most likely big enough to + // complete formatting and get a number of characters that would have been + // written. + char* tmp = cs_winkernel_malloc(0x1000); + if (!tmp) { + return result; + } + + result = _vsnprintf(tmp, 0x1000, format, argptr); + NT_ASSERT(result != -1); + cs_winkernel_free(tmp); + } + + return result; +} +#pragma warning(pop) diff --git a/capstone/windows/winkernel_mm.h b/capstone/windows/winkernel_mm.h new file mode 100644 index 000000000..ed743f3e5 --- /dev/null +++ b/capstone/windows/winkernel_mm.h @@ -0,0 +1,23 @@ +/* Capstone Disassembly Engine */ +/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */ + +#ifndef CS_WINDOWS_WINKERNEL_MM_H +#define CS_WINDOWS_WINKERNEL_MM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <capstone/capstone.h> + +void CAPSTONE_API cs_winkernel_free(void *ptr); +void * CAPSTONE_API cs_winkernel_malloc(size_t size); +void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size); +void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size); +int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr); + +#ifdef __cplusplus +} +#endif + +#endif // CS_WINDOWS_WINKERNEL_MM_H |