Skip to content

Commit 0960d5a

Browse files
committed
Added Set-NtToken command.
1 parent d47b469 commit 0960d5a

3 files changed

Lines changed: 173 additions & 1 deletion

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright 2020 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using NtApiDotNet;
16+
using System;
17+
using System.Management.Automation;
18+
19+
namespace NtObjectManager.Cmdlets.Object
20+
{
21+
/// <summary>
22+
/// <para type="synopsis">Set a NT token on a process or thread.</para>
23+
/// <para type="description">This cmdlet sets a token on a process or thread.</para>
24+
/// </summary>
25+
/// <example>
26+
/// <code>Set-NtToken -Token $token -Process $process</code>
27+
/// <para>Set a process' primary token.</para>
28+
/// </example>
29+
/// <example>
30+
/// <code>Set-NtToken -Token $token -Process $process -Duplicate</code>
31+
/// <para>Set a process' primary token, duplicating it before use.</para>
32+
/// </example>
33+
/// <example>
34+
/// <code>Set-NtToken -Token $token -ProcessId 1234</code>
35+
/// <para>Set a process' primary token from its PID.</para>
36+
/// </example>
37+
/// <example>
38+
/// <code>Set-NtToken -Token $token -Thread $thread</code>
39+
/// <para>Set a thread's impersonation token.</para>
40+
/// </example>
41+
/// <example>
42+
/// <code>Set-NtToken -Token $token -Thread $thread -Duplicate -ImpersonationLevel Identification</code>
43+
/// <para>Set a thread's impersonation token, duplicating as an Identification level token first..</para>
44+
/// </example>
45+
/// <example>
46+
/// <code>Set-NtToken -Token $token -ThreadId 1234</code>
47+
/// <para>Set a thread's impersonation token from its TID.</para>
48+
/// </example>
49+
/// <para type="link">about_ManagingNtObjectLifetime</para>
50+
[Cmdlet(VerbsCommon.Set, "NtToken", DefaultParameterSetName = "Process")]
51+
public class SetNtTokenCmdlet : PSCmdlet
52+
{
53+
/// <summary>
54+
/// <para type="description">Specify the process to set the token on.</para>
55+
/// </summary>
56+
[Parameter(Mandatory = true, Position = 1, ParameterSetName = "Process")]
57+
public NtProcess Process { get; set; }
58+
59+
/// <summary>
60+
/// <para type="description">Specify the process to set the token on.as a PID.</para>
61+
/// </summary>
62+
[Parameter(Mandatory = true, Position = 1, ParameterSetName = "ProcessId"), Alias("pid")]
63+
public int ProcessId { get; set; }
64+
65+
/// <summary>
66+
/// <para type="description">Specify the thread to set the token on.</para>
67+
/// </summary>
68+
[Parameter(Mandatory = true, Position = 1, ParameterSetName = "Thread")]
69+
public NtThread Thread { get; set; }
70+
71+
/// <summary>
72+
/// <para type="description">Specify the thread to set the token on as a TID.</para>
73+
/// </summary>
74+
[Parameter(Mandatory = true, ParameterSetName = "ThreadId"), Alias("tid")]
75+
public int ThreadId { get; set; }
76+
77+
/// <summary>
78+
/// <para type="description">Duplicate the token before setting it.</para>
79+
/// </summary>
80+
[Parameter]
81+
public SwitchParameter Duplicate { get; set; }
82+
83+
/// <summary>
84+
/// <para type="description">Specify the token to set.</para>
85+
/// </summary>
86+
[Parameter(Mandatory = true, Position = 0)]
87+
public NtToken Token { get; set; }
88+
89+
/// <summary>
90+
/// <para type="description">Specify the impersonation level of the token to assign if -Duplicate is specified.</para>
91+
/// </summary>
92+
[Parameter(ParameterSetName = "Thread"), Parameter(ParameterSetName = "ThreadId")]
93+
public SecurityImpersonationLevel ImpersonationLevel { get; set; }
94+
95+
/// <summary>
96+
/// <para type="description">Specify the integrity level of the token to set if -Duplicate is specified.</para>
97+
/// </summary>
98+
[Parameter]
99+
public TokenIntegrityLevel? IntegrityLevel { get; set; }
100+
101+
private bool IsProcess()
102+
{
103+
switch (ParameterSetName)
104+
{
105+
case "Process":
106+
case "ProcessId":
107+
return true;
108+
case "Thread":
109+
case "ThreadId":
110+
return false;
111+
default:
112+
throw new ArgumentException("Invalid parameter set.");
113+
}
114+
}
115+
116+
private NtToken GetToken()
117+
{
118+
if (!Duplicate)
119+
return Token.Duplicate();
120+
121+
TokenType type = IsProcess() ? TokenType.Primary : TokenType.Impersonation;
122+
123+
using (var token = Token.DuplicateToken(type, ImpersonationLevel, TokenAccessRights.MaximumAllowed))
124+
{
125+
if (IntegrityLevel.HasValue)
126+
{
127+
token.IntegrityLevel = IntegrityLevel.Value;
128+
}
129+
return token.Duplicate();
130+
}
131+
}
132+
133+
private NtProcess GetProcess()
134+
{
135+
if (ParameterSetName == "Process")
136+
return Process.Duplicate(ProcessAccessRights.SetInformation);
137+
return NtProcess.Open(ProcessId, ProcessAccessRights.SetInformation);
138+
}
139+
140+
private NtThread GetThread()
141+
{
142+
if (ParameterSetName == "Thread")
143+
return Thread.Duplicate(ThreadAccessRights.Impersonate);
144+
return NtThread.Open(ThreadId, ThreadAccessRights.Impersonate);
145+
}
146+
147+
/// <summary>
148+
/// Overridden ProcessRecord method.
149+
/// </summary>
150+
protected override void ProcessRecord()
151+
{
152+
using (var token = GetToken())
153+
{
154+
if (IsProcess())
155+
{
156+
using (var proc = GetProcess())
157+
{
158+
proc.SetToken(token);
159+
}
160+
}
161+
else
162+
{
163+
using (var thread = GetThread())
164+
{
165+
thread.Impersonate(token);
166+
}
167+
}
168+
}
169+
}
170+
}
171+
}

NtObjectManager/NtObjectManager.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
<Compile Include="Cmdlets\Object\SetNtFileHardlinkCmdlet.cs" />
141141
<Compile Include="Cmdlets\Object\SetNtFileReparsePointCmdlet.cs" />
142142
<Compile Include="Cmdlets\Object\SetNtProcessJobCmdlet.cs" />
143+
<Compile Include="Cmdlets\Object\SetNtTokenCmdlet.cs" />
143144
<Compile Include="Cmdlets\Object\SpecificAccessType.cs" />
144145
<Compile Include="Cmdlets\Object\StartNtDebugWaitCmdlet.cs" />
145146
<Compile Include="Cmdlets\Object\CompareNtSidCmdlet.cs" />

NtObjectManager/NtObjectManager.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ CmdletsToExport = 'Add-NtKeyHive', 'Get-NtDirectory', 'Get-NtEvent', 'Get-NtFile
133133
'Test-NtTokenGroup', 'Test-NtAccessMask', 'Grant-NtAccessMask',
134134
'Revoke-NtAccessMask', 'Select-NtSecurityDescriptorAce', 'Write-NtAudit',
135135
'New-AuthZResourceManager', 'New-AuthZContext', 'Get-AuthZGrantedAccess',
136-
'Add-AuthZSid', 'Remove-AuthZSid'
136+
'Add-AuthZSid', 'Remove-AuthZSid', 'Set-NtToken'
137137

138138
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
139139
AliasesToExport = @()

0 commit comments

Comments
 (0)