@@ -67,7 +67,7 @@ public static Process StartRedirected(string fileName, string arguments, string
67
67
68
68
public static Process StartAttached ( string filename , string arguments )
69
69
{
70
- Logger . Instance . Log ( $ "Process Start: { filename } { arguments } ", LogLevel . Debug ) ;
70
+ Logger . Instance . Log ( $ "Process Start: { filename } { arguments } ", LogLevel . Debug ) ;
71
71
var process = new Process ( ) ;
72
72
process . StartInfo = new ProcessStartInfo ( filename )
73
73
{
@@ -128,7 +128,7 @@ public static Process StartWithCredentials(string filename, string arguments, st
128
128
CreateNoWindow = ! InputArguments . Debug ,
129
129
} ) ;
130
130
}
131
- catch ( Win32Exception ex )
131
+ catch ( Win32Exception ex )
132
132
{
133
133
if ( ex . NativeErrorCode == 1326 )
134
134
throw new ApplicationException ( "The user name or password is incorrect." ) ;
@@ -332,7 +332,7 @@ private static SafeProcessHandle CreateProcessWithToken(IntPtr newToken, string
332
332
return new SafeProcessHandle ( processInformation . hProcess , true ) ;
333
333
}
334
334
335
- internal static SafeProcessHandle CreateProcessAsUserWithFlags ( string lpApplicationName , string args , ProcessApi . CreateProcessFlags dwCreationFlags , out PROCESS_INFORMATION pInfo )
335
+ internal static void CreateProcessForTokenReplacement ( string lpApplicationName , string args , ProcessApi . CreateProcessFlags dwCreationFlags , out SafeProcessHandle processHandle , out SafeHandle threadHandle , out int processId )
336
336
{
337
337
var sInfoEx = new ProcessApi . STARTUPINFOEX ( ) ;
338
338
sInfoEx . StartupInfo . cb = Marshal . SizeOf ( sInfoEx ) ;
@@ -342,7 +342,9 @@ internal static SafeProcessHandle CreateProcessAsUserWithFlags(string lpApplicat
342
342
pSec . nLength = Marshal . SizeOf ( pSec ) ;
343
343
tSec . nLength = Marshal . SizeOf ( tSec ) ;
344
344
345
- // Set more restrictive Security Descriptor
345
+ // Set a more restrictive Security Descriptor:
346
+ // - This code runs at medium integrity, so we dont have permissions to change the SDACL to High integrity level.
347
+ // - We will do that in TokenSwitcher.ReplaceProcessToken.
346
348
string sddl = "D:(D;;GAFAWD;;;S-1-1-0)" ; // Deny Generic-All, File-All, and Write-Dac to everyone.
347
349
348
350
IntPtr sd_ptr = new IntPtr ( ) ;
@@ -354,15 +356,43 @@ internal static SafeProcessHandle CreateProcessAsUserWithFlags(string lpApplicat
354
356
355
357
var command = $ "{ lpApplicationName } { args } ";
356
358
357
- Logger . Instance . Log ( $ "{ nameof ( CreateProcessAsUserWithFlags ) } : { lpApplicationName } { args } ", LogLevel . Debug ) ;
359
+ PROCESS_INFORMATION pInfo ;
360
+ Logger . Instance . Log ( $ "Creating target process: { lpApplicationName } { args } ", LogLevel . Debug ) ;
358
361
if ( ! ProcessApi . CreateProcess ( null , command , ref pSec , ref tSec , false , dwCreationFlags , IntPtr . Zero , null , ref sInfoEx , out pInfo ) )
359
362
{
360
363
throw new Win32Exception ( ( int ) ConsoleApi . GetLastError ( ) ) ;
361
364
}
362
365
363
- return new SafeProcessHandle ( pInfo . hProcess , true ) ;
364
- }
366
+ var currentProcessHandle = ProcessApi . GetCurrentProcess ( ) ;
367
+
368
+ if ( ! DuplicateHandle (
369
+ currentProcessHandle , // Source process handle is the current process
370
+ pInfo . hProcess , // The handle to duplicate
371
+ currentProcessHandle , // Target process handle is also the current process
372
+ out var restrictedProcessHandle , // The duplicated handle with desired access rights
373
+ 0x1000 | 0x00100000 | 0x0001 , // Desired access: PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE
374
+ false , // The handle is not inheritable
375
+ 1 ) ) // dwOptions: auto close pInfo.hProcess.
376
+ {
377
+ throw new Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
378
+ }
365
379
380
+ if ( ! DuplicateHandle (
381
+ currentProcessHandle , // Source process handle is the current process
382
+ pInfo . hThread , // The thread handle to duplicate
383
+ currentProcessHandle , // Target process handle is also the current process
384
+ out var restrictedThreadHandle , // The duplicated handle with desired access rights
385
+ 0x0002 , // Desired access: THREAD_SUSPEND_RESUME
386
+ false , // The handle is not inheritable
387
+ 1 ) ) // dwOptions: auto close pInfo.hThread.
388
+ {
389
+ throw new Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
390
+ }
391
+
392
+ processHandle = new SafeProcessHandle ( restrictedProcessHandle , true ) ;
393
+ threadHandle = new Native . SafeThreadHandle ( restrictedThreadHandle ) ;
394
+
395
+ processId = pInfo . dwProcessId ;
396
+ }
366
397
}
367
398
}
368
-
0 commit comments