Rizin
unix-like reverse engineering framework and cli tools
winkernel_mm.c
Go to the documentation of this file.
1 /* Capstone Disassembly Engine */
2 /* By Satoshi Tanda <tanda.sat@gmail.com>, 2016-2019 */
3 
4 #include "winkernel_mm.h"
5 #include <ntddk.h>
6 #include <Ntintsafe.h>
7 
8 // A pool tag for memory allocation
9 static const ULONG CS_WINKERNEL_POOL_TAG = 'kwsC';
10 
11 
12 // A structure to implement realloc()
13 typedef struct _CS_WINKERNEL_MEMBLOCK {
14  size_t size; // A number of bytes allocated
15  __declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
16  char data[ANYSIZE_ARRAY]; // An address returned to a caller
18 
19 
20 // free()
22 {
23  if (ptr) {
24  ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG);
25  }
26 }
27 
28 // malloc()
30 {
31  // Disallow zero length allocation because they waste pool header space and,
32  // in many cases, indicate a potential validation issue in the calling code.
33  NT_ASSERT(size);
34 
35  // FP; a use of NonPagedPool is required for Windows 7 support
36  size_t number_of_bytes = 0;
37  CS_WINKERNEL_MEMBLOCK *block = NULL;
38  // A specially crafted size value can trigger the overflow.
39  // If the sum in a value that overflows or underflows the capacity of the type,
40  // the function returns NULL.
41  if (!NT_SUCCESS(RtlSizeTAdd(size, FIELD_OFFSET(CS_WINKERNEL_MEMBLOCK, data), &number_of_bytes))) {
42  return NULL;
43  }
44 #pragma prefast(suppress : 30030) // Allocating executable POOL_TYPE memory
46  NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG);
47  if (!block) {
48  return NULL;
49  }
50  block->size = size;
51 
52  return block->data;
53 }
54 
55 // calloc()
56 void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
57 {
58  size_t total = n * size;
59 
60  void *new_ptr = cs_winkernel_malloc(total);
61  if (!new_ptr) {
62  return NULL;
63  }
64 
65  return RtlFillMemory(new_ptr, total, 0);
66 }
67 
68 // realloc()
69 void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size)
70 {
71  void *new_ptr = NULL;
72  size_t current_size = 0;
73  size_t smaller_size = 0;
74 
75  if (!ptr) {
76  return cs_winkernel_malloc(size);
77  }
78 
79  new_ptr = cs_winkernel_malloc(size);
80  if (!new_ptr) {
81  return NULL;
82  }
83 
84  current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size;
85  smaller_size = (current_size < size) ? current_size : size;
86  RtlCopyMemory(new_ptr, ptr, smaller_size);
87  cs_winkernel_free(ptr);
88 
89  return new_ptr;
90 }
91 
92 // vsnprintf(). _vsnprintf() is available for drivers, but it differs from
93 // vsnprintf() in a return value and when a null-terminator is set.
94 // cs_winkernel_vsnprintf() takes care of those differences.
95 #pragma warning(push)
96 // Banned API Usage : _vsnprintf is a Banned API as listed in dontuse.h for
97 // security purposes.
98 #pragma warning(disable : 28719)
99 int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
100 {
101  int result = _vsnprintf(buffer, count, format, argptr);
102 
103  // _vsnprintf() returns -1 when a string is truncated, and returns "count"
104  // when an entire string is stored but without '\0' at the end of "buffer".
105  // In both cases, null-terminator needs to be added manually.
106  if (result == -1 || (size_t)result == count) {
107  buffer[count - 1] = '\0';
108  }
109 
110  if (result == -1) {
111  // In case when -1 is returned, the function has to get and return a number
112  // of characters that would have been written. This attempts so by retrying
113  // the same conversion with temp buffer that is most likely big enough to
114  // complete formatting and get a number of characters that would have been
115  // written.
116  char* tmp = cs_winkernel_malloc(0x1000);
117  if (!tmp) {
118  return result;
119  }
120 
121  result = _vsnprintf(tmp, 0x1000, format, argptr);
122  NT_ASSERT(result != -1);
124  }
125 
126  return result;
127 }
128 #pragma warning(pop)
#define CAPSTONE_API
Definition: capstone.h:32
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
voidpf void uLong size
Definition: ioapi.h:138
ExAllocatePoolWithTag
Definition: kernel.h:18
RtlFillMemory
Definition: kernel.h:287
int n
Definition: mipsasm.c:19
Definition: buffer.h:15
__declspec(noreturn) void uv_fatal_error(const int errorno
#define NT_SUCCESS(status)
Definition: winapi.h:52
@ NonPagedPool
Definition: windows_debug.h:61
ULONG
void *CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size)
Definition: winkernel_mm.c:69
int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
Definition: winkernel_mm.c:99
void CAPSTONE_API cs_winkernel_free(void *ptr)
Definition: winkernel_mm.c:21
void *CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
Definition: winkernel_mm.c:56
struct _CS_WINKERNEL_MEMBLOCK CS_WINKERNEL_MEMBLOCK
static const ULONG CS_WINKERNEL_POOL_TAG
Definition: winkernel_mm.c:9
void *CAPSTONE_API cs_winkernel_malloc(size_t size)
Definition: winkernel_mm.c:29