You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
2.6 KiB
144 lines
2.6 KiB
3 years ago
|
/**
|
||
|
* @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);
|
||
|
}
|