612 lines
13 KiB
C
612 lines
13 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
priv.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module provides a command capability to enable and disable
|
|||
|
privileges. This command is expected to be an internal cmd.exe
|
|||
|
command, but is expected to be passed parameters as if it were
|
|||
|
an external command.
|
|||
|
|
|||
|
|
|||
|
THIS IS A TEMPORARY COMMAND. IF IT IS DESIRED TO MAKE THIS A
|
|||
|
PERMANENT COMMAND, THEN THIS FILE NEEDS TO BE GONE THROUGH WITH
|
|||
|
A FINE-TOOTH COMB TO ROBUSTLY HANDLE ALL ERROR SITUATIONS AND TO
|
|||
|
PROVIDE APPROPRIATE ERROR MESSAGES.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jim Kelly 1-Apr-1991.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
|
|||
|
//#include <sys\types.h>
|
|||
|
//#include <sys\stat.h>
|
|||
|
//#include <malloc.h>
|
|||
|
//#include <stdlib.h>
|
|||
|
//#include <ctype.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
//#include <tools.h>
|
|||
|
|
|||
|
//
|
|||
|
// command qualifier flag values
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN SwitchEnable = FALSE;
|
|||
|
BOOLEAN SwitchDisable = FALSE;
|
|||
|
BOOLEAN SwitchReset = FALSE;
|
|||
|
BOOLEAN SwitchAll = FALSE;
|
|||
|
|
|||
|
#ifndef SHIFT
|
|||
|
#define SHIFT(c,v) {c--; v++;}
|
|||
|
#endif //SHIFT
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Function definitions...
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
Usage ( VOID );
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
OpenAppropriateToken(
|
|||
|
OUT PHANDLE Token
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
EnableAllPrivileges( VOID );
|
|||
|
|
|||
|
VOID
|
|||
|
ResetAllPrivileges( VOID );
|
|||
|
|
|||
|
VOID
|
|||
|
DisableAllPrivileges( VOID );
|
|||
|
|
|||
|
int
|
|||
|
PrivMain (
|
|||
|
IN int c,
|
|||
|
IN PCHAR v[]
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
Usage (
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine prints the "Usage:" message.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
|
|||
|
printf( "Usage: priv [/EDRA] {PrivilegeName}\n");
|
|||
|
printf( " /E - Enable Privilege(s)\n");
|
|||
|
printf( " /D - Disable Privilege(s)\n");
|
|||
|
printf( " /R - Reset to default setting(s)\n");
|
|||
|
printf( " /A - Apply To All Privileges\n");
|
|||
|
printf( "\n");
|
|||
|
|
|||
|
printf( " The qualifiers /E and /D are mutually exclusive and can not\n");
|
|||
|
printf( " be used in the same command.\n");
|
|||
|
printf( " If /A is specified, then the PrivilegeName is ignored.\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "Examples:\n");
|
|||
|
printf( "\n");
|
|||
|
printf( " priv /ae\n");
|
|||
|
printf( " (enables all held privileges.\n");
|
|||
|
printf( "\n");
|
|||
|
printf( " priv /ad\n");
|
|||
|
printf( " disables all held privileges.\n");
|
|||
|
printf( "\n");
|
|||
|
printf( " priv /ar\n");
|
|||
|
printf( " (returns all privileges to their default setting.\n");
|
|||
|
printf( "\n");
|
|||
|
printf( " priv /e SeSetTimePrivilege\n");
|
|||
|
printf( " (enables the privileges called: SeSetTimePrivilege\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
OpenAppropriateToken(
|
|||
|
OUT PHANDLE Token
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine opens the appropriate TOKEN object. For an internal
|
|||
|
command, this is the current process's token. If this command is
|
|||
|
ever made external, then it will be the parent process's token.
|
|||
|
|
|||
|
If the token can't be openned, then a messages is printed indicating
|
|||
|
a problem has been encountered.
|
|||
|
|
|||
|
The caller is expected to close this token when no longer needed.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Token - Receives the handle value of the openned token.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - Indicates the token was successfully openned.
|
|||
|
|
|||
|
FALSE - Indicates the token was NOT successfully openned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status, IgnoreStatus;
|
|||
|
OBJECT_ATTRIBUTES ProcessAttributes;
|
|||
|
HANDLE Process;
|
|||
|
PTEB CurrentTeb;
|
|||
|
|
|||
|
CurrentTeb = NtCurrentTeb();
|
|||
|
InitializeObjectAttributes(&ProcessAttributes, NULL, 0, NULL, NULL);
|
|||
|
Status = NtOpenProcess(
|
|||
|
&Process, // TargetHandle
|
|||
|
PROCESS_QUERY_INFORMATION, // DesiredAccess
|
|||
|
&ProcessAttributes, // ObjectAttributes
|
|||
|
&CurrentTeb->ClientId // ClientId
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
Status = NtOpenProcessToken(
|
|||
|
Process,
|
|||
|
TOKEN_ADJUST_PRIVILEGES |
|
|||
|
TOKEN_QUERY,
|
|||
|
Token
|
|||
|
);
|
|||
|
|
|||
|
IgnoreStatus = NtClose( Process );
|
|||
|
|
|||
|
if ( NT_SUCCESS(Status) ) {
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "You are not allowed to change your own privilege settings.\n");
|
|||
|
printf( "Operation failed.\n");
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
EnableAllPrivileges(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine enables all privileges in the token.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
HANDLE Token;
|
|||
|
ULONG ReturnLength, Index;
|
|||
|
PTOKEN_PRIVILEGES NewState;
|
|||
|
|
|||
|
|
|||
|
if ( !OpenAppropriateToken(&Token) ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the size needed to query current privilege settings...
|
|||
|
//
|
|||
|
|
|||
|
Status = NtQueryInformationToken(
|
|||
|
Token, // TokenHandle
|
|||
|
TokenPrivileges, // TokenInformationClass
|
|||
|
NewState, // TokenInformation
|
|||
|
0, // TokenInformationLength
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
|
|||
|
|
|||
|
NewState = RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
|
|||
|
ASSERT( NewState != NULL );
|
|||
|
|
|||
|
|
|||
|
Status = NtQueryInformationToken(
|
|||
|
Token, // TokenHandle
|
|||
|
TokenPrivileges, // TokenInformationClass
|
|||
|
NewState, // TokenInformation
|
|||
|
ReturnLength, // TokenInformationLength
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the state settings so that all privileges are enabled...
|
|||
|
//
|
|||
|
|
|||
|
if (NewState->PrivilegeCount > 0) {
|
|||
|
Index = NewState->PrivilegeCount;
|
|||
|
|
|||
|
while (Index < NewState->PrivilegeCount) {
|
|||
|
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
|
|||
|
Index += 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Change the settings in the token...
|
|||
|
//
|
|||
|
|
|||
|
Status = NtAdjustPrivilegesToken(
|
|||
|
Token, // TokenHandle
|
|||
|
FALSE, // DisableAllPrivileges
|
|||
|
NewState, // NewState (OPTIONAL)
|
|||
|
ReturnLength, // BufferLength
|
|||
|
NULL, // PreviousState (OPTIONAL)
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RtlFreeHeap( RtlProcessHeap(), 0, NewState );
|
|||
|
Status = NtClose( Token );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ResetAllPrivileges(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine resets all privileges in the token to their default state.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
HANDLE Token;
|
|||
|
ULONG ReturnLength, Index;
|
|||
|
PTOKEN_PRIVILEGES NewState;
|
|||
|
|
|||
|
|
|||
|
if ( !OpenAppropriateToken(&Token) ) {
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "You are not allowed to change your own privilege settings.\n");
|
|||
|
printf( "Operation failed.\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the size needed to query current privilege settings...
|
|||
|
//
|
|||
|
|
|||
|
Status = NtQueryInformationToken(
|
|||
|
Token, // TokenHandle
|
|||
|
TokenPrivileges, // TokenInformationClass
|
|||
|
NewState, // TokenInformation
|
|||
|
0, // TokenInformationLength
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( STATUS_BUFFER_TOO_SMALL );
|
|||
|
|
|||
|
NewState = RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
|
|||
|
ASSERT( NewState != NULL );
|
|||
|
|
|||
|
|
|||
|
Status = NtQueryInformationToken(
|
|||
|
Token, // TokenHandle
|
|||
|
TokenPrivileges, // TokenInformationClass
|
|||
|
NewState, // TokenInformation
|
|||
|
ReturnLength, // TokenInformationLength
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the state settings so that all privileges are reset to
|
|||
|
// their default settings...
|
|||
|
//
|
|||
|
|
|||
|
if (NewState->PrivilegeCount > 0) {
|
|||
|
Index = NewState->PrivilegeCount;
|
|||
|
|
|||
|
while (Index < NewState->PrivilegeCount) {
|
|||
|
if (NewState->Privileges[Index].Attributes ==
|
|||
|
SE_PRIVILEGE_ENABLED_BY_DEFAULT) {
|
|||
|
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
|
|||
|
}
|
|||
|
else {
|
|||
|
NewState->Privileges[Index].Attributes = 0;
|
|||
|
}
|
|||
|
|
|||
|
Index += 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Change the settings in the token...
|
|||
|
//
|
|||
|
|
|||
|
Status = NtAdjustPrivilegesToken(
|
|||
|
Token, // TokenHandle
|
|||
|
FALSE, // DisableAllPrivileges
|
|||
|
NewState, // NewState (OPTIONAL)
|
|||
|
ReturnLength, // BufferLength
|
|||
|
NULL, // PreviousState (OPTIONAL)
|
|||
|
&ReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RtlFreeHeap( RtlProcessHeap(), 0, NewState );
|
|||
|
Status = NtClose( Token );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DisableAllPrivileges(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine disables all privileges in the token.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG IgnoredReturnLength;
|
|||
|
HANDLE Token;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
if ( !OpenAppropriateToken(&Token) ) {
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "You are not allowed to change your own privilege settings.\n");
|
|||
|
printf( "Operation failed.\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Disable all the privileges.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
Status = NtAdjustPrivilegesToken(
|
|||
|
Token, // TokenHandle
|
|||
|
TRUE, // DisableAllPrivileges
|
|||
|
NULL, // NewState (OPTIONAL)
|
|||
|
0, // BufferLength
|
|||
|
NULL, // PreviousState (OPTIONAL)
|
|||
|
&IgnoredReturnLength // ReturnLength
|
|||
|
);
|
|||
|
ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
|
|||
|
|
|||
|
Status = NtClose( Token );
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
PrivMain (
|
|||
|
IN int c,
|
|||
|
IN PCHAR v[]
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the main entry routine for the "priv" command.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TBS
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TBS
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCHAR p;
|
|||
|
CHAR ch;
|
|||
|
ULONG DispositionDirectives;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
DispositionDirectives = 0;
|
|||
|
SHIFT (c,v);
|
|||
|
while ((c > 0) && ((ch = *v[0]))) {
|
|||
|
p = *v;
|
|||
|
if (ch == '/') {
|
|||
|
while (*++p != '\0') {
|
|||
|
if (*p == 'E') {
|
|||
|
SwitchEnable = TRUE;
|
|||
|
DispositionDirectives += 1;
|
|||
|
}
|
|||
|
if (*p == 'D') {
|
|||
|
SwitchDisable = TRUE;
|
|||
|
DispositionDirectives += 1;
|
|||
|
}
|
|||
|
if (*p == 'R') {
|
|||
|
SwitchReset = TRUE;
|
|||
|
DispositionDirectives += 1;
|
|||
|
}
|
|||
|
else if (*p == 'A') {
|
|||
|
SwitchAll = TRUE;
|
|||
|
}
|
|||
|
else {
|
|||
|
Usage();
|
|||
|
}
|
|||
|
}
|
|||
|
SHIFT(c,v);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we don't have conflicting parameters
|
|||
|
//
|
|||
|
// Rules:
|
|||
|
//
|
|||
|
// If /A isn't specified, then a privilege name must be.
|
|||
|
// Exactly one of /E, /D, and /R must be specified.
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
if (!SwitchAll && (c == 0)) {
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "You must provide privilege name or use the /A switch.\n");
|
|||
|
Usage();
|
|||
|
return ( 0 );
|
|||
|
}
|
|||
|
|
|||
|
if (DispositionDirectives != 1) {
|
|||
|
printf( "\n");
|
|||
|
printf( "\n");
|
|||
|
printf( "You must provide one and only one of the following");
|
|||
|
printf( "switches: /E, /D, /R\n");
|
|||
|
Usage();
|
|||
|
return ( 0 );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Everything appears legitimate
|
|||
|
//
|
|||
|
|
|||
|
if (SwitchAll) {
|
|||
|
|
|||
|
//
|
|||
|
// /A switch specified
|
|||
|
//
|
|||
|
|
|||
|
if (SwitchEnable) {
|
|||
|
EnableAllPrivileges();
|
|||
|
}
|
|||
|
else if (SwitchDisable) {
|
|||
|
DisableAllPrivileges();
|
|||
|
}
|
|||
|
else {
|
|||
|
ResetAllPrivileges();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// privilege name specified...
|
|||
|
//
|
|||
|
|
|||
|
else {
|
|||
|
printf( "\n");
|
|||
|
printf( "I'm sorry, but due to the lack of time and interest,\n");
|
|||
|
printf( "individual privilege selection is not yet supported.\n");
|
|||
|
printf( "Please use the /A qualifier for the time being.\n");
|
|||
|
printf( "\n");
|
|||
|
}
|
|||
|
|
|||
|
} finally {
|
|||
|
return ( 0 );
|
|||
|
}
|
|||
|
|
|||
|
return( 0 );
|
|||
|
|
|||
|
}
|