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
144
145
146
147
148
149
150
151
152
153
154
155
|
#pragma once
#include "KMemDriver.h"
#include <Windows.h>
#include <mutex>
#include <stdexcept>
#include <vector>
#define DEFAULT_TIMEOUT_MS ((KRNL_WAIT_TIME_US / 1000) * (KRNL_MAX_WAITS - 1))
#define INVALID_NTSTATUS (UINT32)-1
typedef enum SendRecvReturn {
SRR_INVALID = 0, SRR_SIGNALED, SRR_TIMEOUT, SRR_ERR_UEVENT, SRR_ERR_KEVENT, SRR_ERR_HEADER
} SendRecvReturn;
class KInterface
{
public:
static KInterface& getInstance()
{
static KInterface instance;
return instance;
}
KInterface();
KInterface(KInterface const&) = delete;
void operator=(KInterface const&) = delete;
bool Init();
bool Handshake();
bool Ping();
bool Processes(std::vector<PROCESS_DATA>& dest);
bool Pages(HANDLE targetPID,
std::vector<MEMORY_BASIC_INFORMATION>& dest,
PVOID start_address = NULL);
bool Modules(HANDLE targetPID,
std::vector<MODULE_DATA>& dest);
bool Exit();
bool RPM(HANDLE targetPID, PVOID address, BYTE* buf, SIZE_T size,
PKERNEL_READ_REQUEST result);
bool WPM(HANDLE targetPID, PVOID address, BYTE* buf, SIZE_T size,
PKERNEL_WRITE_REQUEST result);
bool VAlloc(HANDLE targetPID, PVOID* address, SIZE_T* size, ULONG protection);
bool VFree(HANDLE targetPID, PVOID address, SIZE_T size);
bool VUnlink(HANDLE targetPID, PVOID address);
bool MtInit() {
std::unique_lock<std::mutex> lck(m_jobLock);
return Init();
}
bool MtHandshake() {
std::unique_lock<std::mutex> lck(m_jobLock);
return Handshake();
}
bool MtPing() {
std::unique_lock<std::mutex> lck(m_jobLock);
return Ping();
}
bool MtProcesses(std::vector<PROCESS_DATA>& dest) {
std::unique_lock<std::mutex> lck(m_jobLock);
return Processes(dest);
}
bool MtPages(HANDLE targetPID, std::vector<MEMORY_BASIC_INFORMATION>& dest, PVOID start_address = NULL) {
std::unique_lock<std::mutex> lck(m_jobLock);
return Pages(targetPID, dest, start_address);
}
bool MtModules(HANDLE targetPID, std::vector<MODULE_DATA>& dest) {
std::unique_lock<std::mutex> lck(m_jobLock);
return Modules(targetPID, dest);
}
bool MtExit() {
std::unique_lock<std::mutex> lck(m_jobLock);
return Exit();
}
bool MtRPM(HANDLE targetPID, PVOID address, BYTE* buf, SIZE_T size, PKERNEL_READ_REQUEST result) {
std::unique_lock<std::mutex> lck(m_jobLock);
return RPM(targetPID, address, buf, size, result);
}
bool MtWPM(HANDLE targetPID, PVOID address, BYTE* buf, SIZE_T size, PKERNEL_WRITE_REQUEST result) {
std::unique_lock<std::mutex> lck(m_jobLock);
return WPM(targetPID, address, buf, size, result);
}
bool MtVAlloc(HANDLE targetPID, PVOID* address, SIZE_T* size, ULONG protection) {
std::unique_lock<std::mutex> lck(m_jobLock);
return VAlloc(targetPID, address, size, protection);
}
bool MtVFree(HANDLE targetPID, PVOID address, SIZE_T size) {
std::unique_lock<std::mutex> lck(m_jobLock);
return VFree(targetPID, address, size);
}
bool MtVUnlink(HANDLE targetPID, PVOID address) {
std::unique_lock<std::mutex> lck(m_jobLock);
return VUnlink(targetPID, address);
}
PVOID getBuffer();
HANDLE getKHandle();
HANDLE getUHandle();
UINT32 getLastPingValue();
UINT32 getLastNtStatus();
SendRecvReturn RecvWait(DWORD timeout = DEFAULT_TIMEOUT_MS);
void StartPingThread(void (__cdecl *onTimeout)(void));
private:
SendRecvReturn SendRecvWait(UINT32 type, DWORD timeout = DEFAULT_TIMEOUT_MS);
void PingThread(void (__cdecl *onTimeout)(void));
PVOID m_shmem = NULL;
HANDLE m_kevent = NULL, m_uevent = NULL;
UINT32 m_last_ping_value = 0;
UINT32 m_last_ntstatus = INVALID_NTSTATUS;
bool m_pingThreadStarted = false;
std::thread m_pingThread;
std::mutex m_jobLock;
};
class KMemory
{
public:
template <class T>
static T Rpm(HANDLE targetPID, PVOID address) {
T buf;
if (!KInterface::getInstance().RPM(targetPID, address, (BYTE*)&buf, sizeof buf, NULL))
throw std::runtime_error("KMemory RPM failed");
return buf;
}
template <class T>
static void Wpm(HANDLE targetPID, PVOID address, T* buf) {
if (!KInterface::getInstance().WPM(targetPID, address, (BYTE*)buf, sizeof * buf, NULL))
throw std::runtime_error("KMemory WPM failed");
}
};
class KMemoryBuf
{
public:
template <size_t SIZE>
static SSIZE_T Rpm(HANDLE targetPID, PVOID address, BYTE* dest) {
KERNEL_READ_REQUEST rr = { 0 };
if (!KInterface::getInstance().RPM(targetPID, address, &dest[0], SIZE, &rr))
return -1;
return rr.SizeRes;
}
template <size_t SIZE>
static SSIZE_T Wpm(HANDLE targetPID, PVOID address, BYTE* dest) {
KERNEL_WRITE_REQUEST wr = { 0 };
if (!KInterface::getInstance().WPM(targetPID, address, &dest[0], SIZE, &wr))
return -1;
return wr.SizeRes;
}
};
|