• 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 	char data[0];
24 #pragma warning(pop)
25 };
26 
27 EXTERN_C
__drv_allocatesMem(pBlock)28 __drv_when(return!=0, __drv_allocatesMem(pBlock))
29 __checkReturn
30 __drv_maxIRQL(DISPATCH_LEVEL)
31 __bcount_opt(size)
32 void*
33 __cdecl malloc(
34 	__in size_t size
35 	)
36 {
37 	/* A specially crafted size value can trigger the overflow.
38 	If the sum in a value that overflows or underflows the capacity of the type,
39 	the function returns nullptr. */
40 	size_t number_of_bytes = 0;
41 	if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
42 		return nullptr;
43 	}
44 	MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
45 		ExAllocatePoolWithTag(
46 			NonPagedPoolNxCacheAligned,
47 			number_of_bytes,
48 			_LIBC_POOL_TAG));
49 
50 	if (nullptr == pBlock)
51 		return nullptr;
52 
53 	pBlock->size = size;
54 	return pBlock->data;
55 }
56 
57 EXTERN_C
__drv_allocatesMem(p)58 __drv_when(return != 0, __drv_allocatesMem(p))
59 __checkReturn
60 __drv_maxIRQL(DISPATCH_LEVEL)
61 __bcount_opt(size * n)
62 void*
63 __cdecl calloc(size_t n, size_t size)
64 {
65 	size_t total = n * size;
66 	void *p = malloc(total);
67 
68 	if (!p) return NULL;
69 
70 	return memset(p, 0, total);
71 }
72 
73 EXTERN_C
__drv_allocatesMem(inblock)74 __drv_when(return!=0, __drv_allocatesMem(inblock))
75 __checkReturn
76 __drv_maxIRQL(DISPATCH_LEVEL)
77 __bcount_opt(size)
78 void*
79 __cdecl realloc(
80 	__in_opt void* ptr,
81 	__in size_t size
82 	)
83 {
84 	if (!ptr)
85 		return malloc(size);
86 
87 	std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
88 
89 	// alloc new block
90 	void* mem = malloc(size);
91 	if (!mem)
92 		return nullptr;
93 
94 	// copy from old one, not overflow ..
95 	memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
96 	return mem;
97 }
98 
99 EXTERN_C
__drv_maxIRQL(DISPATCH_LEVEL)100 __drv_maxIRQL(DISPATCH_LEVEL)
101 void
102 __cdecl free(
103 	__inout_opt __drv_freesMem(Mem) void* ptr
104 	)
105 {
106 	if (ptr)
107 		ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
108 }
109 
110 #pragma warning(pop)
111 
__drv_allocatesMem(ptr)112 __drv_when(return!=0, __drv_allocatesMem(ptr))
113 __checkReturn
114 __drv_maxIRQL(DISPATCH_LEVEL)
115 __bcount_opt(size)
116 void*
117 __cdecl operator new(
118 	__in size_t size
119 	)
120 {
121 	return malloc(size);
122 }
123 
__drv_maxIRQL(DISPATCH_LEVEL)124 __drv_maxIRQL(DISPATCH_LEVEL)
125 void
126 __cdecl operator delete(
127 	__inout void* ptr
128 	)
129 {
130 	free(ptr);
131 }
132 
133 int
vsnprintf(char * buffer,size_t count,const char * format,va_list argptr)134 __cdecl vsnprintf(
135 	char *buffer,
136 	size_t count,
137 	const char *format,
138 	va_list argptr
139 )
140 {
141 	return vsprintf_s(buffer, count, format, argptr);
142 }
143