첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ Program.cs

using System;
using System.Collections.Generic;

namespace TestProject
{
    /// <summary>
    /// 프로그램
    /// </summary>
    class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 프로그램 시작하기 - Main()

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        private static void Main()
        {
            Console.Title = "사용자 계정 로그온 권한 조사하기";

            string accountName = "hostname\\username"; // 적절한 계정명을 설정한다.

            IList<string> rightList = LocalSecurityAuthorityHelper.GetRightList(accountName);

            if(rightList.Contains(LocalSecurityAuthorityRight.LogonAsService))
            {
                Console.WriteLine($"{accountName} 계정은 서비스 로그온 권한을 갖고 있습니다.");
            }
            else
            {
                Console.WriteLine($"{accountName} 계정은 서비스 로그온 권한을 갖고 있지 않습니다.");
            }
        }

        #endregion
    }
}

 

728x90

 

▶ LocalSecurityAuthorityController.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace TestProject
{
    /// <summary>
    /// 로컬 보안 권한 컨트롤러
    /// </summary>
    public class LocalSecurityAuthorityController
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region LSA 접근 정책 - LSA_AccessPolicy

        /// <summary>
        /// LSA 접근 정책
        /// </summary>
        [Flags]
        private enum LSA_AccessPolicy : long
        {
            /// <summary>
            /// POLICY_VIEW_LOCAL_INFORMATION
            /// </summary>
            POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,

            /// <summary>
            /// POLICY_VIEW_AUDIT_INFORMATION
            /// </summary>
            POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,

            /// <summary>
            /// POLICY_GET_PRIVATE_INFORMATION
            /// </summary>
            POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,

            /// <summary>
            /// POLICY_TRUST_ADMIN
            /// </summary>
            POLICY_TRUST_ADMIN = 0x00000008L,

            /// <summary>
            /// POLICY_CREATE_ACCOUNT
            /// </summary>
            POLICY_CREATE_ACCOUNT = 0x00000010L,

            /// <summary>
            /// POLICY_CREATE_SECRET
            /// </summary>
            POLICY_CREATE_SECRET = 0x00000020L,

            /// <summary>
            /// POLICY_CREATE_PRIVILEGE
            /// </summary>
            POLICY_CREATE_PRIVILEGE = 0x00000040L,

            /// <summary>
            /// POLICY_SET_DEFAULT_QUOTA_LIMITS
            /// </summary>
            POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,

            /// <summary>
            /// POLICY_SET_AUDIT_REQUIREMENTS
            /// </summary>
            POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,

            /// <summary>
            /// POLICY_AUDIT_LOG_ADMIN
            /// </summary>
            POLICY_AUDIT_LOG_ADMIN = 0x00000200L,

            /// <summary>
            /// POLICY_SERVER_ADMIN
            /// </summary>
            POLICY_SERVER_ADMIN = 0x00000400L,

            /// <summary>
            /// POLICY_LOOKUP_NAMES
            /// </summary>
            POLICY_LOOKUP_NAMES = 0x00000800L,

            /// <summary>
            /// POLICY_NOTIFICATION
            /// </summary>
            POLICY_NOTIFICATION = 0x00001000L
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Structure
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region LSA 유니코드 문자열 - LSA_UNICODE_STRING

        /// <summary>
        /// LSA 유니코드 문자열
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct LSA_UNICODE_STRING
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region Field

            /// <summary>
            /// 길이
            /// </summary>
            public ushort Length;

            /// <summary>
            /// 최대 길이
            /// </summary>
            public ushort MaximumLength;

            /// <summary>
            /// 버퍼 핸들
            /// </summary>
            public IntPtr Buffer;

            #endregion
        }

        #endregion
        #region LSA 객체 어트리뷰트 - LSA_OBJECT_ATTRIBUTES

        /// <summary>
        /// LSA 객체 어트리뷰트
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct LSA_OBJECT_ATTRIBUTES
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Field

            #region Field

            /// <summary>
            /// 길이
            /// </summary>
            public int Length;

            /// <summary>
            /// 루트 디렉토리
            /// </summary>
            public IntPtr RootDirectory;

            /// <summary>
            /// 객체명
            /// </summary>
            public LSA_UNICODE_STRING ObjectName;

            /// <summary>
            /// 어트리뷰트
            /// </summary>
            public uint Attributes;

            /// <summary>
            /// 보안 설명자
            /// </summary>
            public IntPtr SecurityDescriptor;

            /// <summary>
            /// 서비스 보안 품질
            /// </summary>
            public IntPtr SecurityQualityOfService;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region LSA 정책 열기 - LsaOpenPolicy(systemName, objectAttributes, desiredAccess, policyHandle)

        /// <summary>
        /// LSA 정책 열기
        /// </summary>
        /// <param name="systemName">시스템명</param>
        /// <param name="objectAttributes">객체 어트리뷰트</param>
        /// <param name="desiredAccess">희망 액세스</param>
        /// <param name="policyHandle">정책 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("advapi32.dll", PreserveSig = true)]
        private static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING systemName, ref LSA_OBJECT_ATTRIBUTES objectAttributes,
            Int32 desiredAccess, out IntPtr policyHandle);

        #endregion
        #region LSA 계정 권리 추가하기 - LsaAddAccountRights(policyHandle, accountSID, userRightArray, rightCount)

        /// <summary>
        /// LSA 계정 권리 추가하기
        /// </summary>
        /// <param name="policyHandle">정책 핸들</param>
        /// <param name="accountSID">계정 SID</param>
        /// <param name="userRightArray">사용자 권리 배열</param>
        /// <param name="rightCount">권리 수</param>
        /// <returns>처리 결과</returns>
        [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
        private static extern uint LsaAddAccountRights(IntPtr policyHandle, IntPtr accountSID, LSA_UNICODE_STRING[] userRightArray, int rightCount);

        #endregion
        #region SID 해제하기 - FreeSid(sidHandle)

        /// <summary>
        /// SID 해제하기
        /// </summary>
        /// <param name="sidHandle">SID 핸들</param>
        [DllImport("advapi32")]
        private static extern void FreeSid(IntPtr sidHandle);

        #endregion
        #region 계정명 찾기 - LookupAccountName(systemName, accountName, sidHandle, sidSize, domainName, domainLength, use)

        /// <summary>
        /// 계정명 찾기
        /// </summary>
        /// <param name="systemName">시스템명</param>
        /// <param name="accountName">계정명</param>
        /// <param name="sidHandle">SID 핸들</param>
        /// <param name="sidSize">SID 크기</param>
        /// <param name="domainName">도메인명</param>
        /// <param name="domainLength">도메인 길이</param>
        /// <param name="use">사용</param>
        /// <returns>처리 결과</returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
        private static extern bool LookupAccountName(string systemName, string accountName, IntPtr sidHandle, ref int sidSize,
            StringBuilder domainName, ref int domainLength, ref int use);

        #endregion
        #region SID 무결성 여부 구하기 - IsValidSid(sidHandle)

        /// <summary>
        /// SID 무결성 여부 구하기
        /// </summary>
        /// <param name="sidHandle">SID 핸들</param>
        /// <returns>SID 무결성 여부</returns>
        [DllImport("advapi32.dll")]
        private static extern bool IsValidSid(IntPtr sidHandle);

        #endregion
        #region LSA 닫기 - LsaClose(objectHandle)

        /// <summary>
        /// LSA 닫기
        /// </summary>
        /// <param name="objectHandle">객체 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("advapi32.dll")]
        private static extern int LsaClose(IntPtr objectHandle);

        #endregion
        #region 마지막 에러 구하기 - GetLastError()

        /// <summary>
        /// 마지막 에러 구하기
        /// </summary>
        /// <returns>에러 코드</returns>
        [DllImport("kernel32.dll")]
        private static extern int GetLastError();

        #endregion
        #region LSA NT 상태에서 윈도우즈 에러 코드 구하기 - LsaNtStatusToWinError(status)

        /// <summary>
        /// LSA NT 상태에서 윈도우즈 에러 코드 구하기
        /// </summary>
        /// <param name="status">상태</param>
        /// <returns>윈도우즈 에러 코드</returns>
        [DllImport("advapi32.dll")]
        private static extern int LsaNtStatusToWinError(uint status);

        #endregion
        #region LSA 계정 권리 열거하기 - LsaEnumerateAccountRights(policyHandle, accountSID, userRightHandle, rightCount)

        /// <summary>
        /// LSA 계정 권리 열거하기
        /// </summary>
        /// <param name="policyHandle">정책 핸들</param>
        /// <param name="accountSID">계정 SID</param>
        /// <param name="userRightHandle">사용자 권리 핸들</param>
        /// <param name="rightCount">권리 수</param>
        /// <returns>처리 결과</returns>
        [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
        private static extern uint LsaEnumerateAccountRights(IntPtr policyHandle, IntPtr accountSID, out IntPtr userRightHandle, out int rightCount);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 액세스
        /// </summary>
        private const int Access = (int)
        (
            LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN          |
            LSA_AccessPolicy.POLICY_CREATE_ACCOUNT           |
            LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE         |
            LSA_AccessPolicy.POLICY_CREATE_SECRET            |
            LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION  |
            LSA_AccessPolicy.POLICY_LOOKUP_NAMES             |
            LSA_AccessPolicy.POLICY_NOTIFICATION             |
            LSA_AccessPolicy.POLICY_SERVER_ADMIN             |
            LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS   |
            LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
            LSA_AccessPolicy.POLICY_TRUST_ADMIN              |
            LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION   |
            LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 권리 리스트 구하기 - GetRightList(accountName)

        /// <summary>
        /// 권리 리스트 구하기
        /// </summary>
        /// <param name="accountName">계정명</param>
        /// <returns>권리 리스트</returns>
        public IList<string> GetRightList(string accountName)
        {
            IList<string> rightList = new List<string>();

            long   errorCode    = 0;
            string errorMessage = string.Empty;

            IntPtr sidHandle     = IntPtr.Zero;
            int    sidHandleSize = 0;

            StringBuilder domainNameStringBuilder = new StringBuilder();

            int domainNameSize = 0;
            int accountType    = 0;

            LookupAccountName(string.Empty, accountName, sidHandle, ref sidHandleSize, domainNameStringBuilder, ref domainNameSize, ref accountType);

            domainNameStringBuilder = new StringBuilder(domainNameSize);

            sidHandle = Marshal.AllocHGlobal(sidHandleSize);

            if(!LookupAccountName(string.Empty, accountName, sidHandle, ref sidHandleSize, domainNameStringBuilder, ref domainNameSize, ref accountType))
            {
                errorCode = GetLastError();

                errorMessage = ("LookupAccountName failed : " + errorCode);

                throw new Win32Exception((int)errorCode, errorMessage);
            }
            else
            {
                LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();

                IntPtr policyHandle    = IntPtr.Zero;
                IntPtr userRightHandle = IntPtr.Zero;

                int rightCount = 0;

                LSA_OBJECT_ATTRIBUTES objectAttributes = CreateLSAObject();

                uint policyStatus = LsaOpenPolicy(ref systemName, ref objectAttributes, Access, out policyHandle);

                errorCode = LsaNtStatusToWinError(policyStatus);

                if(errorCode != 0)
                {
                    errorMessage = string.Format("OpenPolicy failed : {0}.", errorCode);

                    throw new Win32Exception((int)errorCode, errorMessage);
                }
                else
                {
                    try
                    {
                        uint result = LsaEnumerateAccountRights(policyHandle, sidHandle, out userRightHandle, out rightCount);

                        errorCode = LsaNtStatusToWinError(result);

                        if(errorCode != 0)
                        {
                            if(errorCode == 2)
                            {
                                return new List<string>();
                            }

                            errorMessage = string.Format("LsaEnumerateAccountRights failed : {0}", errorCode);

                            throw new Win32Exception((int)errorCode, errorMessage);
                        }

                        long userRightHandleValue = userRightHandle.ToInt64();

                        LSA_UNICODE_STRING userRight;

                        for(int i = 0; i < rightCount; i++)
                        {
                            userRight = (LSA_UNICODE_STRING)Marshal.PtrToStructure(new IntPtr(userRightHandleValue), typeof(LSA_UNICODE_STRING));

                            string userRightString = Marshal.PtrToStringAuto(userRight.Buffer);

                            rightList.Add(userRightString);

                            userRightHandleValue += Marshal.SizeOf(userRight);
                        }
                    }
                    finally
                    {
                        LsaClose(policyHandle);
                    }
                }

                FreeSid(sidHandle);
            }

            return rightList;
        }

        #endregion
        #region 권리 설정하기 - SetRight(accountName, privilegeName)

        /// <summary>
        /// 권리 설정하기
        /// </summary>
        /// <param name="accountName">계정명</param>
        /// <param name="privilegeName">특권명</param>
        public void SetRight(string accountName, string privilegeName)
        {
            long   errorCode    = 0;
            string errorMessage = string.Empty;

            IntPtr sidHandle     = IntPtr.Zero;
            int    sidHandleSize = 0;

            StringBuilder domainNameStringBuilder = new StringBuilder();

            int domainNameSize = 0;
            int accountType    = 0;

            LookupAccountName(String.Empty, accountName, sidHandle, ref sidHandleSize, domainNameStringBuilder, ref domainNameSize, ref accountType);

            domainNameStringBuilder = new StringBuilder(domainNameSize);

            sidHandle = Marshal.AllocHGlobal(sidHandleSize);

            if(!LookupAccountName(string.Empty, accountName, sidHandle, ref sidHandleSize, domainNameStringBuilder, ref domainNameSize, ref accountType))
            {
                errorCode = GetLastError();

                errorMessage = string.Format("LookupAccountName failed : {0}", errorCode);

                throw new Win32Exception((int)errorCode, errorMessage);
            }
            else
            {
                LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();

                IntPtr policyHandle = IntPtr.Zero;

                LSA_OBJECT_ATTRIBUTES objectAttributes = CreateLSAObject();

                uint resultPolicy = LsaOpenPolicy(ref systemName, ref objectAttributes, Access, out policyHandle);

                errorCode = LsaNtStatusToWinError(resultPolicy);

                if(errorCode != 0)
                {
                    errorMessage = string.Format("OpenPolicy failed : {0} ", errorCode);

                    throw new Win32Exception((int)errorCode, errorMessage);
                }
                else
                {
                    try
                    {
                        LSA_UNICODE_STRING[] userRightArray = new LSA_UNICODE_STRING[1];

                        userRightArray[0] = new LSA_UNICODE_STRING();

                        userRightArray[0].Buffer        = Marshal.StringToHGlobalUni(privilegeName);
                        userRightArray[0].Length        = (ushort)(privilegeName.Length * UnicodeEncoding.CharSize);
                        userRightArray[0].MaximumLength = (ushort)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);

                        uint result = LsaAddAccountRights(policyHandle, sidHandle, userRightArray, 1);

                        errorCode = LsaNtStatusToWinError(result);

                        if(errorCode != 0)
                        {
                            errorMessage = string.Format("LsaAddAccountRights failed : {0}", errorCode);

                            throw new Win32Exception((int)errorCode, errorMessage);
                        }
                    }
                    finally
                    {
                        LsaClose(policyHandle);
                    }
                }

                FreeSid(sidHandle);
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region LSA 객체 생성하기 - CreateLSAObject()

        /// <summary>
        /// LSA 객체 생성하기
        /// </summary>
        /// <returns>LSA 객체 어트리뷰트</returns>
        private static LSA_OBJECT_ATTRIBUTES CreateLSAObject()
        {
            LSA_OBJECT_ATTRIBUTES newInstance = new LSA_OBJECT_ATTRIBUTES();

            newInstance.Length                   = 0;
            newInstance.RootDirectory            = IntPtr.Zero;
            newInstance.Attributes               = 0;
            newInstance.SecurityDescriptor       = IntPtr.Zero;
            newInstance.SecurityQualityOfService = IntPtr.Zero;

            return newInstance;
        }

        #endregion
    }
}

 

300x250

 

▶ LocalSecurityAuthorityRight.cs

namespace TestProject
{
    /// <summary>
    /// 로컬 보안 권한 권리
    /// </summary>
    public class LocalSecurityAuthorityRight
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 서비스 로그온
        /// </summary>
        public const string LogonAsService = "SeServiceLogonRight";

        /// <summary>
        /// 배치 작업 로그온
        /// </summary>
        public const string LogonAsBatchJob = "SeBatchLogonRight";

        /// <summary>
        /// 대화형 로그온
        /// </summary>
        public const string InteractiveLogon = "SeInteractiveLogonRight";

        /// <summary>
        /// 네트워크 로그온
        /// </summary>
        public const string NetworkLogon = "SeNetworkLogonRight";

        /// <summary>
        /// 보안 감사 생성
        /// </summary>
        public const string GenerateSecurityAudits = "SeAuditPrivilege";

        #endregion
    }
}

 

▶ LocalSecurityAuthorityHelper.cs

using System.Collections.Generic;

namespace TestProject
{
    /// <summary>
    /// 로컬 보안 권한 헬퍼
    /// </summary>
    public static class LocalSecurityAuthorityHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 권리 리스트 구하기 - GetRightList(accountName)

        /// <summary>
        /// 권리 리스트 구하기
        /// </summary>
        /// <param name="accountName">계정명</param>
        /// <returns>권리 리스트</returns>
        public static IList<string> GetRightList(string accountName)
        {
            return new LocalSecurityAuthorityController().GetRightList(accountName);
        }

        #endregion
        #region 권리 설정하기 - SetRight(accountName, privilegeName)

        /// <summary>
        /// 권리 설정하기
        /// </summary>
        /// <param name="accountName">계정명</param>
        /// <param name="privilegeName">특권명</param>
        public static void SetRight(string accountName, string privilegeName)
        {
            new LocalSecurityAuthorityController().SetRight(accountName, privilegeName);
        }

        #endregion
    }
}

※ 관리자 권한으로 실행한다.

728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요