2014年6月14日星期六

枚举用户(组)的特权

#include "stdafx.h"


/*
进程继承用户的权限。
程序员大多知道给进程提权。
但是有的进程的某些权限是不易搞到的。
如:Note that your process must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges for successful execution of CreateProcessAsUser. 
解决办法是用LsaAddAccountRights/LsaRemoveAccountRights给用户添加/删除权限。
然后在用常用的办法提权。
可是这要求注销/重启系统。

记得有个办法是不用重启的,但是忘了方法和链接了。
所以谨记此文。
此文的功能是枚举用户或者用户组的权限的。
此文修改自:Microsoft SDKs\Windows\v6.0\Samples\Security\LSAPolicy\LsaPrivs\LsaPrivs.c。

注意:Unlike privileges, however, account rights are not supported by the LookupPrivilegeValue and LookupPrivilegeName functions.
用户的特权很重要,如:
修改固件环境值。
加载驱动。
启动服务,服务一般不是普通用户运行的。
以操作系统方式执行。
更多信息,请看:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb545671(v=vs.85).aspx  Account Rights Constants
http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx  Privilege Constants
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/08bc7712-548c-4308-a49c-d551a4b5e245.mspx?mfr=true
等等。
 
更多的功能请看:
LsaEnumerateAccountsWithUserRight 
LsaEnumerateTrustedDomains
LsaEnumerateTrustedDomainsEx 
NetEnumerateServiceAccounts (Windows 7/Windows Server 2008 R2)

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


#ifndef UNICODE
#define UNICODE
#endif // UNICODE

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

#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


BOOL GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid)
    /*++
    This function attempts to obtain a SID representing the supplied account on the supplied system.

    If the function succeeds, the return value is TRUE. 
    A buffer is allocated which contains the SID representing the supplied account.
    This buffer should be freed when it is no longer needed by calling HeapFree(GetProcessHeap(), 0, buffer)

    If the function fails, the return value is FALSE. Call GetLastError() to obtain extended error information.
    --*/
{
    LPTSTR ReferencedDomain=NULL;
    LPTSTR TempReferencedDomain = NULL;
    LPTSTR TempSid = NULL;
    DWORD cbSid=128;    // initial allocation attempt
    DWORD cchReferencedDomain=16; // initial allocation size
    SID_NAME_USE peUse;
    BOOL bSuccess=FALSE; // assume this function will fail

    __try
    {
        *Sid = (PSID)HeapAlloc(GetProcessHeap(), 0, cbSid);// initial memory allocations
        if(*Sid == NULL) __leave;

        ReferencedDomain = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, cchReferencedDomain * sizeof(TCHAR));
        if(ReferencedDomain == NULL) __leave;

        // Obtain the SID of the specified account on the specified system.
        while(!LookupAccountName(
            SystemName,         // machine to lookup account on
            AccountName,        // account to lookup
            *Sid,               // SID of interest
            &cbSid,             // size of SID
            ReferencedDomain,   // domain account was found on
            &cchReferencedDomain, &peUse)) 
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
            {
                TempSid  = (LPTSTR)HeapReAlloc(GetProcessHeap(), 0, *Sid, cbSid);// reallocate memory
                if(TempSid  == NULL) __leave;
                *Sid = TempSid;

                TempReferencedDomain = (LPTSTR)HeapReAlloc(GetProcessHeap(), 0, ReferencedDomain, cchReferencedDomain * sizeof(TCHAR));

                if(TempReferencedDomain == NULL) __leave;
                ReferencedDomain = TempReferencedDomain;              
            }
            else __leave;
        }

        bSuccess=TRUE;// Indicate success.
    } // try
    __finally {// Cleanup and indicate failure, if appropriate.
        HeapFree(GetProcessHeap(), 0, ReferencedDomain);
        if(!bSuccess) {
            if(*Sid != NULL) {
                HeapFree(GetProcessHeap(), 0, *Sid);
                *Sid = NULL;
            }
        }
    } // finally

    return bSuccess;
}


void InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
{
    DWORD StringLength;

    if(String == NULL) {
        LsaString->Buffer = NULL;
        LsaString->Length = 0;
        LsaString->MaximumLength = 0;
        return;
    }

    StringLength = lstrlenW(String);
    LsaString->Buffer = String;
    LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
    LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
}


NTSTATUS OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
{
    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
    LSA_UNICODE_STRING ServerString;
    PLSA_UNICODE_STRING Server;

    ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));// Always initialize the object attributes to all zeroes.
    if (ServerName != NULL) {// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
        InitLsaString(&ServerString, ServerName);
        Server = &ServerString;
    } else {
        Server = NULL;
    }

    return LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess, PolicyHandle);// Attempt to open the policy.
}


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

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

    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[])
{
    LSA_HANDLE PolicyHandle;
    WCHAR wComputerName[256]=L"";   // static machine name buffer
    TCHAR AccountName[256];         // static account name buffer
    PSID pSid;
    NTSTATUS Status;
    int iRetVal=RTN_ERROR;          // assume error from main

    if(argc == 1) {
        fprintf(stderr,"Usage: %s <Account> [TargetMachine]\n", argv[0]);
        return RTN_USAGE;
    }

    // Pick up account name on argv[1].
    // Assumes source is ANSI. Resultant string is ANSI or Unicode
    _snwprintf_s(AccountName, 256, 255, TEXT("%hS"), argv[1]);//可以是用户也可以是用户组,如:administrator或者administrators.

    // Pick up machine name on argv[2], if appropriate
    // assumes source is ANSI. Resultant string is Unicode.
    if(argc == 3) _snwprintf_s(wComputerName, 256, 255, L"%hS", argv[2]);//这个参数可以无。

    // Open the policy on the target machine. 
    Status = OpenPolicy(
        wComputerName,      // target machine
        POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
        &PolicyHandle       // resultant policy handle
        );
    if(Status != STATUS_SUCCESS) {
        DisplayNtStatus("OpenPolicy", Status);
        return RTN_ERROR;
    }

    // Obtain the SID of the user/group.
    // Note that we could target a specific machine, but we don't.
    // Specifying NULL for target machine searches for the SID in the following order: well-known, Built-in and local, primary domain,trusted domains.
    if(GetAccountSid(
        NULL,       // default lookup logic
        AccountName,// account to obtain SID
        &pSid       // buffer to allocate to contain resultant SID
        )) 
    {
        //这几行代码是自己的。
        PLSA_UNICODE_STRING UserRights;
        ULONG CountOfRights;
        Status = LsaEnumerateAccountRights(PolicyHandle, pSid, &UserRights, &CountOfRights);
        if(Status != STATUS_SUCCESS) {
            DisplayNtStatus("LsaEnumerateAccountRights", Status);
            return RTN_ERROR;
        }

        ULONG i = 0;
        for (PLSA_UNICODE_STRING plun = UserRights; i < CountOfRights; i++ )
        {
            fprintf(stderr,"%ws!\n", plun->Buffer);
            plun ++;
        }

        Status = LsaFreeMemory(&UserRights);
        if(Status != STATUS_SUCCESS) {
            DisplayNtStatus("LsaFreeMemory", Status);
            return RTN_ERROR;
        }

        iRetVal=RTN_OK;
    }
    else {
        DisplayWinError("GetAccountSid", GetLastError());// Error obtaining SID.
    }

    LsaClose(PolicyHandle);// Close the policy handle.
    if(pSid != NULL) HeapFree(GetProcessHeap(), 0, pSid);// Free memory allocated for SID.
    return iRetVal;
}

没有评论:

发表评论