liyujie
2025-08-28 b3810562527858a3b3d98ffa6e9c9c5b0f4a9a8e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
   char data[1];  // An address returned to a caller
} CS_WINKERNEL_MEMBLOCK;
C_ASSERT(sizeof(CS_WINKERNEL_MEMBLOCK) == sizeof(void *) * 2);
 
 
// 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, sizeof(CS_WINKERNEL_MEMBLOCK), &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)