2012年7月5日星期四

LookupAccountName.Cpp

/*
sid一个神秘的东西,本想是获取或者枚举用户和它的关系.
这里有两个从微软搬过来的函数,
一个是从句柄获得sid,这个好像有问题,难道是我使用的问题.
一个是从(用户)名字获取sid.这个经试验是好的.
这里主要用了两个函数:GetTokenInformation,LookupAccountNameW
因为用GetTokenInformation的函数获取的东西好像有点问题,所以此文就命名为:LookupAccountName.Cpp.
*/

#include "stdafx.h"
#include <windows.h>
#include "D:\Program Files\Microsoft Visual Studio 9.0\SmartDevices\SDK\Smartphone2003\Include\mq.h"
#include <Sddl.h>
#pragma comment(lib, "advapi32.lib")

//http://msdn.microsoft.com/en-us/library/windows/desktop/aa446670(v=vs.85).aspx
BOOL GetLogonSID (HANDLE hToken, PSID *ppsid)
{
    BOOL bSuccess = FALSE;
    DWORD dwIndex;
    DWORD dwLength = 0;
    PTOKEN_GROUPS ptg = NULL;
   
    if (NULL == ppsid)// Verify the parameter passed in is not NULL.
        goto Cleanup;
   
    if (!GetTokenInformation(// Get required buffer size and allocate the TOKEN_GROUPS buffer.
        hToken,         // handle to the access token
        TokenGroups,    // get information about the token's groups
        (LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer
        0,              // size of buffer
        &dwLength       // receives required buffer size
        ))
    {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            goto Cleanup;

        ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwLength);
        if (ptg == NULL)
            goto Cleanup;
    }
   
    if (!GetTokenInformation(hToken,TokenGroups,(LPVOID) ptg,dwLength,&dwLength)) {// Get the token group information from the access token.
        goto Cleanup;
    }

    // Loop through the groups to find the logon SID.
    for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) //这个没有大括号.
        if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)  ==  SE_GROUP_LOGON_ID)
        {   // Found the logon SID; make a copy of it.
            dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
            *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
            if (*ppsid == NULL)
                goto Cleanup;
            if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))
            {
                HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
                goto Cleanup;
            }
            break;
        }

        bSuccess = TRUE;
Cleanup:
        if (ptg != NULL)// Free the buffer for the token groups.
            HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);

        return bSuccess;
}

//这个不要了.
//VOID FreeLogonSID (PSID *ppsid)
//{
//    HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
//}

//http://msdn.microsoft.com/en-us/library/windows/desktop/ms707085(v=vs.85).aspx
//还有一个函数:CreateQSecDescriptor
HRESULT GetSid(LPCWSTR wszAccName,PSID * ppSid) //此函数,还可以精简,我没有精简.
{  
    if (wszAccName == NULL || ppSid == NULL) {// Validate the input parameters.
        return MQ_ERROR_INVALID_PARAMETER;
    }

    // Create buffers that may be large enough.If a buffer is too small, the count parameter will be set to the size needed.
    const DWORD INITIAL_SIZE = 32;
    DWORD cbSid = 0;
    DWORD dwSidBufferSize = INITIAL_SIZE;
    DWORD cchDomainName = 0;
    DWORD dwDomainBufferSize = INITIAL_SIZE;
    WCHAR * wszDomainName = NULL;
    SID_NAME_USE eSidType;
    DWORD dwErrorCode = 0;
    HRESULT hr = MQ_OK;
   
    *ppSid = (PSID) new BYTE[dwSidBufferSize];// Create buffers for the SID and the domain name.
    if (*ppSid == NULL) {
        return MQ_ERROR_INSUFFICIENT_RESOURCES;
    }
    memset(*ppSid, 0, dwSidBufferSize);
    wszDomainName = new WCHAR[dwDomainBufferSize];
    if (wszDomainName == NULL) {
        return MQ_ERROR_INSUFFICIENT_RESOURCES;
    }
    memset(wszDomainName, 0, dwDomainBufferSize*sizeof(WCHAR));
   
    for ( ; ; )// Obtain the SID for the account name passed.
    {   // Set the count variables to the buffer sizes and retrieve the SID.
        cbSid = dwSidBufferSize;
        cchDomainName = dwDomainBufferSize;
        if (LookupAccountNameW(
            NULL,            // Computer name. NULL for the local computer
            wszAccName,
            *ppSid,          // Pointer to the SID buffer. Use NULL to get the size needed,
            &cbSid,          // Size of the SID buffer needed.
            wszDomainName,   // wszDomainName,//这个还能获取域名.
            &cchDomainName,
            &eSidType)) //其实这个函数就是返回sid和域名用的别的没啥,不要多想,下面的是垃圾,加上更完美.
        {
            if (IsValidSid(*ppSid) == FALSE)
            {
                wprintf(L"The SID for %s is invalid.\n", wszAccName);
                dwErrorCode = MQ_ERROR;
            }
            break;
        }
        dwErrorCode = GetLastError();
     
        if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER) // Check if one of the buffers was too small.
        {
            if (cbSid > dwSidBufferSize)
            {   // Reallocate memory for the SID buffer.
                wprintf(L"The SID buffer was too small. It will be reallocated.\n");
                FreeSid(*ppSid);
                *ppSid = (PSID) new BYTE[cbSid];
                if (*ppSid == NULL)
                {
                    return MQ_ERROR_INSUFFICIENT_RESOURCES;
                }
                memset(*ppSid, 0, cbSid);
                dwSidBufferSize = cbSid;
            }
            if (cchDomainName > dwDomainBufferSize)
            {   // Reallocate memory for the domain name buffer.
                wprintf(L"The domain name buffer was too small. It will be reallocated.\n");
                delete [] wszDomainName;
                wszDomainName = new WCHAR[cchDomainName];
                if (wszDomainName == NULL)
                {
                    return MQ_ERROR_INSUFFICIENT_RESOURCES;
                }
                memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));
                dwDomainBufferSize = cchDomainName;
            }
        }
        else
        {
            wprintf(L"LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
            hr = HRESULT_FROM_WIN32(dwErrorCode);
            break;
        }
    }

    delete [] wszDomainName;
    return hr;
}

//http://msdn.microsoft.com/en-us/library/windows/desktop/aa379554(v=vs.85).aspx
#define MAX_NAME 256
BOOL SearchTokenGroupsForSID (VOID) //这个暂时放这里.不做讨论.
{
    DWORD i, dwSize = 0, dwResult = 0;
    HANDLE hToken;
    PTOKEN_GROUPS pGroupInfo;
    SID_NAME_USE SidType;
    char lpName[MAX_NAME];
    char lpDomain[MAX_NAME];
    PSID pSID = NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;

    // Open a handle to the access token for the calling process.
    if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ))
    {
        printf( "OpenProcessToken Error %u\n", GetLastError() );
        return FALSE;
    }

    // Call GetTokenInformation to get the buffer size.
    if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
    {
        dwResult = GetLastError();
        if( dwResult != ERROR_INSUFFICIENT_BUFFER ) {
            printf( "GetTokenInformation Error %u\n", dwResult );
            return FALSE;
        }
    }

    // Allocate the buffer.
    pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc( GPTR, dwSize );

    // Call GetTokenInformation again to get the group information.
    if(! GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize ) )
    {
        printf( "GetTokenInformation Error %u\n", GetLastError() );
        return FALSE;
    }

    // Create a SID for the BUILTIN\Administrators group.
    if(! AllocateAndInitializeSid( &SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID) )
    {
        printf( "AllocateAndInitializeSid Error %u\n", GetLastError() );
        return FALSE;
    }

    // Loop through the group SIDs looking for the administrator SID.
    for(i=0; i<pGroupInfo->GroupCount; i++)
    {
        if ( EqualSid(pSID, pGroupInfo->Groups[i].Sid) )
        {   // Lookup the account name and print it.
            dwSize = MAX_NAME;
            if( !LookupAccountSid( NULL, pGroupInfo->Groups[i].Sid, (LPWSTR)lpName, &dwSize, (LPWSTR)lpDomain, &dwSize, &SidType ) )  //此函数能实现根据sid获取用户名的功能,进而可以想办法利用此函数进行枚举.
            {
                dwResult = GetLastError();
                if( dwResult == ERROR_NONE_MAPPED )
                    strcpy_s (lpName, dwSize, "NONE_MAPPED" );
                else
                {
                    printf("LookupAccountSid Error %u\n", GetLastError());
                    return FALSE;
                }
            }
            printf( "Current user is a member of the %s\\%s group\n", lpDomain, lpName );

            // Find out whether the SID is enabled in the token.
            if (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
                printf("The group SID is enabled.\n");
            else if (pGroupInfo->Groups[i].Attributes & SE_GROUP_USE_FOR_DENY_ONLY)
                printf("The group SID is a deny-only SID.\n");
            else
                printf("The group SID is not enabled.\n");
        }
    }

    if (pSID)
        FreeSid(pSID);
    if ( pGroupInfo )
        GlobalFree( pGroupInfo );
    return TRUE;
}

//更多的还有http://msdn.microsoft.com/en-us/library/windows/desktop/aa379608(v=vs.85).aspx

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t sz_UserNamew[260] = {0};
    int len = sizeof(sz_UserNamew);
    GetUserName(sz_UserNamew,(LPDWORD)&len);

    LPWSTR * wsz_sid = (LPWSTR *)HeapAlloc(GetProcessHeap(), 0, 0x200);
    PSID * ppSid = (PSID *)HeapAlloc(GetProcessHeap(), 0, 0x200);

    GetSid(sz_UserNamew,ppSid);//Administrator,Defaultapppool应该有枚举的办法.NetUserEnum,但不全.特殊的没有.
    bool  b = ConvertSidToStringSid(*ppSid,(LPWSTR *)wsz_sid);
    int x = GetLastError();
    MessageBox(0,(LPCWSTR)(* ( int *)wsz_sid),0,0);

    RtlZeroMemory(wsz_sid,0x200);
    RtlZeroMemory(ppSid,0x200);

    HANDLE hToken;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY_SOURCE | TOKEN_QUERY, &hToken)) return( FALSE );
    GetLogonSID(hToken,ppSid);//字面意思是登录的sid,用的是当前进程或者线程的句柄.
    b = ConvertSidToStringSid(*ppSid,(LPWSTR *)wsz_sid);
    x = GetLastError();
    MessageBox(0,(LPCWSTR)(* ( int *)wsz_sid),0,0);//得到的这个值在注册表中找不到.HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

    HeapFree(GetProcessHeap(), 0, wsz_sid);
    HeapFree(GetProcessHeap(), 0, ppSid);

    SearchTokenGroupsForSID();

 return 0;
}
//made by correy.


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
参考:Microsoft SDKs\Windows\v7.1\Samples\security\authorization\textsid这个工程.
获取当前用户(进程的)SID更简单.其实也就这么简单.
made at 2013.10.10
*/

#include <windows.h>
#include <Sddl.h>

int _tmain()
{
#define MY_BUFSIZE 256 // all allocations should be dynamic
    HANDLE hToken;
    BYTE buf[MY_BUFSIZE];
    PTOKEN_USER ptgUser = (PTOKEN_USER)buf;
    DWORD cbBuffer=MY_BUFSIZE;
    BOOL bSuccess;

    // obtain current process token
    if(!OpenProcessToken(
        GetCurrentProcess(), // target current process
        TOKEN_QUERY,         // TOKEN_QUERY access
        &hToken              // resultant hToken
        ))  {
            return 1;
    }

    // obtain user identified by current process' access token
    bSuccess = GetTokenInformation(
        hToken,    // identifies access token
        TokenUser, // TokenUser info type
        ptgUser,   // retrieved info buffer
        cbBuffer,  // size of buffer passed-in
        &cbBuffer  // required buffer size
        );
    CloseHandle(hToken);
    if(!bSuccess) {
        return 1;
    }

    LPWSTR lpSid = NULL;
    ConvertSidToStringSid(ptgUser->User.Sid, &lpSid);

    //这时已经获取到了,可以查看了.

    LocalFree(lpSid);

    return 1;
}

没有评论:

发表评论