-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathNtQueryVirtualMemoryHook.txt
More file actions
123 lines (107 loc) · 4.14 KB
/
NtQueryVirtualMemoryHook.txt
File metadata and controls
123 lines (107 loc) · 4.14 KB
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
// NtQueryVirtualMemory hook function
NTSTATUS NTAPI Cloaker::NtQueryVirtualMemory_Hook(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
OUT PVOID Buffer,
IN ULONG Length,
OUT PULONG ResultLength OPTIONAL)
{
typedef NTSTATUS (NTAPI* tNtQueryVirtualMemory)(HANDLE ProcessHandle,
PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass,
PVOID Buffer, ULONG Length, PULONG ResultLength);
tNtQueryVirtualMemory pNtQueryVirtualMemory = m_pNtQueryVirtualMemory->
GetOrig<tNtQueryVirtualMemory>();
// Make a backup of the buffer (For extra security. Potentially safer
// than nulling out the buffer to hide.)
std::vector<BYTE> TempBuffer;
// Wrap in try/catch in case of access violations
try
{
std::copy(reinterpret_cast<PBYTE>(Buffer),
reinterpret_cast<PBYTE>(Buffer) + Length,
std::back_inserter(TempBuffer));
}
// In case of error just call the original API. If the above doesn't
// work then the buffer is obviously invalid so the API call will
// fail anyway, hence no more checks need to be done.
catch (...)
{
return pNtQueryVirtualMemory(ProcessHandle, BaseAddress,
MemoryInformationClass, Buffer, Length, ResultLength);
}
// Call original function
NTSTATUS Result = pNtQueryVirtualMemory(ProcessHandle, BaseAddress,
MemoryInformationClass, Buffer, Length, ResultLength);
try
{
// Don't bother trying to hide if the function failed or the process
// handle is invalid.
if (FAILED(Result) || GetProcessId(ProcessHandle) !=
GetCurrentProcessId())
{
return Result;
}
// Don't bother trying to hide if information class is irrelevant
if (MemoryInformationClass != MemoryBasicInformation &&
MemoryInformationClass != MemorySectionName)
{
return Result;
}
// Check if base address is inside any of the modules we want to hide
bool ShouldHide = false;
std::for_each(GetModuleList().begin(), GetModuleList().end(),
[&ShouldHide, BaseAddress] (Module* pModule)
{
PBYTE ModBase = reinterpret_cast<PBYTE>(pModule->m_Handle);
PBYTE ModEnd = ModBase + pModule->m_Size;
if (BaseAddress >= ModBase && BaseAddress <= ModEnd)
ShouldHide = true;
});
// Don't bother trying to hide if the module isn't in a hidden range.
if (!ShouldHide)
{
return Result;
}
// Check for section name retrieval
if (MemoryInformationClass == MemorySectionName)
{
// Restore the backup of the buffer (extra security)
std::copy(TempBuffer.begin(), TempBuffer.end(),
reinterpret_cast<PBYTE>(Buffer));
// Call original API with invalid address
return pNtQueryVirtualMemory(ProcessHandle, NULL,
MemoryInformationClass, Buffer, Length, ResultLength);
}
// MemorySectionName has already been handled and the only other
// supported information class is MemoryBasicInformation so if we
// get here that's what we have.
// Convert buffer to MEMORY_BASIC_INFORMATION
PMEMORY_BASIC_INFORMATION pMBI = static_cast<PMEMORY_BASIC_INFORMATION>(
Buffer);
// Next memory block
PVOID NextBase = reinterpret_cast<PBYTE>(pMBI->BaseAddress) +
pMBI->RegionSize;
// Return next block of memory
MEMORY_BASIC_INFORMATION NextBlock;
ULONG NextLength = 0;
Result = pNtQueryVirtualMemory(ProcessHandle, NextBase,
MemoryInformationClass, &NextBlock, sizeof(NextBlock), &NextLength);
// Set structure to look like a free block of memory
pMBI->AllocationBase = 0;
pMBI->AllocationProtect = 0;
pMBI->State = MEM_FREE;
pMBI->Protect = PAGE_NOACCESS;
pMBI->Type = 0;
// If next block is free too, add it to the region size
if (NextBlock.State == MEM_FREE)
pMBI->RegionSize += NextBlock.RegionSize;
// Return result
return Result;
}
catch (...)
{
// Return result
return Result;
}
}