-
Notifications
You must be signed in to change notification settings - Fork 115
/
Copy pathprocess_env.cpp
173 lines (156 loc) · 5.98 KB
/
process_env.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "process_env.h"
#include "ntddk.h"
#include "ntdll_undoc.h"
#include "util.h"
#include <iostream>
#include <userenv.h>
#pragma comment(lib, "Userenv.lib")
bool set_params_in_peb(PVOID params_base, HANDLE hProcess, PPEB remote_peb)
{
//Write parameters address into PEB:
SIZE_T written = 0;
if (!WriteProcessMemory(hProcess, &remote_peb->ProcessParameters,
¶ms_base, sizeof(PVOID),
&written))
{
std::cout << "Cannot update Params!" << std::endl;
return false;
}
return true;
}
bool buffer_remote_peb(HANDLE hProcess, PROCESS_BASIC_INFORMATION &pi, OUT PEB &peb_copy)
{
memset(&peb_copy, 0, sizeof(PEB));
PPEB remote_peb_addr = pi.PebBaseAddress;
#ifdef _DEBUG
std::cout << "PEB address: " << (std::hex) << (ULONGLONG)remote_peb_addr << std::endl;
#endif
// Write the payload's ImageBase into remote process' PEB:
NTSTATUS status = NtReadVirtualMemory(hProcess, remote_peb_addr, &peb_copy, sizeof(PEB), NULL);
if (status != STATUS_SUCCESS)
{
std::cerr << "Cannot read remote PEB: " << GetLastError() << std::endl;
return false;
}
return true;
}
//Preserve the aligmnent! The remote address of the parameters must be the same as local.
LPVOID write_params_into_process(HANDLE hProcess, PRTL_USER_PROCESS_PARAMETERS params, DWORD protect)
{
if (params == NULL) return NULL;
PVOID buffer = params;
ULONG_PTR buffer_end = (ULONG_PTR)params + params->Length;
//params and environment in one space:
if (params->Environment) {
if ((ULONG_PTR)params > (ULONG_PTR)params->Environment) {
buffer = (PVOID)params->Environment;
}
ULONG_PTR env_end = (ULONG_PTR)params->Environment + params->EnvironmentSize;
if (env_end > buffer_end) {
buffer_end = env_end;
}
}
// copy the continuous area containing parameters + environment
SIZE_T buffer_size = buffer_end - (ULONG_PTR)buffer;
if (VirtualAllocEx(hProcess, buffer, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
if (!WriteProcessMemory(hProcess, (LPVOID)params, (LPVOID)params, params->Length, NULL)) {
std::cerr << "Writing RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (params->Environment) {
if (!WriteProcessMemory(hProcess, (LPVOID)params->Environment, (LPVOID)params->Environment, params->EnvironmentSize, NULL)) {
std::cerr << "Writing environment failed" << std::endl;
return nullptr;
}
}
return (LPVOID)params;
}
// could not copy the continuous space, try to fill it as separate chunks:
if (!VirtualAllocEx(hProcess, (LPVOID)params, params->Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
std::cerr << "Allocating RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (!WriteProcessMemory(hProcess, (LPVOID)params, (LPVOID)params, params->Length, NULL)) {
std::cerr << "Writing RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (params->Environment) {
if (!VirtualAllocEx(hProcess, (LPVOID)params->Environment, params->EnvironmentSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
std::cerr << "Allocating environment failed" << std::endl;
return nullptr;
}
if (!WriteProcessMemory(hProcess, (LPVOID)params->Environment, (LPVOID)params->Environment, params->EnvironmentSize, NULL)) {
std::cerr << "Writing environment failed" << std::endl;
return nullptr;
}
}
return (LPVOID)params;
}
bool setup_process_parameters(HANDLE hProcess, PROCESS_BASIC_INFORMATION &pi, LPWSTR targetPath)
{
//---
UNICODE_STRING uTargetPath = { 0 };
RtlInitUnicodeString(&uTargetPath, targetPath);
//---
wchar_t dirPath[MAX_PATH] = { 0 };
get_directory(targetPath, dirPath, MAX_PATH);
//if the directory is empty, set the current one
if (wcsnlen(dirPath, MAX_PATH) == 0) {
GetCurrentDirectoryW(MAX_PATH, dirPath);
}
UNICODE_STRING uCurrentDir = { 0 };
RtlInitUnicodeString(&uCurrentDir, dirPath);
//---
wchar_t dllDir[] = L"C:\\Windows\\System32";
UNICODE_STRING uDllDir = { 0 };
RtlInitUnicodeString(&uDllDir, dllDir);
//---
UNICODE_STRING uWindowName = { 0 };
wchar_t *windowName = L"Process Ghosting test!";
RtlInitUnicodeString(&uWindowName, windowName);
LPVOID environment;
CreateEnvironmentBlock(&environment, NULL, TRUE);
// fetch desktop info from current process:
PUNICODE_STRING desktopInfo = nullptr;
PPEB myPEB = NtCurrentPeb();
if (myPEB && myPEB->ProcessParameters) {
desktopInfo = &myPEB->ProcessParameters->DesktopInfo;
}
PRTL_USER_PROCESS_PARAMETERS params = nullptr;
NTSTATUS status = RtlCreateProcessParametersEx(
¶ms,
(PUNICODE_STRING)&uTargetPath,
(PUNICODE_STRING)&uDllDir,
(PUNICODE_STRING)&uCurrentDir,
(PUNICODE_STRING)&uTargetPath,
environment,
(PUNICODE_STRING)&uWindowName,
desktopInfo,
nullptr,
nullptr,
RTL_USER_PROC_PARAMS_NORMALIZED
);
if (status != STATUS_SUCCESS) {
std::cerr << "RtlCreateProcessParametersEx failed" << std::endl;
return false;
}
LPVOID remote_params = write_params_into_process(hProcess, params, PAGE_READWRITE);
if (!remote_params) {
std::cout << "[+] Cannot make a remote copy of parameters: " << GetLastError() << std::endl;
return false;
}
#ifdef _DEBUG
std::cout << "[+] Parameters mapped!" << std::endl;
#endif
if (!set_params_in_peb(remote_params, hProcess, pi.PebBaseAddress)) {
std::cout << "[+] Cannot update PEB: " << GetLastError() << std::endl;
return false;
}
#ifdef _DEBUG
if (!buffer_remote_peb(hProcess, pi, peb_copy)) {
return false;
}
std::cout << "> ProcessParameters addr: " << peb_copy.ProcessParameters << std::endl;
#endif
return true;
}