Skip to content

Commit ab7ccd3

Browse files
committed
Added basic Silo initialization.
1 parent 4174256 commit ab7ccd3

4 files changed

Lines changed: 260 additions & 4 deletions

File tree

NtApiDotNet/NtJob.cs

Lines changed: 160 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,136 @@ public static NtJob Open(string path, NtObject root)
154154
{
155155
return Open(path, root, JobAccessRights.MaximumAllowed);
156156
}
157+
158+
/// <summary>
159+
/// Create and initialize a Silo,
160+
/// </summary>
161+
/// <param name="root_dir_flags">Flags for root directory.</param>
162+
/// <param name="throw_on_error">True to throw on error.</param>
163+
/// <returns>The Job object.</returns>
164+
public static NtResult<NtJob> CreateSilo(SiloObjectRootDirectoryControlFlags root_dir_flags, bool throw_on_error)
165+
{
166+
using (var job = Create(null, JobAccessRights.MaximumAllowed, throw_on_error))
167+
{
168+
if (!job.IsSuccess)
169+
return job;
170+
return job.Result.InitializeSilo(root_dir_flags, false).CreateResult(throw_on_error, () => job.Result.Duplicate());
171+
}
172+
}
173+
174+
/// <summary>
175+
/// Create an initialize a Silo,
176+
/// </summary>
177+
/// <param name="root_dir_flags">Flags for root directory.</param>
178+
/// <returns>The Job object.</returns>
179+
public static NtJob CreateSilo(SiloObjectRootDirectoryControlFlags root_dir_flags)
180+
{
181+
return CreateSilo(root_dir_flags, true).Result;
182+
}
183+
157184
#endregion
158185

159186
#region Public Methods
187+
/// <summary>
188+
/// Convert Job object into a Silo
189+
/// </summary>
190+
/// <param name="throw_on_error">True to throw on error.</param>
191+
/// <returns>The NT status code.</returns>
192+
public NtStatus CreateSilo(bool throw_on_error)
193+
{
194+
return NtSystemCalls.NtSetInformationJobObject(Handle, JobObjectInformationClass.JobObjectCreateSilo,
195+
SafeHGlobalBuffer.Null, 0).ToNtException(throw_on_error);
196+
}
197+
160198
/// <summary>
161199
/// Convert Job object into a Silo
162200
/// </summary>
163201
public void CreateSilo()
164202
{
165-
NtSystemCalls.NtSetInformationJobObject(Handle, JobObjectInformationClass.JobObjectCreateSilo,
166-
SafeHGlobalBuffer.Null, 0).ToNtException();
203+
CreateSilo(true);
204+
}
205+
206+
/// <summary>
207+
/// Initialize a Silo,
208+
/// </summary>
209+
/// <param name="root_dir_flags">Flags for root directory.</param>
210+
/// <param name="throw_on_error">True to throw on error.</param>
211+
/// <returns>The NT status code.</returns>
212+
public NtStatus InitializeSilo(SiloObjectRootDirectoryControlFlags root_dir_flags, bool throw_on_error)
213+
{
214+
NtStatus status = SetLimitFlags(JobObjectLimitFlags.Application, throw_on_error);
215+
if (!status.IsSuccess())
216+
return status;
217+
status = CreateSilo(throw_on_error);
218+
if (!status.IsSuccess())
219+
return status;
220+
status = AssignProcessPseudoHandle(throw_on_error);
221+
if (!status.IsSuccess())
222+
return status;
223+
return SetSiloObjectRootDirectory(root_dir_flags, throw_on_error);
224+
}
225+
226+
/// <summary>
227+
/// Initialize a Silo,
228+
/// </summary>
229+
/// <param name="root_dir_flags">Flags for root directory.</param>
230+
public void InitializeSilo(SiloObjectRootDirectoryControlFlags root_dir_flags)
231+
{
232+
InitializeSilo(root_dir_flags, true);
233+
}
234+
235+
/// <summary>
236+
/// Initialize a Silo to a Server Silo.
237+
/// </summary>
238+
/// <param name="delete_event">Event to signal when silo deleted.</param>
239+
/// <param name="downlevel_container">True if a downlevel container.</param>
240+
/// <param name="throw_on_error">True to throw on error.</param>
241+
/// <returns>The NT status code.</returns>
242+
public NtStatus InitializeServerSilo(NtEvent delete_event, bool downlevel_container, bool throw_on_error)
243+
{
244+
ServerSiloInitInformation init = new ServerSiloInitInformation()
245+
{
246+
DeleteEvent = delete_event?.Handle.DangerousGetHandle() ?? IntPtr.Zero,
247+
IsDownlevelContainer = downlevel_container
248+
};
249+
250+
return Set(JobObjectInformationClass.JobObjectServerSiloInitialize, init, throw_on_error);
251+
}
252+
253+
/// <summary>
254+
/// Initialize a Silo to a Server Silo.
255+
/// </summary>
256+
/// <param name="delete_event">Event to signal when silo deleted.</param>
257+
/// <param name="downlevel_container">True if a downlevel container.</param>
258+
/// <returns>The NT status code.</returns>
259+
public void InitializeServerSilo(NtEvent delete_event, bool downlevel_container)
260+
{
261+
InitializeServerSilo(delete_event, downlevel_container, true);
262+
}
263+
264+
/// <summary>
265+
/// Create the silo's root object directory.
266+
/// </summary>
267+
/// <param name="flags">The flags for the creation.</param>
268+
/// <param name="throw_on_error">True to throw on error.</param>
269+
/// <returns>The NT status code.</returns>
270+
public NtStatus SetSiloObjectRootDirectory(SiloObjectRootDirectoryControlFlags flags, bool throw_on_error)
271+
{
272+
SiloObjectRootDirectory root_dir = new SiloObjectRootDirectory
273+
{
274+
ControlFlags = flags
275+
};
276+
return Set(JobObjectInformationClass.JobObjectSiloRootDirectory, root_dir, throw_on_error);
277+
}
278+
279+
/// <summary>
280+
/// Create the silo's root object directory.
281+
/// </summary>
282+
/// <param name="flags">The flags for the creation.</param>
283+
/// <returns>The NT status code.</returns>
284+
public void SetSiloObjectRootDirectory(SiloObjectRootDirectoryControlFlags flags)
285+
{
286+
SetSiloObjectRootDirectory(flags, true);
167287
}
168288

169289
/// <summary>
@@ -186,12 +306,20 @@ public NtStatus AssignProcess(NtProcess process, bool throw_on_error)
186306
return NtSystemCalls.NtAssignProcessToJobObject(Handle, process.Handle).ToNtException(throw_on_error);
187307
}
188308

309+
/// <summary>
310+
/// Assign a process to this job object using current Job on Windows 1709+.
311+
/// </summary>
312+
public NtStatus AssignProcessPseudoHandle(bool throw_on_error)
313+
{
314+
return AssignProcess(NtProcess.FromHandle(new SafeKernelObjectHandle(new IntPtr(-7), false)), throw_on_error);
315+
}
316+
189317
/// <summary>
190318
/// Assign a process to this job object using current Job on Windows 1709+.
191319
/// </summary>
192320
public void AssignProcessPseudoHandle()
193321
{
194-
AssignProcess(NtProcess.FromHandle(new SafeKernelObjectHandle(new IntPtr(-7), false)));
322+
AssignProcessPseudoHandle(true);
195323
}
196324

197325
/// <summary>
@@ -529,6 +657,20 @@ public void SetUiRestrictionFlags(JobObjectUiLimitFlags flags)
529657
SetUiRestrictionFlags(flags, true);
530658
}
531659

660+
/// <summary>
661+
/// Query Silo Root directory.
662+
/// </summary>
663+
/// <param name="throw_on_error">True to throw on error.</param>
664+
/// <returns>The silo root directory.</returns>
665+
public NtResult<string> QuerySiloRootDirectory(bool throw_on_error)
666+
{
667+
using (var buffer = new SafeStructureInOutBuffer<SiloObjectRootDirectory>(64 * 1024, true))
668+
{
669+
return QueryInformation(JobObjectInformationClass.JobObjectSiloRootDirectory,
670+
buffer, out int length).CreateResult(throw_on_error, () => buffer.Result.Path.ToString());
671+
}
672+
}
673+
532674
/// <summary>
533675
/// Method to query information for this object type.
534676
/// </summary>
@@ -742,6 +884,21 @@ public bool SilentBreakawayOk
742884
/// </summary>
743885
public int JobId => Query<JobObjectContainerIdentifierV2>(JobObjectInformationClass.JobObjectContainerId).JobId;
744886

887+
/// <summary>
888+
/// Get the Silo's Root Directory.
889+
/// </summary>
890+
public string SiloRootDirectory => QuerySiloRootDirectory(true).GetResultOrDefault(string.Empty);
891+
892+
/// <summary>
893+
/// Get Silo basic information.
894+
/// </summary>
895+
public SiloObjectBasicInformation SiloBasicInformation => Query<SiloObjectBasicInformation>(JobObjectInformationClass.JobObjectSiloBasicInformation);
896+
897+
/// <summary>
898+
/// Get Silo basic information.
899+
/// </summary>
900+
public ServerSiloBasicInformation ServerSiloBasicInformation => Query<ServerSiloBasicInformation>(JobObjectInformationClass.JobObjectServerSiloBasicInformation);
901+
745902
#endregion
746903

747904
#region Private Members

NtApiDotNet/NtJobNative.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,88 @@ public struct JobObjectContainerIdentifierV2
274274
public int JobId;
275275
}
276276

277+
[StructLayout(LayoutKind.Sequential)]
278+
public struct ServerSiloInitInformation
279+
{
280+
public IntPtr DeleteEvent;
281+
[MarshalAs(UnmanagedType.U1)]
282+
public bool IsDownlevelContainer;
283+
}
284+
285+
public enum NtProductType
286+
{
287+
WinNt = 1,
288+
LanManNt = 2,
289+
Server = 3
290+
}
291+
292+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
293+
public struct SiloUserSharedData
294+
{
295+
public int ServiceSessionId;
296+
public int ActiveConsoleId;
297+
public long ConsoleSessionForegroundProcessId;
298+
public NtProductType NtProductType;
299+
public int SuiteMask;
300+
public int SharedUserSessionId;
301+
public byte IsMultiSessionSku;
302+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
303+
public string NtSystemRoot;
304+
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
305+
public ushort[] UserModeGlobalLogger;
306+
}
307+
308+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
309+
public struct SiloObjectBasicInformation
310+
{
311+
public int SiloId;
312+
public int SiloParentId;
313+
public int NumberOfProcesses;
314+
[MarshalAs(UnmanagedType.U1)]
315+
public bool IsInServerSilo;
316+
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
317+
public byte[] Reserved;
318+
}
319+
320+
[Flags]
321+
public enum SiloObjectRootDirectoryControlFlags
322+
{
323+
None = 0,
324+
ShadowRoot = 1,
325+
InitializeRoot = 2,
326+
ShadowGlobal = 4
327+
}
328+
329+
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
330+
public struct SiloObjectRootDirectory
331+
{
332+
[FieldOffset(0)]
333+
public SiloObjectRootDirectoryControlFlags ControlFlags;
334+
[FieldOffset(0)]
335+
public UnicodeStringOut Path;
336+
}
337+
338+
public enum ServerSiloState
339+
{
340+
Initing = 0,
341+
Started = 1,
342+
ShuttingDown = 2,
343+
Terminating = 3,
344+
Terminated = 4
345+
}
346+
347+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
348+
public struct ServerSiloBasicInformation
349+
{
350+
public int ServiceSessionId;
351+
public ServerSiloState State;
352+
public NtStatus ExitStatus;
353+
[MarshalAs(UnmanagedType.U1)]
354+
public bool IsDownlevelContainer;
355+
public IntPtr ApiSetSchema;
356+
public IntPtr HostApiSetSchema;
357+
}
358+
277359
public static partial class NtSystemCalls
278360
{
279361
[DllImport("ntdll.dll")]

NtObjectManager/Cmdlets/Object/NewNtJobCmdlet.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ public sealed class NewNtJobCmdlet : NtObjectBaseCmdletWithAccess<JobAccessRight
6464
[Parameter]
6565
public JobObjectUiLimitFlags UiRestrictionFlags { get; set; }
6666

67+
/// <summary>
68+
/// <para type="description">Specify to create Job as a Silo.</para>
69+
/// </summary>
70+
[Parameter]
71+
public SwitchParameter CreateSilo { get; set; }
72+
73+
/// <summary>
74+
/// <para type="description">Specify to flags when creating the Silo's root directory. Must be used with -Silo.</para>
75+
/// </summary>
76+
[Parameter]
77+
public SiloObjectRootDirectoryControlFlags SiloRootDirectoryFlags { get; set; }
78+
6779
/// <summary>
6880
/// Determine if the cmdlet can create objects.
6981
/// </summary>
@@ -94,6 +106,11 @@ protected override object CreateObject(ObjectAttributes obj_attributes)
94106
{
95107
job.UiRestrictionFlags = UiRestrictionFlags;
96108
}
109+
if (CreateSilo)
110+
{
111+
job.InitializeSilo(SiloRootDirectoryFlags);
112+
}
113+
97114
return job.Duplicate();
98115
}
99116
}

NtObjectManager/NtObjectManager.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9439,4 +9439,4 @@ function Get-NdrComplexType {
94399439
$StublessProxy+$base_address, $OffsetTable+$base_address, $TypeIndex, $Flags) | Write-Output
94409440
}
94419441
}
9442-
}
9442+
}

0 commit comments

Comments
 (0)