570 lines
15 KiB
C
570 lines
15 KiB
C
|
/****************************************************************************
|
||
|
|
||
|
PROGRAM: MYTOKEN.C
|
||
|
|
||
|
PURPOSE: Contains routines that manipulate tokens
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "PVIEWP.h"
|
||
|
|
||
|
typedef PVOID *PPVOID;
|
||
|
|
||
|
|
||
|
HANDLE OpenToken(
|
||
|
HANDLE hMyToken,
|
||
|
ACCESS_MASK DesiredAccess);
|
||
|
|
||
|
BOOL CloseToken(
|
||
|
HANDLE Token);
|
||
|
|
||
|
BOOL GetTokenInfo(
|
||
|
HANDLE Token,
|
||
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||
|
PPVOID pBuffer);
|
||
|
|
||
|
BOOL SetTokenInfo(
|
||
|
HANDLE Token,
|
||
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||
|
PVOID Buffer);
|
||
|
|
||
|
BOOL FreeTokenInfo(
|
||
|
PVOID Buffer);
|
||
|
|
||
|
HANDLE AllocMyToken(VOID);
|
||
|
BOOL ReadMyToken(HANDLE);
|
||
|
BOOL WriteMyToken(HWND, HANDLE);
|
||
|
BOOL FreeMyToken(HANDLE);
|
||
|
PVOID AllocTokenInfo(HANDLE, TOKEN_INFORMATION_CLASS);
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: OpenMyToken
|
||
|
|
||
|
PURPOSE: Opens the token of the specified process or thread.
|
||
|
|
||
|
RETURNS : Handle to mytoken on success, or NULL on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
HANDLE OpenMyToken(
|
||
|
HANDLE Token,
|
||
|
LPWSTR Name
|
||
|
)
|
||
|
{
|
||
|
PMYTOKEN pMyToken;
|
||
|
HANDLE hMyToken;
|
||
|
|
||
|
//
|
||
|
// Build a MYTOKEN structure.
|
||
|
|
||
|
hMyToken = AllocMyToken();
|
||
|
if (hMyToken == NULL) {
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
pMyToken = (PMYTOKEN)hMyToken;
|
||
|
|
||
|
pMyToken->Token = Token;
|
||
|
|
||
|
pMyToken->Name = Alloc((lstrlenW(Name) + 1) * sizeof(WCHAR));
|
||
|
if (pMyToken->Name == NULL) {
|
||
|
Free(pMyToken);
|
||
|
return(NULL);
|
||
|
}
|
||
|
lstrcpyW(pMyToken->Name, Name);
|
||
|
|
||
|
|
||
|
if (!ReadMyToken(hMyToken)) {
|
||
|
DbgPrint("PVIEW : Failed to read token info\n");
|
||
|
Free(pMyToken->Name);
|
||
|
Free(pMyToken);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
return(hMyToken);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: ReadMyToken
|
||
|
|
||
|
PURPOSE: Reads the token info and stores in mytoken structure
|
||
|
|
||
|
RETURNS : TRUE on success, FALSE on failure
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL ReadMyToken(
|
||
|
HANDLE hMyToken)
|
||
|
{
|
||
|
HANDLE Token;
|
||
|
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
|
||
|
|
||
|
Token = OpenToken(hMyToken, TOKEN_QUERY);
|
||
|
|
||
|
if (Token == NULL) {
|
||
|
DbgPrint("PVIEW : Failed to open the token with TOKEN_QUERY access\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenStatistics, (PPVOID)&(pMyToken->TokenStats))) {
|
||
|
DbgPrint("PVIEW : Failed to read token statistics from token\n");
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenGroups, (PPVOID)&(pMyToken->Groups))) {
|
||
|
DbgPrint("PVIEW : Failed to read group info from token\n");
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenUser, (PPVOID)&(pMyToken->UserId))) {
|
||
|
DbgPrint("PVIEW : Failed to read userid from token\n");
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenOwner, (PPVOID)&(pMyToken->DefaultOwner))) {
|
||
|
DbgPrint("PVIEW : Failed to read default owner from token\n");
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenPrimaryGroup, (PPVOID)&(pMyToken->PrimaryGroup))) {
|
||
|
DbgPrint("PVIEW : Failed to read primary group from token\n");
|
||
|
}
|
||
|
|
||
|
if (!GetTokenInfo(Token, TokenPrivileges, (PPVOID)&(pMyToken->Privileges))) {
|
||
|
DbgPrint("PVIEW : Failed to read privilege info from token\n");
|
||
|
}
|
||
|
|
||
|
if ( !GetTokenInfo( Token, TokenRestrictedSids, (PPVOID) &(pMyToken->RestrictedSids) ) )
|
||
|
{
|
||
|
pMyToken->RestrictedSids = NULL ;
|
||
|
}
|
||
|
|
||
|
|
||
|
CloseToken(Token);
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: CloseMyToken
|
||
|
|
||
|
PURPOSE: Closes the specified mytoken handle
|
||
|
If fSaveChanges = TRUE, the token information is saved,
|
||
|
otherwise it is discarded.
|
||
|
|
||
|
RETURNS : TRUE on success, FALSE on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL CloseMyToken(
|
||
|
HWND hDlg,
|
||
|
HANDLE hMyToken,
|
||
|
BOOL fSaveChanges)
|
||
|
{
|
||
|
if (fSaveChanges) {
|
||
|
WriteMyToken(hDlg, hMyToken);
|
||
|
}
|
||
|
|
||
|
return FreeMyToken(hMyToken);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: AllocMyToken
|
||
|
|
||
|
PURPOSE: Allocates space for mytoken structure.
|
||
|
|
||
|
RETURNS : HANDLE to mytoken or NULL on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
HANDLE AllocMyToken(VOID)
|
||
|
{
|
||
|
PMYTOKEN pMyToken;
|
||
|
|
||
|
pMyToken = (PMYTOKEN)Alloc(sizeof(MYTOKEN));
|
||
|
|
||
|
return((HANDLE)pMyToken);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: FreeMyToken
|
||
|
|
||
|
PURPOSE: Frees the memory allocated to mytoken structure.
|
||
|
|
||
|
RETURNS : TRUE on success, FALSE on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL FreeMyToken(
|
||
|
HANDLE hMyToken)
|
||
|
{
|
||
|
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
|
||
|
|
||
|
if (pMyToken->TokenStats != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->TokenStats));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->UserId != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->UserId));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->PrimaryGroup != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->PrimaryGroup));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->DefaultOwner != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->DefaultOwner));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->Groups != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->Groups));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->Privileges != NULL) {
|
||
|
FreeTokenInfo((PVOID)(pMyToken->Privileges));
|
||
|
}
|
||
|
|
||
|
if (pMyToken->Name != NULL) {
|
||
|
Free((PVOID)pMyToken->Name);
|
||
|
}
|
||
|
|
||
|
Free((PVOID)pMyToken);
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: WriteMyToken
|
||
|
|
||
|
PURPOSE: Writes the token information out to the token
|
||
|
|
||
|
RETURNS : TRUE on success, FALSE on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL WriteMyToken(
|
||
|
HWND hDlg,
|
||
|
HANDLE hMyToken)
|
||
|
{
|
||
|
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
|
||
|
HANDLE Token;
|
||
|
|
||
|
//
|
||
|
// Save default owner and primary group
|
||
|
//
|
||
|
|
||
|
Token = OpenToken(hMyToken, TOKEN_ADJUST_DEFAULT);
|
||
|
|
||
|
if (Token == NULL) {
|
||
|
|
||
|
DbgPrint("PVIEW: Failed to open token with TOKEN_ADJUST_DEFAULT access\n");
|
||
|
MessageBox(hDlg, "Failed to open token with access required\nUnable to change default owner or primary group", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// Set default owner
|
||
|
//
|
||
|
if ((pMyToken->DefaultOwner != NULL) &&
|
||
|
(!SetTokenInfo(Token, TokenOwner, (PVOID)(pMyToken->DefaultOwner)))) {
|
||
|
MessageBox(hDlg, "Failed to set default owner", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
}
|
||
|
|
||
|
// Set primary group
|
||
|
//
|
||
|
if ((pMyToken->PrimaryGroup != NULL) &&
|
||
|
(!SetTokenInfo(Token, TokenPrimaryGroup, (PVOID)(pMyToken->PrimaryGroup)))) {
|
||
|
MessageBox(hDlg, "Failed to set primary group", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
}
|
||
|
|
||
|
CloseToken(Token);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Save group info
|
||
|
//
|
||
|
|
||
|
Token = OpenToken(hMyToken, TOKEN_ADJUST_GROUPS);
|
||
|
|
||
|
if (Token == NULL) {
|
||
|
|
||
|
DbgPrint("PVIEW: Failed to open token with TOKEN_ADJUST_GROUPS access\n");
|
||
|
MessageBox(hDlg, "Failed to open token with access required\nUnable to change group settings", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if ((pMyToken->Groups != NULL) &&
|
||
|
(!SetTokenInfo(Token, TokenGroups, (PVOID)(pMyToken->Groups)))) {
|
||
|
MessageBox(hDlg, "Failed to change group settings", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
}
|
||
|
|
||
|
CloseToken(Token);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Change privileges
|
||
|
//
|
||
|
|
||
|
Token = OpenToken(hMyToken, TOKEN_ADJUST_PRIVILEGES);
|
||
|
|
||
|
if (Token == NULL) {
|
||
|
|
||
|
DbgPrint("PVIEW: Failed to open token with TOKEN_ADJUST_PRIVILEGES access\n");
|
||
|
MessageBox(hDlg, "Failed to open token with access required\nUnable to change privilege settings", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if ((pMyToken->Privileges != NULL) &&
|
||
|
(!SetTokenInfo(Token, TokenPrivileges, (PVOID)(pMyToken->Privileges)))) {
|
||
|
MessageBox(hDlg, "Failed to change privilege settings", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
||
|
}
|
||
|
|
||
|
CloseToken(Token);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: OpenToken
|
||
|
|
||
|
PURPOSE: Opens the token with the specified access
|
||
|
|
||
|
RETURNS : Handle to token on success, or NULL on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
HANDLE OpenToken(
|
||
|
HANDLE hMyToken,
|
||
|
ACCESS_MASK DesiredAccess)
|
||
|
{
|
||
|
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
|
||
|
|
||
|
return(pMyToken->Token);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: CloseToken
|
||
|
|
||
|
PURPOSE: Closes the specified token handle
|
||
|
|
||
|
RETURNS : TRUE on success, FALSE on failure.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL CloseToken(
|
||
|
HANDLE Token)
|
||
|
{
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: AllocTokenInfo
|
||
|
|
||
|
PURPOSE: Allocates memory to hold the parameter that
|
||
|
NTQueryInformationToken will return.
|
||
|
Memory should be freed later using FreeTokenInfo
|
||
|
|
||
|
RETURNS : Pointer to allocated memory or NULL on failure
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
PVOID AllocTokenInfo(
|
||
|
HANDLE Token,
|
||
|
TOKEN_INFORMATION_CLASS TokenInformationClass)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ULONG InfoLength;
|
||
|
|
||
|
Status = NtQueryInformationToken(
|
||
|
Token, // Handle
|
||
|
TokenInformationClass, // TokenInformationClass
|
||
|
NULL, // TokenInformation
|
||
|
0, // TokenInformationLength
|
||
|
&InfoLength // ReturnLength
|
||
|
);
|
||
|
|
||
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
||
|
DbgPrint("PVIEW: NtQueryInformationToken did NOT return buffer_too_small, status = 0x%lx\n", Status);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
return Alloc(InfoLength);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: FreeTokenInfo
|
||
|
|
||
|
PURPOSE: Frees the memory previously allocated with AllocTokenInfo
|
||
|
|
||
|
RETURNS : TRUE on success, otherwise FALSE
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL FreeTokenInfo(
|
||
|
PVOID Buffer)
|
||
|
{
|
||
|
return(Free(Buffer));
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: GetTokenInfo
|
||
|
|
||
|
PURPOSE: Allocates a buffer and reads the specified data
|
||
|
out of the token and into it.
|
||
|
|
||
|
RETURNS : TRUE on success otherwise FALSE.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL GetTokenInfo(
|
||
|
HANDLE Token,
|
||
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||
|
PPVOID pBuffer)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ULONG BufferSize;
|
||
|
ULONG InfoLength;
|
||
|
PVOID Buffer;
|
||
|
|
||
|
*pBuffer = NULL; // Prepare for failure
|
||
|
|
||
|
Buffer = AllocTokenInfo(Token, TokenInformationClass);
|
||
|
if (Buffer == NULL) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
BufferSize = GetAllocSize(Buffer);
|
||
|
|
||
|
Status = NtQueryInformationToken(
|
||
|
Token, // Handle
|
||
|
TokenInformationClass, // TokenInformationClass
|
||
|
Buffer, // TokenInformation
|
||
|
BufferSize, // TokenInformationLength
|
||
|
&InfoLength // ReturnLength
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DbgPrint("PVIEW: NtQueryInformationToken failed, status = 0x%lx\n", Status);
|
||
|
FreeTokenInfo(Buffer);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
if (InfoLength > BufferSize) {
|
||
|
DbgPrint("PVIEW: NtQueryInformationToken failed, DataSize > BufferSize");
|
||
|
FreeTokenInfo(Buffer);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
*pBuffer = Buffer;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
FUNCTION: SetTokenInfo
|
||
|
|
||
|
PURPOSE: Sets the specified information in the given token.
|
||
|
|
||
|
RETURNS : TRUE on success otherwise FALSE.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL SetTokenInfo(
|
||
|
HANDLE Token,
|
||
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||
|
PVOID Buffer)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ULONG BufferSize;
|
||
|
|
||
|
BufferSize = GetAllocSize(Buffer);
|
||
|
|
||
|
switch (TokenInformationClass) {
|
||
|
|
||
|
case TokenOwner:
|
||
|
case TokenPrimaryGroup:
|
||
|
case TokenDefaultDacl:
|
||
|
|
||
|
Status = NtSetInformationToken(
|
||
|
Token, // Handle
|
||
|
TokenInformationClass, // TokenInformationClass
|
||
|
Buffer, // TokenInformation
|
||
|
BufferSize // TokenInformationLength
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DbgPrint("PVIEW: NtSetInformationToken failed, info class = 0x%x, status = 0x%lx\n",
|
||
|
TokenInformationClass, Status);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case TokenGroups:
|
||
|
|
||
|
Status = NtAdjustGroupsToken(
|
||
|
Token, // Handle
|
||
|
FALSE, // Reset to default
|
||
|
(PTOKEN_GROUPS)Buffer, // New State
|
||
|
BufferSize, // Buffer Length
|
||
|
NULL, // Previous State
|
||
|
NULL // Return Length
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DbgPrint("PVIEW: NtAdjustGroupsToken failed, status = 0x%lx\n", Status);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case TokenPrivileges:
|
||
|
|
||
|
Status = NtAdjustPrivilegesToken(
|
||
|
Token, // Handle
|
||
|
FALSE, // Disable all privileges
|
||
|
(PTOKEN_PRIVILEGES)Buffer, // New State
|
||
|
BufferSize, // Buffer Length
|
||
|
NULL, // Previous State
|
||
|
NULL // Return Length
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DbgPrint("PVIEW: NtAdjustPrivilegesToken failed, status = 0x%lx\n", Status);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
default:
|
||
|
|
||
|
// Unrecognised information type
|
||
|
DbgPrint("PVIEW: SetTokenInfo passed unrecognised infoclass, class = 0x%x\n", TokenInformationClass);
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|