forked from capstone-engine/capstone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibc.cpp
142 lines (123 loc) · 2.57 KB
/
libc.cpp
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
/**
* @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)
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);
}