2014年6月15日星期日

枚举系统的登录会话及其信息

#include "stdafx.h"

/*
文件名:LsaEnumerateLogonSessions.Cpp
功能:枚举系统的登录的会话及其信息。
说明:看名字是枚举会话的,其实还有很多的用户名,会话是会重复的。
      感觉还不如枚举进程,然后收集进程的会话信息方便呢?

会话,好多人都听说过。
如网络上的,网页的链接,TCP/Http的链接等。
这里说的是系统的登录的会话。

这好像用处不大,只是在远程登录/多用户的情况下会考虑到。
但是用到了,就必须会,解决掉。

再说:会话的ID也不一定是连续的。
如登录一个会话,然后再注销,再登录看看:注销的那个会话的ID就不再了,但是后面登录的是还存在的。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa378290(v=vs.85).aspx
这个页面的LSAFreeReturnBuffer也写错了,严格的说是大小写错误。

made by correy
made at 2014.06.15
homepage:http://correy.webs.com
*/


#ifndef UNICODE
#define UNICODE
#endif // UNICODE

#include <windows.h>
//#include <stdio.h>

#include <Ntsecapi.h>
#pragma comment (lib,"Secur32.lib")

//#include "ntsecapi.h"

#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13

// If you have the ddk, include ntstatus.h.
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#endif


void DisplayWinError(LPSTR szAPI, DWORD WinError)
{
    LPSTR MessageBuffer;
    DWORD dwBufferLength;

    // TODO: Get this fprintf out of here!
    fprintf(stderr,"%s error!\n", szAPI);

    if(dwBufferLength=FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, WinError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &MessageBuffer, 0, NULL))
    {
        DWORD dwBytesWritten; // unused
        WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL);// Output message string on stderr.       
        LocalFree(MessageBuffer);// Free the buffer allocated by the system.
    }
}


void DisplayNtStatus(LPSTR szAPI, NTSTATUS Status)
{    
    DisplayWinError(szAPI, LsaNtStatusToWinError(Status));// Convert the NTSTATUS to Winerror. Then call DisplayWinError().
}


int __cdecl main(int argc, char *argv[])
{
    NTSTATUS Status; 
    int iRetVal=RTN_ERROR;
    ULONG LogonSessionCount;
    PLUID LogonSessionList;

    Status = LsaEnumerateLogonSessions(&LogonSessionCount, & LogonSessionList);
    if (Status != STATUS_SUCCESS) {
        DisplayNtStatus("LsaEnumerateLogonSessions", Status);
        return RTN_ERROR;
    }

    /*
    登录的会话还挺多的。
    几个用户同时登录还会重复。
    */

    ULONG i = 0;
    for (PLUID p = LogonSessionList; i < LogonSessionCount; i++ )
    {
        //To retrieve information about a logon session, the caller must be the owner of the session or a local system administrator.
        PSECURITY_LOGON_SESSION_DATA ppLogonSessionData;
        Status = LsaGetLogonSessionData(p, & ppLogonSessionData);
        if (Status != STATUS_SUCCESS) {
            DisplayNtStatus("LsaGetLogonSessionData", Status);
            return RTN_ERROR;//break;
        }

        if (ppLogonSessionData->UserName.Length)
        {
            fprintf(stderr,"UserName:%wZ!\n", &ppLogonSessionData->UserName);
        }
        if (ppLogonSessionData->LogonDomain.Length)
        {
            fprintf(stderr,"LogonDomain:%wZ!\n", &ppLogonSessionData->LogonDomain);
        }
        if (ppLogonSessionData->AuthenticationPackage.Length)
        {
            fprintf(stderr,"AuthenticationPackage:%wZ!\n", &ppLogonSessionData->AuthenticationPackage);
        }

        if (ppLogonSessionData->LogonServer.Length)
        {
            fprintf(stderr,"LogonServer:%wZ!\n", &ppLogonSessionData->LogonServer);
        }
        if (ppLogonSessionData->DnsDomainName.Length)
        {
            fprintf(stderr,"DnsDomainName:%wZ!\n", &ppLogonSessionData->DnsDomainName);
        }
        if (ppLogonSessionData->Upn.Length)
        {
            fprintf(stderr,"Upn:%wZ!\n", &ppLogonSessionData->Upn);
        }

        if (ppLogonSessionData->LogonScript.Length)
        {
            fprintf(stderr,"LogonScript:%wZ!\n", &ppLogonSessionData->LogonScript);
        }
        if (ppLogonSessionData->ProfilePath.Length)
        {
            fprintf(stderr,"ProfilePath:%wZ!\n", &ppLogonSessionData->ProfilePath);
        }
        if (ppLogonSessionData->HomeDirectory.Length)
        {
            fprintf(stderr,"HomeDirectory:%wZ!\n", &ppLogonSessionData->HomeDirectory);
        }
        if (ppLogonSessionData->HomeDirectoryDrive.Length)
        {
            fprintf(stderr,"HomeDirectoryDrive:%wZ!\n", &ppLogonSessionData->HomeDirectoryDrive);
        }

        if (ppLogonSessionData->LogonType == Interactive)
        {
            fprintf(stderr,"LogonType:Interactive!\n");//有几个普通的帐户登录,这里就会显示几次。就是说可以显示多个。
        }
        else if (ppLogonSessionData->LogonType == Network)
        {
            fprintf(stderr,"LogonType:Network!\n");
        }
        else if (ppLogonSessionData->LogonType == Service)
        {
            fprintf(stderr,"LogonType:Service!\n");
        }
        else 
        {
            fprintf(stderr,"LogonType:%d!\n", ppLogonSessionData->LogonType);
        }        

        /*摘自:\Microsoft SDKs\Windows\v7.1A\Include\NTSecAPI.h
        //
        // Values for UserFlags.
        //

        #define LOGON_GUEST                 0x01
        #define LOGON_NOENCRYPTION          0x02
        #define LOGON_CACHED_ACCOUNT        0x04
        #define LOGON_USED_LM_PASSWORD      0x08
        #define LOGON_EXTRA_SIDS            0x20
        #define LOGON_SUBAUTH_SESSION_KEY   0x40
        #define LOGON_SERVER_TRUST_ACCOUNT  0x80
        #define LOGON_NTLMV2_ENABLED        0x100       // says DC understands NTLMv2
        #define LOGON_RESOURCE_GROUPS       0x200
        #define LOGON_PROFILE_PATH_RETURNED 0x400
        // Defined in Windows Server 2008 and above
        #define LOGON_NT_V2                 0x800   // NT response was used for validation
        #define LOGON_LM_V2                 0x1000  // LM response was used for validation
        #define LOGON_NTLM_V2               0x2000  // LM response was used to authenticate but NT response was used to derive the session key

        #if (_WIN32_WINNT >= 0x0600)

        #define LOGON_OPTIMIZED             0x4000  // this is an optimized logon
        #define LOGON_WINLOGON              0x8000  // the logon session was created for winlogon
        #define LOGON_PKINIT               0x10000  // Kerberos PKINIT extension was used to authenticate the user
        #define LOGON_NO_OPTIMIZED         0x20000  // optimized logon has been disabled for this account

        #endif
        */
        if (ppLogonSessionData->UserFlags & LOGON_WINLOGON)
        {
            fprintf(stderr,"UserFlags:LOGON_WINLOGON!\n");//经测试,感觉这个就是普通用户的登录。远程登录的没有试验。
        }
        //else if (ppLogonSessionData->UserFlags & LOGON_NTLMV2_ENABLED)
        //{
        //    fprintf(stderr,"UserFlags:LOGON_NTLMV2_ENABLED!\n");
        //}
        //else if (ppLogonSessionData->UserFlags == LOGON_EXTRA_SIDS)
        //{
        //    fprintf(stderr,"UserFlags:LOGON_EXTRA_SIDS!\n");
        //}
        else if (ppLogonSessionData->UserFlags == 0)
        {
            fprintf(stderr,"UserFlags:%d!\n", ppLogonSessionData->UserFlags);
        }        

        fprintf(stderr,"Session:%d!\n", ppLogonSessionData->Session);

        /*
        还有更多新信息就不打印了,如SID,时间的转换等。
        */

        fprintf(stderr,"\n");
        fprintf(stderr,"\n");

        Status = LsaFreeReturnBuffer(ppLogonSessionData);
        if(Status != STATUS_SUCCESS) {
            DisplayNtStatus(" LSAFreeReturnBuffer", Status);
            return RTN_ERROR;//break;
        }

        p ++;
    }

    Status = LsaFreeReturnBuffer(LogonSessionList);
    if(Status != STATUS_SUCCESS) {
        DisplayNtStatus(" LSAFreeReturnBuffer", Status);
        return RTN_ERROR;
    }   

    iRetVal=RTN_OK;

    return iRetVal;
}

没有评论:

发表评论