102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
nt_process.c
Go to the documentation of this file.
1#include <dttr_errors.h>
2#include <dttr_loader.h>
3#include <dttr_log.h>
4#include <string.h>
5#include <windows.h>
6
7#define PS_ATTRIBUTE_IMAGE_NAME 0x00020005
8#define PS_ATTRIBUTE_CLIENT_ID 0x00010003
9#define RTL_USER_PROC_PARAMS_NORMALIZED 0x01
10#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
11#define PEB_SHIM_DATA_OFFSET 0x1E8
12
13static const WCHAR NT_PATH_PREFIX[] = L"\\??\\";
14
15typedef LONG NTSTATUS;
16#define NT_SUCCESS(s) ((NTSTATUS)(s) >= 0)
17
18typedef struct {
19 USHORT length;
20 USHORT max_length;
21 PWSTR buffer;
23
32
33typedef struct {
34 HANDLE process;
35 HANDLE thread;
36} client_id;
37
38typedef struct {
40 SIZE_T size;
41 union {
42 ULONG value;
43 PVOID value_ptr;
44 };
45
47} attribute;
48
49typedef struct {
53
54typedef struct {
55 SIZE_T size;
56 ULONG state;
57 union {
58 struct {
61 } init_state;
62 UCHAR reserved[64];
63 };
65
67 PHANDLE,
68 PHANDLE,
69 ACCESS_MASK,
70 ACCESS_MASK,
73 ULONG,
74 ULONG,
75 PVOID,
78);
79
81 PVOID *,
86 PVOID,
91 ULONG
92);
93
95typedef VOID(NTAPI *rtl_init_unicode_string_fn)(unicode_string *, PCWSTR);
96
97#define RESOLVE(module, type, name) \
98 ((type)DTTR_UNWRAP_WINAPI_EXISTS(GetProcAddress(module, name)))
99
101 WCHAR *nt_path,
102 size_t nt_path_size,
103 WCHAR *cwd,
104 size_t cwd_size,
105 const WCHAR *image_name
106) {
107 WCHAR full_path[MAX_PATH];
108 const DWORD resolved_len = GetFullPathNameW(image_name, MAX_PATH, full_path, NULL);
109 if (resolved_len == 0 || resolved_len >= MAX_PATH) {
110 DTTR_FATAL("Game path is too long");
111 }
112
113 const size_t full_path_len = wcslen(full_path);
114 if (full_path_len + 5 > nt_path_size || full_path_len + 1 > cwd_size) {
115 DTTR_FATAL("Game path is too long");
116 }
117
118 memcpy(nt_path, NT_PATH_PREFIX, 4 * sizeof(WCHAR));
119 memcpy(nt_path + 4, full_path, (full_path_len + 1) * sizeof(WCHAR));
120
121 memcpy(cwd, full_path, (full_path_len + 1) * sizeof(WCHAR));
122 WCHAR *const last_sep = wcsrchr(cwd, L'\\');
123 if (!last_sep) {
124 DTTR_FATAL("Game path is missing a parent directory");
125 }
126
127 last_sep[1] = L'\0';
128}
129
131 HANDLE process,
132 uintptr_t peb_addr,
133 const char *shim_data,
134 size_t shim_data_len
135) {
136 LPVOID remote_shim = DTTR_UNWRAP_WINAPI_EXISTS(VirtualAllocEx(
137 process,
138 NULL,
139 shim_data_len,
140 MEM_COMMIT | MEM_RESERVE,
141 PAGE_READWRITE
142 ));
143
145 WriteProcessMemory(process, remote_shim, shim_data, shim_data_len, NULL)
146 );
147
148 DTTR_UNWRAP_WINAPI_NONZERO(WriteProcessMemory(
149 process,
150 (LPVOID)(peb_addr + PEB_SHIM_DATA_OFFSET),
151 &remote_shim,
152 sizeof(PVOID),
153 NULL
154 ));
155
157 "Shim data (%u bytes) written to PEB->pShimData at 0x%08X",
158 (unsigned)shim_data_len,
159 (unsigned)(uintptr_t)remote_shim
160 );
161}
162
164 const WCHAR *image_name,
165 const char *shim_data,
166 size_t shim_data_len,
167 PROCESS_INFORMATION *child_info
168) {
170 "Spawning game process: NtCreateUserProcess (%u bytes shim data)",
171 (unsigned)shim_data_len
172 );
173
174 HMODULE ntdll = DTTR_UNWRAP_WINAPI_EXISTS(GetModuleHandleA("ntdll.dll"));
175
176 const nt_create_user_process_fn nt_create_user_process = RESOLVE(
177 ntdll,
179 "NtCreateUserProcess"
180 );
181
182 const rtl_create_process_parameters_ex_fn rtl_create_process_parameters_ex = RESOLVE(
183 ntdll,
185 "RtlCreateProcessParametersEx"
186 );
187
188 const rtl_destroy_process_parameters_fn rtl_destroy_process_parameters = RESOLVE(
189 ntdll,
191 "RtlDestroyProcessParameters"
192 );
193
194 const rtl_init_unicode_string_fn rtl_init_unicode_string = RESOLVE(
195 ntdll,
197 "RtlInitUnicodeString"
198 );
199
200 WCHAR nt_path[MAX_PATH + 8];
201 WCHAR cwd[MAX_PATH];
203 nt_path,
204 sizeof(nt_path) / sizeof(nt_path[0]),
205 cwd,
206 sizeof(cwd) / sizeof(cwd[0]),
207 image_name
208 );
209
210 unicode_string us_image, us_cmd, us_cwd;
211 rtl_init_unicode_string(&us_image, nt_path);
212 rtl_init_unicode_string(&us_cmd, image_name);
213 rtl_init_unicode_string(&us_cwd, cwd);
214
215 DTTR_LOG_DEBUG("NT image path: %ls", nt_path);
216 DTTR_LOG_DEBUG("Working directory: %ls", cwd);
217
218 PVOID params = NULL;
219 NTSTATUS status = rtl_create_process_parameters_ex(
220 &params,
221 &us_image,
222 NULL,
223 &us_cwd,
224 &us_cmd,
225 NULL,
226 NULL,
227 NULL,
228 NULL,
229 NULL,
231 );
232 if (!NT_SUCCESS(status)) {
233 DTTR_FATAL("RtlCreateProcessParametersEx failed: 0x%08lX", (unsigned long)status);
234 }
235
236 client_id client_id = {0};
237 attribute_list attr_list = {0};
238
239 attr_list.total_length = sizeof(attr_list);
240 attr_list.attributes[0] = (attribute){
242 us_image.length,
243 {.value_ptr = us_image.buffer},
244 NULL
245 };
246 attr_list.attributes[1] = (attribute){
248 sizeof(client_id),
249 {.value_ptr = &client_id},
250 NULL
251 };
252
254 create_info.size = sizeof(create_info);
255
256 HANDLE process = NULL, thread = NULL;
257 status = nt_create_user_process(
258 &process,
259 &thread,
260 PROCESS_ALL_ACCESS,
261 THREAD_ALL_ACCESS,
262 NULL,
263 NULL,
264 0,
266 params,
268 &attr_list
269 );
270 rtl_destroy_process_parameters(params);
271 if (!NT_SUCCESS(status)) {
272 DTTR_FATAL("NtCreateUserProcess failed: 0x%08lX", (unsigned long)status);
273 }
274
275 child_info->hProcess = process;
276 child_info->hThread = thread;
277 child_info->dwProcessId = (DWORD)(ULONG_PTR)client_id.process;
278 child_info->dwThreadId = (DWORD)(ULONG_PTR)client_id.thread;
280 "Process created: PID=%lu, TID=%lu",
281 child_info->dwProcessId,
282 child_info->dwThreadId
283 );
284
285 CONTEXT thread_context = {.ContextFlags = CONTEXT_INTEGER};
286 DTTR_UNWRAP_WINAPI_NONZERO(GetThreadContext(thread, &thread_context));
287
288 const uintptr_t peb_addr = (uintptr_t)thread_context.Ebx;
289 write_remote_shim_data(process, peb_addr, shim_data, shim_data_len);
290}
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
#define DTTR_UNWRAP_WINAPI_NONZERO(result)
Definition dttr_errors.h:75
#define DTTR_UNWRAP_WINAPI_EXISTS(result)
Definition dttr_errors.h:79
#define DTTR_FATAL(error_message,...)
Definition dttr_errors.h:30
#define DTTR_LOG_DEBUG(...)
Definition dttr_log.h:28
#define PS_ATTRIBUTE_IMAGE_NAME
Definition nt_process.c:7
static void write_remote_shim_data(HANDLE process, uintptr_t peb_addr, const char *shim_data, size_t shim_data_len)
Definition nt_process.c:130
#define PS_ATTRIBUTE_CLIENT_ID
Definition nt_process.c:8
#define RESOLVE(module, type, name)
Definition nt_process.c:97
NTSTATUS(NTAPI * rtl_destroy_process_parameters_fn)(PVOID)
Definition nt_process.c:94
#define RTL_USER_PROC_PARAMS_NORMALIZED
Definition nt_process.c:9
NTSTATUS(NTAPI * nt_create_user_process_fn)(PHANDLE, PHANDLE, ACCESS_MASK, ACCESS_MASK, object_attributes *, object_attributes *, ULONG, ULONG, PVOID, create_info *, attribute_list *)
Definition nt_process.c:66
VOID(NTAPI * rtl_init_unicode_string_fn)(unicode_string *, PCWSTR)
Definition nt_process.c:95
LONG NTSTATUS
Definition nt_process.c:15
static const WCHAR NT_PATH_PREFIX[]
Definition nt_process.c:13
#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED
Definition nt_process.c:10
#define PEB_SHIM_DATA_OFFSET
Definition nt_process.c:11
void DTTR_Compat_CreateProcess(const WCHAR *image_name, const char *shim_data, size_t shim_data_len, PROCESS_INFORMATION *child_info)
Definition nt_process.c:163
static void resolve_nt_path_and_cwd(WCHAR *nt_path, size_t nt_path_size, WCHAR *cwd, size_t cwd_size, const WCHAR *image_name)
Definition nt_process.c:100
NTSTATUS(NTAPI * rtl_create_process_parameters_ex_fn)(PVOID *, unicode_string *, unicode_string *, unicode_string *, unicode_string *, PVOID, unicode_string *, unicode_string *, unicode_string *, unicode_string *, ULONG)
Definition nt_process.c:80
#define NT_SUCCESS(s)
Definition nt_process.c:16
SIZE_T total_length
Definition nt_process.c:50
attribute attributes[2]
Definition nt_process.c:51
SIZE_T size
Definition nt_process.c:40
PSIZE_T return_length
Definition nt_process.c:46
ULONG ps_attribute
Definition nt_process.c:39
PVOID value_ptr
Definition nt_process.c:43
ULONG value
Definition nt_process.c:42
HANDLE thread
Definition nt_process.c:35
HANDLE process
Definition nt_process.c:34
ULONG additional_file_access
Definition nt_process.c:60
SIZE_T size
Definition nt_process.c:55
ULONG state
Definition nt_process.c:56
ULONG init_flags
Definition nt_process.c:59
UCHAR reserved[64]
Definition nt_process.c:62
unicode_string * object_name
Definition nt_process.c:27
PVOID security_descriptor
Definition nt_process.c:29
HANDLE root_directory
Definition nt_process.c:26
USHORT max_length
Definition nt_process.c:20