#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define _WIN32_WINNT 0x500
#include<windows.h>
#include<tchar.h>
#include<iostream>
#include<sddl.h>
#include"sized_array.h"
const DWORD MAX_USERNAME_LENGTH = 260;
void PrintPrivAttrib(DWORD Attributes);
void PrintAttrib(DWORD Attributes);
void PrintSid(PSID SidUser);
int PrintUserFromToken(HANDLE hToken);
void DoWhoAmI(void);
#ifndef MAIN_INCLUDED
int main(void)
{
try {
DoWhoAmI();
} catch(std::logic_error &e) {
std::wcout << _T("\r\nFatal error:\t") << e.what() << std::endl;
}
return 0;
}
#endif /* MAIN_INCLUDED. If there is no main() available, make a stub. */
void DoWhoAmI(void)
{
size_t i = 0;
HANDLE ProcToken = NULL;
TOKEN_GROUPS_AND_PRIVILEGES *tp = NULL;
DWORD ReturnLength = 0, TokenInformationLength = 0;
if( !::OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &ProcToken) &&
!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &ProcToken))
{/* Get the current access token. */
throw std::logic_error("Error opening access token");
}
/* Get the username from the token. */
std::wcout << _T("[User] = ");
PrintUserFromToken(ProcToken);
/* Get the TOKEN_GROUPS_AND_PRIVILEGES from the token. */
::GetTokenInformation(ProcToken, TokenGroupsAndPrivileges, NULL, TokenInformationLength, &ReturnLength);
std::sized_array<BYTE> tpBuf(ReturnLength) ;
TokenInformationLength = ReturnLength;
::GetTokenInformation(ProcToken, TokenGroupsAndPrivileges, tpBuf.get(), TokenInformationLength, &ReturnLength);
tp = reinterpret_cast<TOKEN_GROUPS_AND_PRIVILEGES *>(tpBuf.get());
/** All the information we need for Whoami is contained in TOKEN_GROUPS_AND_PRIVILEGES
* The rest of the program deals with printing the information from this access token.
**/
std::wcout << _T("\r\nAuthentication ID:") << (tp->AuthenticationId.HighPart)
<< tp->AuthenticationId.LowPart << _T("\r\nGroups");
for(i = 0; i < tp->SidCount; i++)
{/* Groups */
std::wcout << _T("\r\n[Group ") << static_cast<unsigned int>(i) << _T("] ");
PrintSid(tp->Sids[i].Sid);
PrintAttrib(tp->Sids[i].Attributes);
}
std::wcout << _T("\r\n\r\nRestricted Sids");
for(i = 0; i < tp->RestrictedSidCount; i++)
{/* Restricted Sids */
std::wcout << _T("\r\n[SID ") << static_cast<unsigned int>(i) << _T("] ");
PrintSid(tp->RestrictedSids[i].Sid);
PrintAttrib(tp->RestrictedSids[i].Attributes);
}
std::wcout << _T("\r\n\r\nPrivileges\r\n");
for(i = 0; i < tp->PrivilegeCount; i++)
{/* Privileges */
ReturnLength = 0;
::LookupPrivilegeName(NULL, &tp->Privileges[i].Luid, NULL, &ReturnLength);
ReturnLength++;
/* Docs are rather unclear on the null terminator ambiguity. Better safe than sorry. */
std::sized_array<TCHAR> PrivilegeName (ReturnLength);
::LookupPrivilegeName(NULL, &tp->Privileges[i].Luid, PrivilegeName.get(), &ReturnLength);
PrintPrivAttrib(tp->Privileges[i].Attributes);
std::wcout << _T("\t\t") << PrivilegeName.get() << _T("\r\n");
}
::CloseHandle(ProcToken); ProcToken = NULL;
}
int PrintUserFromToken(HANDLE hToken)
{
/* Get the current user from GetTokenInformation(TokenUser) */
DWORD ReturnLength = 0, TokenInformationLength = 0;
::GetTokenInformation(hToken, TokenUser, NULL, TokenInformationLength, &ReturnLength);
std::sized_array<BYTE> TokenInformation(ReturnLength);
TokenInformationLength = ReturnLength;
if(::GetTokenInformation(hToken, TokenUser, TokenInformation.get(), TokenInformationLength, &ReturnLength))
{/* Now that we have the SID, convert it to a user name */
TOKEN_USER *tp = reinterpret_cast<TOKEN_USER *>(TokenInformation.get());
PrintSid(tp->User.Sid);
}
return 0;
}
void PrintSid(PSID SidUser)
{/** This function takes a SID, and prints both the username, and the textual SID. **/
LPTSTR SidText = NULL;
DWORD cchName = 0, cchReferencedDomainName = 0;
SID_NAME_USE peUse = SidTypeUser;
::LookupAccountSid(NULL, SidUser, NULL,
&cchName, NULL, &cchReferencedDomainName, &peUse);
std::sized_array<TCHAR> UserName(cchName);
std::sized_array<TCHAR> ReferencedDomainName(cchReferencedDomainName);
if(::LookupAccountSid(NULL, SidUser, UserName.get(),
&cchName, ReferencedDomainName.get(), &cchReferencedDomainName, &peUse))
{/* Get the username */
std::wcout << ReferencedDomainName.get() << _T("\\");
std::wcout << UserName.get();
if(::ConvertSidToStringSid(SidUser, &SidText))
{
std::wcout << _T(" (") << SidText << _T(")");
::LocalFree(SidText); SidText = NULL;
}
}
}
void PrintPrivAttrib(DWORD Attributes)
{/* This function prints out the attributes from a SID. */
std::basic_ostream<TCHAR, std::char_traits<TCHAR> > &s = std::wcout;
if(Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
{
s << _T("default ");
}
if(Attributes & SE_PRIVILEGE_ENABLED)
{
s << _T("enabled, ");
}
if(Attributes & SE_PRIVILEGE_REMOVED)
{
s << _T("removed, ");
}
if(Attributes & SE_PRIVILEGE_USED_FOR_ACCESS)
{
s << _T("used for access, ");
}
}
void PrintAttrib(DWORD Attributes)
{/* Obtain the group type */
std::basic_ostream<TCHAR, std::char_traits<TCHAR> > &s = std::wcout;
if(Attributes & SE_GROUP_OWNER)
{
s << _T(", owner");
}
if(Attributes & SE_GROUP_ENABLED_BY_DEFAULT)
{
s << _T(", default");
}
if(Attributes & SE_GROUP_RESOURCE)
{
s << _T(", domain-local");
}
if(Attributes & SE_GROUP_MANDATORY)
{
s << _T(", mandatory");
}
if(Attributes & SE_GROUP_USE_FOR_DENY_ONLY)
{
s << _T(", deny");
}
}