619 lines
16 KiB
C
619 lines
16 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: logon2.c
|
|
//
|
|
// Contents: Logon test app
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 6-20-94 richardw Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntlsa.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#define DUMP_TOKEN 1
|
|
#define DUMP_HEX 2
|
|
|
|
|
|
char *User = NULL;
|
|
char *Domain = NULL;
|
|
char *Password = NULL;
|
|
char *SecPackage = NULL;
|
|
char *Cmd = NULL;
|
|
|
|
DWORD fLogon = 0;
|
|
DWORD fMe = 0;
|
|
DWORD fService = 0;
|
|
DWORD fCookie = 0;
|
|
FILE * fOut;
|
|
DWORD Threads;
|
|
DWORD fDup = 0;
|
|
DWORD LogonType = LOGON32_LOGON_INTERACTIVE;
|
|
|
|
char * ImpLevels[] = { "Anonymous", "Identity", "Impersonation", "Delegation"};
|
|
|
|
char * LogonTypes[] = { "Invalid", "Invalid", "Interactive", "Network", "Batch", "Service", "Proxy" };
|
|
|
|
void DumpToken(HANDLE hToken);
|
|
|
|
void
|
|
DoArgs(int argc,
|
|
char **argv)
|
|
|
|
{
|
|
int i;
|
|
|
|
Threads = 1;
|
|
|
|
if (argc < 3)
|
|
{
|
|
fprintf( fOut,"usage: %s <name> <domain> [-p pw] [-f flags] [-s] [-d] [-x cmd]\n", argv[0]);
|
|
fprintf( fOut,"Tests logon path\n");
|
|
fprintf( fOut," -p \tOverride password\n");
|
|
fprintf( fOut," -D \tDump token\n");
|
|
fprintf( fOut," -d \tduplicate\n");
|
|
fprintf( fOut," -s \tLogon as service\n");
|
|
fprintf( fOut," -x cmd \tStart cmd as user\n");
|
|
fprintf( fOut," -o file\tSend output to file\n");
|
|
fprintf( fOut," -t # \tHit with # threads at once\n");
|
|
fprintf( fOut," -l type\tLogon type\n");
|
|
exit(1);
|
|
}
|
|
|
|
for (i = 1; i < argc ; i++ )
|
|
{
|
|
if (*argv[i] == '-')
|
|
{
|
|
switch (*(argv[i]+1))
|
|
{
|
|
case 'f':
|
|
fLogon = atoi(argv[++i]);
|
|
break;
|
|
|
|
case 'd':
|
|
fDup = 1;
|
|
break;
|
|
|
|
case 'D':
|
|
fMe |= DUMP_TOKEN;
|
|
break;
|
|
|
|
case 'x':
|
|
Cmd = argv[++i];
|
|
break;
|
|
|
|
case 'p':
|
|
Password = argv[++i];
|
|
break;
|
|
|
|
case 't':
|
|
Threads = atoi(argv[++i]);
|
|
break;
|
|
|
|
case 's':
|
|
LogonType = LOGON32_LOGON_SERVICE;
|
|
break;
|
|
|
|
case 'l':
|
|
++i;
|
|
if (argv[i] == NULL )
|
|
{
|
|
fprintf(fOut, "No logon type specified\n");
|
|
exit(1);
|
|
}
|
|
for (LogonType = 2 ;
|
|
LogonType < sizeof(LogonTypes) / sizeof(PSTR) ;
|
|
LogonType ++ )
|
|
{
|
|
if (_stricmp( LogonTypes[LogonType], argv[i]) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (LogonType == (sizeof(LogonTypes) / sizeof(PSTR) ))
|
|
{
|
|
fprintf(fOut, "Invalid logon type '%s'\n", argv[i]);
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 'o':
|
|
fOut = fopen(argv[++i], "w");
|
|
if (!fOut)
|
|
{
|
|
fOut = stderr;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf( fOut,"Invalid switch %s\n", argv[i]);
|
|
exit(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!User)
|
|
User = argv[i];
|
|
else
|
|
if (!Domain)
|
|
Domain = argv[i];
|
|
}
|
|
}
|
|
|
|
if (!Password)
|
|
Password = User;
|
|
}
|
|
|
|
DWORD
|
|
DoIt(
|
|
PVOID pv)
|
|
{
|
|
NTSTATUS scRet, SubStatus, Status;
|
|
PISID pSid;
|
|
LUID Luid;
|
|
TOKEN_GROUPS TokenGroups;
|
|
STRING sMe;
|
|
HANDLE hToken;
|
|
HANDLE hImp;
|
|
HANDLE hDup;
|
|
STRING sPackage;
|
|
ULONG Package;
|
|
LUID LogonId;
|
|
TOKEN_SOURCE TokenSource;
|
|
char ImpersonateName[MAX_PATH];
|
|
DWORD cbImpersonateName = MAX_PATH;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
POBJECT_TYPE_INFORMATION pTypeInfo;
|
|
POBJECT_NAME_INFORMATION pNameInfo;
|
|
POBJECT_BASIC_INFORMATION pBasicInfo;
|
|
UCHAR Buffer[1024];
|
|
HANDLE hWait;
|
|
|
|
hWait = (HANDLE) pv;
|
|
|
|
if (hWait != NULL)
|
|
{
|
|
WaitForSingleObjectEx( hWait, INFINITE, FALSE );
|
|
}
|
|
|
|
fprintf( fOut,"Logging on %s to %s\n", User, Domain);
|
|
|
|
//
|
|
// Copy the strings into the right places:
|
|
//
|
|
|
|
if (!LogonUserA(User, Domain, Password,
|
|
LogonType,
|
|
LOGON32_PROVIDER_DEFAULT, &hToken))
|
|
{
|
|
fprintf( fOut,"FAILED to logon, GetLastError is %d\n", GetLastError());
|
|
}
|
|
|
|
else
|
|
{
|
|
if (fMe & DUMP_TOKEN)
|
|
DumpToken(hToken);
|
|
|
|
if (!ImpersonateLoggedOnUser(hToken))
|
|
{
|
|
fprintf( fOut, "FAILED to impersonate, GetLastError is %d\n", GetLastError());
|
|
}
|
|
|
|
GetUserName(ImpersonateName, &cbImpersonateName);
|
|
if (fDup)
|
|
{
|
|
if (OpenThreadToken( GetCurrentThread(),
|
|
MAXIMUM_ALLOWED,
|
|
TRUE,
|
|
&hImp))
|
|
{
|
|
DumpToken( hImp );
|
|
if (DuplicateTokenEx( hImp,
|
|
MAXIMUM_ALLOWED,
|
|
NULL,
|
|
SecurityImpersonation,
|
|
TokenPrimary,
|
|
&hDup ) )
|
|
{
|
|
fprintf( fOut, "Success! Duplicated that token!\n");
|
|
DumpToken( hToken );
|
|
CloseHandle( hToken );
|
|
}
|
|
else
|
|
{
|
|
fprintf( fOut, "DuplicateTokenEx FAILED, %d\n", GetLastError() );
|
|
|
|
}
|
|
|
|
CloseHandle( hImp );
|
|
|
|
}
|
|
else
|
|
{
|
|
fprintf( fOut, "OpenThreadToken FAILED, %d\n", GetLastError() );
|
|
}
|
|
|
|
}
|
|
RevertToSelf();
|
|
fprintf( fOut,"Hey look! I'm %s\n", ImpersonateName);
|
|
|
|
if (Cmd)
|
|
{
|
|
fprintf( fOut,"Starting '%s' as user\n", Cmd);
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
if (!CreateProcessAsUser(hToken, NULL, Cmd, NULL, NULL, FALSE,
|
|
CREATE_SEPARATE_WOW_VDM, NULL,
|
|
NULL, &si, &pi))
|
|
{
|
|
fprintf( fOut,"FAILED, %d\n", GetLastError());
|
|
}
|
|
|
|
fprintf( fOut,"Process Info:\n");
|
|
fprintf( fOut," Process Handle \t%x\n", pi.hProcess );
|
|
fprintf( fOut," Thread Handle \t%x\n", pi.hThread );
|
|
fprintf( fOut," Process Id \t%d\n", pi.dwProcessId );
|
|
fprintf( fOut," Thread Id \t%d\n", pi.dwThreadId );
|
|
|
|
ZeroMemory( Buffer, 1024 );
|
|
|
|
pTypeInfo = (POBJECT_TYPE_INFORMATION) Buffer;
|
|
pNameInfo = (POBJECT_NAME_INFORMATION) Buffer;
|
|
pBasicInfo = (POBJECT_BASIC_INFORMATION) Buffer;
|
|
|
|
Status = NtQueryObject( pi.hProcess, ObjectTypeInformation, pTypeInfo, 1024, NULL );
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
fprintf( fOut," Type \t%ws\n", pTypeInfo->TypeName.Buffer );
|
|
}
|
|
|
|
ZeroMemory( Buffer, 1024 );
|
|
Status = NtQueryObject(pi.hProcess, ObjectBasicInformation, pBasicInfo, 1024, NULL);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
fprintf( fOut," Attributes \t%#x\n", pBasicInfo->Attributes );
|
|
fprintf( fOut," GrantedAccess\t%#x\n", pBasicInfo->GrantedAccess );
|
|
fprintf( fOut," HandleCount \t%d\n", pBasicInfo->HandleCount );
|
|
fprintf( fOut," PointerCount \t%d\n", pBasicInfo->PointerCount );
|
|
}
|
|
else
|
|
{
|
|
fprintf( fOut,"FAILED %x to query basic info\n", Status );
|
|
}
|
|
|
|
ZeroMemory( Buffer, 1024 );
|
|
Status = NtQueryObject( pi.hProcess, ObjectNameInformation, pNameInfo, 1024, NULL );
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
fprintf( fOut," Name \t%ws\n", pNameInfo->Name.Buffer);
|
|
}
|
|
else
|
|
{
|
|
fprintf( fOut,"FAILED %x to query name info\n", Status );
|
|
}
|
|
|
|
CloseHandle( pi.hProcess );
|
|
CloseHandle( pi.hThread );
|
|
|
|
}
|
|
CloseHandle(hToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
__cdecl
|
|
main (int argc, char *argv[])
|
|
{
|
|
HANDLE hWait;
|
|
DWORD i;
|
|
DWORD tid;
|
|
HANDLE hThreads[64];
|
|
|
|
fOut = stdout;
|
|
|
|
//
|
|
// Get params
|
|
//
|
|
DoArgs(argc, argv);
|
|
|
|
if (Threads == 1)
|
|
{
|
|
DoIt(NULL);
|
|
|
|
}
|
|
else
|
|
{
|
|
if (Threads > 64 )
|
|
{
|
|
Threads = 64;
|
|
}
|
|
|
|
hWait = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
|
|
for (i = 0; i < Threads ; i++ )
|
|
{
|
|
hThreads[i] = CreateThread( NULL, 0, DoIt, hWait, 0, &tid);
|
|
}
|
|
|
|
SetEvent( hWait );
|
|
|
|
WaitForMultipleObjectsEx( Threads, hThreads, TRUE, INFINITE, FALSE );
|
|
|
|
for ( i = 0 ; i < Threads ; i++ )
|
|
{
|
|
CloseHandle( hThreads[i] );
|
|
}
|
|
}
|
|
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
#define SATYPE_USER 1
|
|
#define SATYPE_GROUP 2
|
|
#define SATYPE_PRIV 3
|
|
|
|
|
|
ULONG PID;
|
|
|
|
void
|
|
DumpSid(PSID pxSid)
|
|
{
|
|
PISID pSid = pxSid;
|
|
int i, j =0;
|
|
|
|
|
|
fprintf( fOut," S-%d-", pSid->Revision);
|
|
for (i = 0;i < 6 ; i++ )
|
|
{
|
|
if (j)
|
|
{
|
|
fprintf( fOut,"%x", pSid->IdentifierAuthority.Value[i]);
|
|
}
|
|
else
|
|
{
|
|
if (pSid->IdentifierAuthority.Value[i])
|
|
{
|
|
j = 1;
|
|
fprintf( fOut,"%x", pSid->IdentifierAuthority.Value[i]);
|
|
}
|
|
}
|
|
if (i==4)
|
|
{
|
|
j = 1;
|
|
}
|
|
}
|
|
for (i = 0; i < pSid->SubAuthorityCount ; i++ )
|
|
{
|
|
fprintf( fOut,(fMe & DUMP_HEX ? "-%x" : "-%lu"), pSid->SubAuthority[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpSidAttr(PSID_AND_ATTRIBUTES pSA,
|
|
int SAType)
|
|
{
|
|
DumpSid(pSA->Sid);
|
|
|
|
if (SAType == SATYPE_GROUP)
|
|
{
|
|
fprintf( fOut,"\tAttributes - ");
|
|
if (pSA->Attributes & SE_GROUP_MANDATORY)
|
|
{
|
|
fprintf( fOut,"Mandatory ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_ENABLED_BY_DEFAULT)
|
|
{
|
|
fprintf( fOut,"Default ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_ENABLED)
|
|
{
|
|
fprintf( fOut,"Enabled ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_OWNER)
|
|
{
|
|
fprintf( fOut,"Owner ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_LOGON_ID)
|
|
{
|
|
fprintf( fOut,"LogonId ");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
CHAR * GetPrivName(PLUID pPriv)
|
|
{
|
|
switch (pPriv->LowPart)
|
|
{
|
|
case SE_CREATE_TOKEN_PRIVILEGE:
|
|
return(SE_CREATE_TOKEN_NAME);
|
|
case SE_ASSIGNPRIMARYTOKEN_PRIVILEGE:
|
|
return(SE_ASSIGNPRIMARYTOKEN_NAME);
|
|
case SE_LOCK_MEMORY_PRIVILEGE:
|
|
return(SE_LOCK_MEMORY_NAME);
|
|
case SE_INCREASE_QUOTA_PRIVILEGE:
|
|
return(SE_INCREASE_QUOTA_NAME);
|
|
case SE_UNSOLICITED_INPUT_PRIVILEGE:
|
|
return(SE_UNSOLICITED_INPUT_NAME);
|
|
case SE_TCB_PRIVILEGE:
|
|
return(SE_TCB_NAME);
|
|
case SE_SECURITY_PRIVILEGE:
|
|
return(SE_SECURITY_NAME);
|
|
case SE_TAKE_OWNERSHIP_PRIVILEGE:
|
|
return(SE_TAKE_OWNERSHIP_NAME);
|
|
case SE_LOAD_DRIVER_PRIVILEGE:
|
|
return(SE_LOAD_DRIVER_NAME);
|
|
case SE_SYSTEM_PROFILE_PRIVILEGE:
|
|
return(SE_SYSTEM_PROFILE_NAME);
|
|
case SE_SYSTEMTIME_PRIVILEGE:
|
|
return(SE_SYSTEMTIME_NAME);
|
|
case SE_PROF_SINGLE_PROCESS_PRIVILEGE:
|
|
return(SE_PROF_SINGLE_PROCESS_NAME);
|
|
case SE_INC_BASE_PRIORITY_PRIVILEGE:
|
|
return(SE_INC_BASE_PRIORITY_NAME);
|
|
case SE_CREATE_PAGEFILE_PRIVILEGE:
|
|
return(SE_CREATE_PAGEFILE_NAME);
|
|
case SE_CREATE_PERMANENT_PRIVILEGE:
|
|
return(SE_CREATE_PERMANENT_NAME);
|
|
case SE_BACKUP_PRIVILEGE:
|
|
return(SE_BACKUP_NAME);
|
|
case SE_RESTORE_PRIVILEGE:
|
|
return(SE_RESTORE_NAME);
|
|
case SE_SHUTDOWN_PRIVILEGE:
|
|
return(SE_SHUTDOWN_NAME);
|
|
case SE_DEBUG_PRIVILEGE:
|
|
return(SE_DEBUG_NAME);
|
|
case SE_AUDIT_PRIVILEGE:
|
|
return(SE_AUDIT_NAME);
|
|
case SE_SYSTEM_ENVIRONMENT_PRIVILEGE:
|
|
return(SE_SYSTEM_ENVIRONMENT_NAME);
|
|
case SE_CHANGE_NOTIFY_PRIVILEGE:
|
|
return(SE_CHANGE_NOTIFY_NAME);
|
|
case SE_REMOTE_SHUTDOWN_PRIVILEGE:
|
|
return(SE_REMOTE_SHUTDOWN_NAME);
|
|
default:
|
|
return("Unknown Privilege");
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpLuidAttr(PLUID_AND_ATTRIBUTES pLA,
|
|
int LAType)
|
|
{
|
|
char * PrivName;
|
|
|
|
fprintf( fOut,"0x%x%08x", pLA->Luid.HighPart, pLA->Luid.LowPart);
|
|
fprintf( fOut," %-32s", GetPrivName(&pLA->Luid));
|
|
|
|
if (LAType == SATYPE_PRIV)
|
|
{
|
|
fprintf( fOut," Attributes - ");
|
|
if (pLA->Attributes & SE_PRIVILEGE_ENABLED)
|
|
{
|
|
fprintf( fOut,"Enabled ");
|
|
}
|
|
|
|
if (pLA->Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
|
|
{
|
|
fprintf( fOut,"Default ");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
DumpToken(HANDLE hToken)
|
|
{
|
|
PTOKEN_USER pTUser;
|
|
PTOKEN_GROUPS pTGroups;
|
|
PTOKEN_PRIVILEGES pTPrivs;
|
|
PTOKEN_OWNER pTOwner;
|
|
PTOKEN_PRIMARY_GROUP pTPrimaryGroup;
|
|
TOKEN_STATISTICS TStats;
|
|
ULONG cbInfo;
|
|
ULONG cbRetInfo;
|
|
NTSTATUS status;
|
|
DWORD i;
|
|
|
|
|
|
pTUser = malloc(256);
|
|
|
|
|
|
status = GetTokenInformation( hToken,
|
|
TokenUser,
|
|
pTUser,
|
|
256,
|
|
&cbRetInfo);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
fprintf( fOut,"FAILED querying token, %#x\n", status);
|
|
return;
|
|
}
|
|
|
|
fprintf( fOut,"User\n ");
|
|
DumpSidAttr(&pTUser->User, SATYPE_USER);
|
|
|
|
fprintf( fOut,"\nGroups");
|
|
pTGroups = malloc(4096);
|
|
status = GetTokenInformation( hToken,
|
|
TokenGroups,
|
|
pTGroups,
|
|
4096,
|
|
&cbRetInfo);
|
|
|
|
for (i = 0; i < pTGroups->GroupCount ; i++ )
|
|
{
|
|
fprintf( fOut,"\n %02d ", i);
|
|
DumpSidAttr(&pTGroups->Groups[i], SATYPE_GROUP);
|
|
}
|
|
|
|
pTPrimaryGroup = malloc(128);
|
|
status = GetTokenInformation( hToken,
|
|
TokenPrimaryGroup,
|
|
pTPrimaryGroup,
|
|
128,
|
|
&cbRetInfo);
|
|
|
|
fprintf( fOut,"\nPrimary Group:\n ");
|
|
DumpSid(pTPrimaryGroup->PrimaryGroup);
|
|
|
|
fprintf( fOut,"\nPrivs\n");
|
|
pTPrivs = malloc(4096);
|
|
status = GetTokenInformation( hToken,
|
|
TokenPrivileges,
|
|
pTPrivs,
|
|
4096,
|
|
&cbRetInfo);
|
|
|
|
for (i = 0; i < pTPrivs->PrivilegeCount ; i++ )
|
|
{
|
|
fprintf( fOut,"\n %02d ", i);
|
|
DumpLuidAttr(&pTPrivs->Privileges[i], SATYPE_PRIV);
|
|
}
|
|
|
|
status = GetTokenInformation( hToken,
|
|
TokenStatistics,
|
|
&TStats,
|
|
sizeof(TStats),
|
|
&cbRetInfo);
|
|
|
|
fprintf( fOut, "\n\nAuth ID %x:%x\n", TStats.AuthenticationId.HighPart, TStats.AuthenticationId.LowPart);
|
|
fprintf( fOut, "TokenId %x:%x\n", TStats.TokenId.HighPart, TStats.TokenId.LowPart);
|
|
fprintf( fOut, "TokenType %s\n", TStats.TokenType == TokenPrimary ? "Primary" : "Impersonation");
|
|
fprintf( fOut, "Imp Level %s\n", ImpLevels[ TStats.ImpersonationLevel ]);
|
|
|
|
}
|
|
|
|
|
|
|