-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRBoxRun.cpp
151 lines (111 loc) · 4 KB
/
RBoxRun.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
//
// Created by hx1997 on 2017/11/12.
//
#include <thread>
#include "RBoxRun.h"
#include "RBoxIOCPNotifs.h"
// Forward declarations
DWORD RunWithLowToken(HANDLE hToken, LPCWSTR szPath, HANDLE &hProcess, HANDLE &hThread);
DWORD Sandbox::RunSandboxed(LPCWSTR szPath, BOOL bDropRights) {
DWORD fStatus;
HANDLE hToken, hNewToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &hToken))
return GetLastError();
if (bDropRights) {
// No need to duplicate the token since we are creating a NEW one based on the original
RestrictToken(hToken, hNewToken, true);
if (hNewToken)
hToken = hNewToken;
} else {
if (!DuplicateTokenEx(hToken, 0, nullptr, SecurityAnonymous, TokenPrimary, &hToken)) {
CloseHandle(hToken);
return GetLastError();
}
}
HANDLE hProcess;
HANDLE hThread;
if ((fStatus = RunWithLowToken(hToken, szPath, hProcess, hThread)) != ERROR_SUCCESS) {
goto Cleanup;
}
if ((fStatus = this->job->ConfineProcessToJob(hProcess)) != ERROR_SUCCESS) {
TerminateProcess(hProcess, ERROR_SUCCESS);
goto Cleanup;
}
if ((fStatus = this->job->RegisterJobNotify()) != ERROR_SUCCESS) {
TerminateProcess(hProcess, ERROR_SUCCESS);
goto Cleanup;
}
ResumeThread(hThread);
Cleanup:
CloseHandle(hProcess);
CloseHandle(hThread);
CloseHandle(hToken);
CloseHandle(hNewToken);
return fStatus;
}
DWORD RunWithLowToken(HANDLE hToken, LPCWSTR szPath, HANDLE &hProcess, HANDLE &hThread) {
DWORD fStatus = 0;
if ((fStatus = SetTokenLowIL(hToken)) != ERROR_SUCCESS)
return fStatus;
STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
si.cb = sizeof(si);
if (!CreateProcessAsUser(hToken, szPath, nullptr, nullptr, nullptr, false,
CREATE_BREAKAWAY_FROM_JOB | CREATE_SUSPENDED, nullptr, nullptr, &si, &pi))
return GetLastError();
hProcess = pi.hProcess;
hThread = pi.hThread;
return fStatus;
}
DWORD Sandbox::StopSandbox() {
this->job->StopJob();
return ERROR_SUCCESS;
}
DWORD Sandbox::Job::StopJob() {
TerminateJobObject(this->hJob, ERROR_SUCCESS);
CloseHandle(this->hJob);
this->hJob = nullptr;
return ERROR_SUCCESS;
}
DWORD Sandbox::Job::ConfineProcessToJob(HANDLE hProcess) {
if (!hProcess)
return ERROR_INVALID_HANDLE;
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
if (!this->hJob)
if (!(this->hJob = CreateJobObject(&sa, nullptr)))
return GetLastError();
if (!AssignProcessToJobObject(this->hJob, hProcess)) {
CloseHandle(this->hJob);
return GetLastError();
}
if (!SetJobLimits(JOB_OBJECT_UILIMIT_EXITWINDOWS)) {
CloseHandle(this->hJob);
return GetLastError();
}
return ERROR_SUCCESS;
}
int Sandbox::Job::SetJobLimits(DWORD dwUILimits) {
JOBOBJECT_BASIC_UI_RESTRICTIONS jbui = {};
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {};
jbui.UIRestrictionsClass = dwUILimits;
if (!SetInformationJobObject(this->hJob, JobObjectBasicUIRestrictions, &jbui, sizeof(jbui)))
return 0;
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (!SetInformationJobObject(this->hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
return 0;
return 1;
}
DWORD Sandbox::Job::RegisterJobNotify() {
if (!(this->hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, NULL, NULL))) {
CloseHandle(this->hJob);
return GetLastError();
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp = {this->hJob, this->hIocp};
if (!SetInformationJobObject(this->hJob, JobObjectAssociateCompletionPortInformation, &joacp, sizeof(joacp)))
return GetLastError();
std::thread t1(PollCompletionPort, this->hIocp);
t1.detach();
return ERROR_SUCCESS;
}