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 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 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 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 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 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 124 __drv_maxIRQL(DISPATCH_LEVEL) 125 void 126 __cdecl operator delete( 127 __inout void* ptr 128 ) 129 { 130 free(ptr); 131 } 132 133 int 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