Skip to content

Commit a260728

Browse files
committed
improve safe attach option on Vista+
1 parent f835fc8 commit a260728

File tree

1 file changed

+74
-31
lines changed

1 file changed

+74
-31
lines changed

TitanEngine/Global.Debugger.cpp

+74-31
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,74 @@ static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
133133
return Handle;
134134
}
135135

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)
137144
{
138-
HANDLE hThread;
139-
CLIENT_ID ClientId;
140145
NTSTATUS Status;
146+
HANDLE hThread;
141147

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+
}
143200

201+
static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
202+
{
203+
PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
144204
LPVOID RemoteMemory = VirtualAllocEx(Process, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ);
145205
if(RemoteMemory)
146206
{
@@ -156,31 +216,14 @@ static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
156216
}
157217
}
158218

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);
176221
}
177222

178223
static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
179224
{
180-
NTSTATUS Status;
181-
182225
/* Tell the kernel to start debugging */
183-
Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]);
226+
NTSTATUS Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]);
184227
if(NT_SUCCESS(Status))
185228
{
186229
/* Now break-in the process */
@@ -199,26 +242,26 @@ static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
199242
// Source: https://github.com/mirror/reactos/blob/c6d2b35ffc91e09f50dfb214ea58237509329d6b/reactos/dll/win32/kernel32/client/debugger.c#L480
200243
BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
201244
{
202-
NTSTATUS Status, Status1;
203-
HANDLE Handle;
204-
205245
/* Connect to the debugger */
206-
Status = DbgUiConnectToDbg();
246+
NTSTATUS Status = DbgUiConnectToDbg();
207247
if(!NT_SUCCESS(Status))
208248
{
209249
BaseSetLastNTError(Status);
210250
return FALSE;
211251
}
212252

213253
/* 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+
}
216259

217260
/* Now debug the process */
218261
Status = DbgUiDebugActiveProcess_(Handle);
219262

220263
/* Close the handle since we're done */
221-
Status1 = NtClose(Handle);
264+
NtClose(Handle);
222265

223266
/* Check if debugging worked */
224267
if(!NT_SUCCESS(Status))

0 commit comments

Comments
 (0)