• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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