@@ -133,14 +133,74 @@ static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
133
133
return Handle ;
134
134
}
135
135
136
- static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_ (IN HANDLE Process)
136
+ #define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
137
+ #define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002
138
+ #define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004
139
+ #define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010
140
+ #define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020
141
+ #define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080
142
+
143
+ static NTSTATUS CreateThreadSkipAttach (IN HANDLE ProcessHandle, IN PUSER_THREAD_START_ROUTINE StartRoutine, IN PVOID Argument)
137
144
{
138
- HANDLE hThread;
139
- CLIENT_ID ClientId;
140
145
NTSTATUS Status;
146
+ HANDLE hThread;
141
147
142
- PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
148
+ typedef NTSTATUS (NTAPI *t_NtCreateThreadEx)(
149
+ PHANDLE /* ThreadHandle */ ,
150
+ ACCESS_MASK /* DesiredAccess */ ,
151
+ POBJECT_ATTRIBUTES /* ObjectAttributes */ ,
152
+ HANDLE /* ProcessHandle */ ,
153
+ PUSER_THREAD_START_ROUTINE /* StartRoutine */ ,
154
+ PVOID /* Argument */ ,
155
+ ULONG /* CreateFlags */ ,
156
+ ULONG_PTR /* ZeroBits */ ,
157
+ SIZE_T /* StackSize */ ,
158
+ SIZE_T /* MaximumStackSize */ ,
159
+ PPS_ATTRIBUTE_LIST /* AttributeList */
160
+ );
161
+
162
+ auto p_NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress (GetModuleHandleW (L" ntdll.dll" ), " NtCreateThreadEx" );
163
+ if (p_NtCreateThreadEx)
164
+ {
165
+ // Based on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/339263/16/client/crashpad_client_win.cc#697
166
+ Status = p_NtCreateThreadEx (&hThread,
167
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
168
+ nullptr ,
169
+ ProcessHandle,
170
+ StartRoutine,
171
+ Argument,
172
+ THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
173
+ 0 ,
174
+ 0x4000 /* PAGE_SIZE * 4 */ ,
175
+ 0 ,
176
+ nullptr );
177
+ }
178
+ else
179
+ {
180
+ CLIENT_ID ClientId;
181
+ Status = RtlCreateUserThread (ProcessHandle,
182
+ NULL ,
183
+ FALSE ,
184
+ 0 ,
185
+ 0 ,
186
+ 0x4000 /* PAGE_SIZE * 4 */ ,
187
+ StartRoutine,
188
+ Argument,
189
+ &hThread,
190
+ &ClientId);
191
+ }
192
+
193
+ if (NT_SUCCESS (Status))
194
+ {
195
+ NtClose (hThread);
196
+ }
197
+
198
+ return Status;
199
+ }
143
200
201
+ static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_ (IN HANDLE Process)
202
+ {
203
+ PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
144
204
LPVOID RemoteMemory = VirtualAllocEx (Process, 0 , 0x1000 , MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ);
145
205
if (RemoteMemory)
146
206
{
@@ -156,31 +216,14 @@ static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
156
216
}
157
217
}
158
218
159
- /* Create the thread that will do the breakin */
160
- Status = RtlCreateUserThread (Process,
161
- NULL ,
162
- FALSE ,
163
- 0 ,
164
- 0 ,
165
- 0x1000 /* PAGE_SIZE */ ,
166
- RemoteBreakFunction,
167
- NULL ,
168
- &hThread,
169
- &ClientId);
170
-
171
- /* Close the handle on success */
172
- if (NT_SUCCESS (Status)) NtClose (hThread);
173
-
174
- /* Return status */
175
- return Status;
219
+ /* Create the thread that will perform the breakin (on Vista+ it will skip DllMain and TLS callbacks) */
220
+ return CreateThreadSkipAttach (Process, RemoteBreakFunction, NULL );
176
221
}
177
222
178
223
static NTSTATUS NTAPI DbgUiDebugActiveProcess_ (IN HANDLE Process)
179
224
{
180
- NTSTATUS Status;
181
-
182
225
/* Tell the kernel to start debugging */
183
- Status = NtDebugActiveProcess (Process, NtCurrentTeb ()->DbgSsReserved [1 ]);
226
+ NTSTATUS Status = NtDebugActiveProcess (Process, NtCurrentTeb ()->DbgSsReserved [1 ]);
184
227
if (NT_SUCCESS (Status))
185
228
{
186
229
/* Now break-in the process */
@@ -199,26 +242,26 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
199
242
// Source: https://github.com/mirror/reactos/blob/c6d2b35ffc91e09f50dfb214ea58237509329d6b/reactos/dll/win32/kernel32/client/debugger.c#L480
200
243
BOOL WINAPI DebugActiveProcess_ (IN DWORD dwProcessId)
201
244
{
202
- NTSTATUS Status, Status1;
203
- HANDLE Handle ;
204
-
205
245
/* Connect to the debugger */
206
- Status = DbgUiConnectToDbg ();
246
+ NTSTATUS Status = DbgUiConnectToDbg ();
207
247
if (!NT_SUCCESS (Status))
208
248
{
209
249
BaseSetLastNTError (Status);
210
250
return FALSE ;
211
251
}
212
252
213
253
/* Get the process handle */
214
- Handle = ProcessIdToHandle (dwProcessId);
215
- if (!Handle ) return FALSE ;
254
+ HANDLE Handle = ProcessIdToHandle (dwProcessId);
255
+ if (!Handle )
256
+ {
257
+ return FALSE ;
258
+ }
216
259
217
260
/* Now debug the process */
218
261
Status = DbgUiDebugActiveProcess_ (Handle );
219
262
220
263
/* Close the handle since we're done */
221
- Status1 = NtClose (Handle );
264
+ NtClose (Handle );
222
265
223
266
/* Check if debugging worked */
224
267
if (!NT_SUCCESS (Status))
0 commit comments