1 /**
2 * @file libc.cpp
3 * @author created by: Peter Hlavaty
4 */
5
6 #include "libc.h"
7 #include <memory>
8 #include <Ntintsafe.h>
9
10 #pragma warning(push)
11 #pragma warning (disable : 4565)
12
13 #ifndef _LIBC_POOL_TAG
14 #define _LIBC_POOL_TAG 'colM'
15 #endif
16
17 // very nice for debug forensics!
18 struct MEMBLOCK
19 {
20 size_t size;
21 #pragma warning(push)
22 #pragma warning (disable : 4200)
23 __declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
24 char data[0];
25 #pragma warning(pop)
26 };
27
28 EXTERN_C
__drv_allocatesMem(pBlock)29 __drv_when(return!=0, __drv_allocatesMem(pBlock))
30 __checkReturn
31 __drv_maxIRQL(DISPATCH_LEVEL)
32 __bcount_opt(size)
33 void*
34 __cdecl malloc(
35 __in size_t size
36 )
37 {
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 nullptr. */
41 size_t number_of_bytes = 0;
42 if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
43 return nullptr;
44 }
45 MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
46 ExAllocatePoolWithTag(
47 NonPagedPoolNxCacheAligned,
48 number_of_bytes,
49 _LIBC_POOL_TAG));
50
51 if (nullptr == pBlock)
52 return nullptr;
53
54 pBlock->size = size;
55 return pBlock->data;
56 }
57
58 EXTERN_C
__drv_allocatesMem(p)59 __drv_when(return != 0, __drv_allocatesMem(p))
60 __checkReturn
61 __drv_maxIRQL(DISPATCH_LEVEL)
62 __bcount_opt(size * n)
63 void*
64 __cdecl calloc(size_t n, size_t size)
65 {
66 size_t total = n * size;
67 void *p = malloc(total);
68
69 if (!p) return NULL;
70
71 return memset(p, 0, total);
72 }
73
74 EXTERN_C
__drv_allocatesMem(inblock)75 __drv_when(return!=0, __drv_allocatesMem(inblock))
76 __checkReturn
77 __drv_maxIRQL(DISPATCH_LEVEL)
78 __bcount_opt(size)
79 void*
80 __cdecl realloc(
81 __in_opt void* ptr,
82 __in size_t size
83 )
84 {
85 if (!ptr)
86 return malloc(size);
87
88 std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
89
90 // alloc new block
91 void* mem = malloc(size);
92 if (!mem)
93 return nullptr;
94
95 // copy from old one, not overflow ..
96 memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
97 return mem;
98 }
99
100 EXTERN_C
__drv_maxIRQL(DISPATCH_LEVEL)101 __drv_maxIRQL(DISPATCH_LEVEL)
102 void
103 __cdecl free(
104 __inout_opt __drv_freesMem(Mem) void* ptr
105 )
106 {
107 if (ptr)
108 ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
109 }
110
111 #pragma warning(pop)
112
__drv_allocatesMem(ptr)113 __drv_when(return!=0, __drv_allocatesMem(ptr))
114 __checkReturn
115 __drv_maxIRQL(DISPATCH_LEVEL)
116 __bcount_opt(size)
117 void*
118 __cdecl operator new(
119 __in size_t size
120 )
121 {
122 return malloc(size);
123 }
124
__drv_maxIRQL(DISPATCH_LEVEL)125 __drv_maxIRQL(DISPATCH_LEVEL)
126 void
127 __cdecl operator delete(
128 __inout void* ptr
129 )
130 {
131 free(ptr);
132 }
133
134 int
vsnprintf(char * buffer,size_t count,const char * format,va_list argptr)135 __cdecl vsnprintf(
136 char *buffer,
137 size_t count,
138 const char *format,
139 va_list argptr
140 )
141 {
142 return vsprintf_s(buffer, count, format, argptr);
143 }
144