//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: logon2.c // // Contents: Logon test app // // Classes: // // Functions: // // History: 6-20-94 richardw Created // //---------------------------------------------------------------------------- #ifdef UNICODE #undef UNICODE #endif #include #include #include #include #include #include #include #include #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); BOOL WINAPI KerbLogonUserW( PWSTR lpszUsername, PWSTR lpszDomain, PWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, HANDLE * phToken ); BOOL WINAPI KerbLogonUserA( LPSTR lpszUsername, LPSTR lpszDomain, LPSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, HANDLE * phToken ); BOOL Logon32Initialize( VOID ); void DoArgs(int argc, char **argv) { int i; Threads = 1; if (argc < 3) { fprintf( fOut,"usage: %s [-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 (!KerbLogonUserA(User, Domain, Password, LogonType, LOGON32_PROVIDER_WINNT40, &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 ); #ifdef notdef 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 ); } #endif 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; Logon32Initialize(); // // 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 ]); }