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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/**
* @file libc.cpp
* @author created by: Peter Hlavaty
*/
#include "libc.h"
#include <memory>
#include <Ntintsafe.h>
#pragma warning(push)
#pragma warning (disable : 4565)
#ifndef _LIBC_POOL_TAG
#define _LIBC_POOL_TAG 'colM'
#endif
// very nice for debug forensics!
struct MEMBLOCK
{
size_t size;
#pragma warning(push)
#pragma warning (disable : 4200)
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT))
char data[0];
#pragma warning(pop)
};
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(pBlock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl malloc(
__in size_t size
)
{
/* 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 nullptr. */
size_t number_of_bytes = 0;
if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(MEMBLOCK), &number_of_bytes))){
return nullptr;
}
MEMBLOCK *pBlock = static_cast<MEMBLOCK*>(
ExAllocatePoolWithTag(
NonPagedPoolNxCacheAligned,
number_of_bytes,
_LIBC_POOL_TAG));
if (nullptr == pBlock)
return nullptr;
pBlock->size = size;
return pBlock->data;
}
EXTERN_C
__drv_when(return != 0, __drv_allocatesMem(p))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size * n)
void*
__cdecl calloc(size_t n, size_t size)
{
size_t total = n * size;
void *p = malloc(total);
if (!p) return NULL;
return memset(p, 0, total);
}
EXTERN_C
__drv_when(return!=0, __drv_allocatesMem(inblock))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl realloc(
__in_opt void* ptr,
__in size_t size
)
{
if (!ptr)
return malloc(size);
std::unique_ptr<unsigned char> inblock = std::unique_ptr<unsigned char>(static_cast<unsigned char*>(ptr));
// alloc new block
void* mem = malloc(size);
if (!mem)
return nullptr;
// copy from old one, not overflow ..
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data)->size, size));
return mem;
}
EXTERN_C
__drv_maxIRQL(DISPATCH_LEVEL)
void
__cdecl free(
__inout_opt __drv_freesMem(Mem) void* ptr
)
{
if (ptr)
ExFreePoolWithTag(CONTAINING_RECORD(ptr, MEMBLOCK, data), _LIBC_POOL_TAG);
}
#pragma warning(pop)
__drv_when(return!=0, __drv_allocatesMem(ptr))
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
__bcount_opt(size)
void*
__cdecl operator new(
__in size_t size
)
{
return malloc(size);
}
__drv_maxIRQL(DISPATCH_LEVEL)
void
__cdecl operator delete(
__inout void* ptr
)
{
free(ptr);
}
int
__cdecl vsnprintf(
char *buffer,
size_t count,
const char *format,
va_list argptr
)
{
return vsprintf_s(buffer, count, format, argptr);
}
|