첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
0.01MB

▶ HANDLE_FLAG.cs

using System;

namespace TestProject
{
    /// <summary>
    /// 핸들 플래그
    /// </summary>
    [Flags]
    public enum HANDLE_FLAG : uint
    {
        /// <summary>
        /// NONE
        /// </summary>
        NONE = 0,

        /// <summary>
        /// INHERIT
        /// </summary>
        INHERIT = 1,

        /// <summary>
        /// PROTECT_FROM_CLOSE
        /// </summary>
        PROTECT_FROM_CLOSE = 2
    }
}

 

728x90

 

▶ PROCESS_INFORMATION.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 프로세스 정보
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 프로세스 핸들
        /// </summary>
        public IntPtr ProcessHandle;

        /// <summary>
        /// 스레드 핸들
        /// </summary>
        public IntPtr ThreadHandle;

        /// <summary>
        /// 프로세스 ID
        /// </summary>
        public int ProcessID;

        /// <summary>
        /// 스레드 ID
        /// </summary>
        public int ThreadID;

        #endregion
    }
}

 

300x250

 

▶ ProcessAccessFlag.cs

using System;

namespace TestProject
{
    /// <summary>
    /// 프로세스 액세스 플래그
    /// </summary>
    [Flags]
    public enum ProcessAccessFlag : uint
    {
        /// <summary>
        /// All
        /// </summary>
        All = 0x001f0fff,

        /// <summary>
        /// Terminate
        /// </summary>
        Terminate = 0x00000001,

        /// <summary>
        /// CreateThread
        /// </summary>
        CreateThread = 0x00000002,

        /// <summary>
        /// VirtualMemoryOperation
        /// </summary>
        VirtualMemoryOperation = 0x00000008,

        /// <summary>
        /// VirtualMemoryRead
        /// </summary>
        VirtualMemoryRead = 0x00000010,

        /// <summary>
        /// VirtualMemoryWrite
        /// </summary>
        VirtualMemoryWrite = 0x00000020,

        /// <summary>
        /// DuplicateHandle
        /// </summary>
        DuplicateHandle = 0x00000040,

        /// <summary>
        /// CreateProcess
        /// </summary>
        CreateProcess = 0x000000080,

        /// <summary>
        /// SetQuota
        /// </summary>
        SetQuota = 0x00000100,

        /// <summary>
        /// SetInformation
        /// </summary>
        SetInformation = 0x00000200,

        /// <summary>
        /// QueryInformation
        /// </summary>
        QueryInformation = 0x00000400,

        /// <summary>
        /// QueryLimitedInformation
        /// </summary>
        QueryLimitedInformation = 0x00001000,

        /// <summary>
        /// Synchronize
        /// </summary>
        Synchronize = 0x00100000
    }
}

 

▶ SECURITY_ATTRIBUTES.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 보안 어트리뷰트
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

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

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

        /// <summary>
        /// 핸들 상속 여부
        /// </summary>
        [MarshalAs(UnmanagedType.Bool)]
        public bool InheritHandle;

        #endregion
    }
}

 

▶ STARTUPINFO.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 시작시 정보
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct STARTUPINFO
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 바이트 카운트
        /// </summary>
        public int ByteCount;

        /// <summary>
        /// 예약
        /// </summary>
        public string Reserved;

        /// <summary>
        /// 데스크톱
        /// </summary>
        public string Desktop;

        /// <summary>
        /// 제목
        /// </summary>
        public string Title;

        /// <summary>
        /// X
        /// </summary>
        public int X;

        /// <summary>
        /// Y
        /// </summary>
        public int Y;

        /// <summary>
        /// X 크기
        /// </summary>
        public int XSize;

        /// <summary>
        /// Y 크기
        /// </summary>
        public int YSize;

        /// <summary>
        /// X 문자 카운트
        /// </summary>
        public int XCountCharacters;

        /// <summary>
        /// Y 문자 카운트
        /// </summary>
        public int YCountCharacters;

        /// <summary>
        /// 칠하기 어트리뷰트
        /// </summary>
        public int FillAttribute;

        /// <summary>
        /// 플래그
        /// </summary>
        public int Flag;

        /// <summary>
        /// 윈도우 표시
        /// </summary>
        public short ShowWindow;

        /// <summary>
        /// 예약 2 바이트 카운트
        /// </summary>
        public short Reserved2ByteCount;

        /// <summary>
        /// 예약 2 핸들
        /// </summary>
        public IntPtr Reserved2Handle;

        /// <summary>
        /// 표준 입력 핸들
        /// </summary>
        public IntPtr StandardInputHandle;

        /// <summary>
        /// 표준 출력 핸들
        /// </summary>
        public IntPtr StandardOutputHandle;

        /// <summary>
        /// 표준 에러 핸들
        /// </summary>
        public IntPtr StandardErrorHandle;

        #endregion
    }
}

 

▶ STARTUPINFOEX.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 시작시 정보 (확장)
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct STARTUPINFOEX
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 시작시 정보
        /// </summary>
        public STARTUPINFO StartupInfo;

        /// <summary>
        /// 어트리뷰트 리스트 핸들
        /// </summary>
        public IntPtr AttributeListHandle;

        #endregion
    }
}

 

▶ ProcessHelper.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 프로세스 헬퍼
    /// </summary>
    public static class ProcessHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 프로세스 생성하기 - CreateProcess(applicationName, commandLine, processAttributes, threadAttributes, inheritHandles, creationFlag, environmentHandle, currentDirectoryPath, startupInfo, processInformation)

        /// <summary>
        /// 프로세스 생성하기
        /// </summary>
        /// <param name="applicationName">애플리케이션명</param>
        /// <param name="commandLine">명령줄</param>
        /// <param name="processAttributes">프로세스 어트리뷰트</param>
        /// <param name="threadAttributes">스레드 어트리뷰트</param>
        /// <param name="inheritHandles">핸들 상속 여부</param>
        /// <param name="creationFlag">생성 플래그</param>
        /// <param name="environmentHandle">환경 핸들</param>
        /// <param name="currentDirectoryPath">현재 디렉토리 경로</param>
        /// <param name="startupInfo">시작시 정보</param>
        /// <param name="processInformation">프로세스 정보</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CreateProcess
        (
            string                  applicationName,
            string                  commandLine,
            ref SECURITY_ATTRIBUTES processAttributes,
            ref SECURITY_ATTRIBUTES threadAttributes,
            bool                    inheritHandles,
            uint                    creationFlag,
            IntPtr                  environmentHandle,
            string                  currentDirectoryPath,
            [In] ref STARTUPINFOEX  startupInfo,
            out PROCESS_INFORMATION processInformation
        );

        #endregion
        #region 프로세스 열기 - OpenProcess(processAccessFlag, inheritHandle, processID)

        /// <summary>
        /// 프로세스 열기
        /// </summary>
        /// <param name="processAccessFlag">프로세스 액세스 플래그</param>
        /// <param name="inheritHandle">핸들 상속 여부</param>
        /// <param name="processID">프로세스 ID</param>
        /// <returns>프로세스 핸들</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern IntPtr OpenProcess(ProcessAccessFlag processAccessFlag, bool inheritHandle, int processID);

        #endregion
        #region 단일 객체 대기하기 - WaitForSingleObject(handle, milliseconds)

        /// <summary>
        /// 단일 객체 대기하기
        /// </summary>
        /// <param name="handle">핸들</param>
        /// <param name="milliseconds">밀리초</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);

        #endregion
        #region 프로세스 스레드 어트리뷰트 업데이트하기 - UpdateProcThreadAttribute(attributeListHandle, flag, attributeHandle, valueHandle, byteCountHandle, previousValueHandle, returnSizeHandle)

        /// <summary>
        /// 프로세스 스레드 어트리뷰트 업데이트하기
        /// </summary>
        /// <param name="attributeListHandle">어트리뷰트 리스트 핸들</param>
        /// <param name="flag">플래그</param>
        /// <param name="attributeHandle">어트리뷰트 핸들</param>
        /// <param name="valueHandle">값 핸들</param>
        /// <param name="byteCountHandle">바이트 카운트 핸들</param>
        /// <param name="previousValueHandle">이전 값 핸들</param>
        /// <param name="returnSizeHandle">반환 크기 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UpdateProcThreadAttribute
        (
            IntPtr attributeListHandle,
            uint   flag,
            IntPtr attributeHandle,
            IntPtr valueHandle,
            IntPtr byteCountHandle,
            IntPtr previousValueHandle,
            IntPtr returnSizeHandle
        );

        #endregion
        #region 프로세스 스레드 어트리뷰트 리스트 초기화하기 - InitializeProcThreadAttributeList(attributeListHandle, attributeCount, flag, sizeHandle)

        /// <summary>
        /// 프로세스 스레드 어트리뷰트 리스트 초기화하기
        /// </summary>
        /// <param name="attributeListHandle">어트리뷰트 리스트 핸들</param>
        /// <param name="attributeCount">어트리뷰트 카운트</param>
        /// <param name="flag">플래그</param>
        /// <param name="sizeHandle">크기 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool InitializeProcThreadAttributeList(IntPtr attributeListHandle, int attributeCount, int flag, ref IntPtr sizeHandle);

        #endregion
        #region 핸들 정보 설정하기 - SetHandleInformation(objectHandle, mask, flag)

        /// <summary>
        /// 핸들 정보 설정하기
        /// </summary>
        /// <param name="objectHandle">객체 핸들</param>
        /// <param name="mask">마스크</param>
        /// <param name="flag">플래그</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern bool SetHandleInformation(IntPtr objectHandle, HANDLE_FLAG mask, HANDLE_FLAG flag);

        #endregion
        #region 핸들 닫기 - CloseHandle(objectHandle)

        /// <summary>
        /// 핸들 닫기
        /// </summary>
        /// <param name="objectHandle">객체 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern bool CloseHandle(IntPtr objectHandle);

        #endregion
        #region 핸들 복제하기 - DuplicateHandle(sourceProcessHandle, sourceHandle, targetProcessHandle, targetHandle, desiredAccess, inheritHandle, option)

        /// <summary>
        /// 핸들 복제하기
        /// </summary>
        /// <param name="sourceProcessHandle">소스 프로세스 핸들</param>
        /// <param name="sourceHandle">소스 핸들</param>
        /// <param name="targetProcessHandle">타겟 프로세스 핸들</param>
        /// <param name="targetHandle">타겟 핸들</param>
        /// <param name="desiredAccess">희망 액세스</param>
        /// <param name="inheritHandle">핸들 상속 여부</param>
        /// <param name="option">옵션</param>
        /// <returns>처리 결과</returns>
        [DllImport("kernel32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool DuplicateHandle
        (
            IntPtr                               sourceProcessHandle,
            IntPtr                               sourceHandle,
            IntPtr                               targetProcessHandle,
            ref IntPtr                           targetHandle,
            uint                                 desiredAccess,
            [MarshalAs(UnmanagedType.Bool)] bool inheritHandle,
            uint                                 option
        );

        #endregion

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

        #region Field

        /// <summary>
        /// PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
        /// </summary>
        private const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;

        /// <summary>
        /// EXTENDED_STARTUPINFO_PRESENT
        /// </summary>
        private const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;

        /// <summary>
        /// CREATE_NEW_CONSOLE
        /// </summary>
        private const uint CREATE_NEW_CONSOLE = 0x00000010;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public


        #region 프로세스 실행하기 - ExecuteProcess(parentProcessID, filePath)

        /// <summary>
        /// 프로세스 실행하기
        /// </summary>
        /// <param name="parentProcessID">부모 프로세스 ID</param>
        /// <param name="filePath">파일 경로</param>
        public static void ExecuteProcess(int parentProcessID, string filePath)
        {
            PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();

            STARTUPINFOEX startupInfoEx = new STARTUPINFOEX();

            IntPtr valueHandle         = IntPtr.Zero;
            IntPtr sourceProcessHandle = IntPtr.Zero;
            IntPtr sizeHandle          = IntPtr.Zero;

            InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref sizeHandle);

            startupInfoEx.AttributeListHandle = Marshal.AllocHGlobal(sizeHandle);

            InitializeProcThreadAttributeList(startupInfoEx.AttributeListHandle, 1, 0, ref sizeHandle);

            IntPtr parentHandle = OpenProcess(ProcessAccessFlag.CreateProcess | ProcessAccessFlag.DuplicateHandle, false, parentProcessID);

            valueHandle = Marshal.AllocHGlobal(IntPtr.Size);

            Marshal.WriteIntPtr(valueHandle, parentHandle);

            UpdateProcThreadAttribute
            (
                startupInfoEx.AttributeListHandle,
                0,
                (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                valueHandle,
                (IntPtr)IntPtr.Size,
                IntPtr.Zero,
                IntPtr.Zero
            );

            SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES();
            SECURITY_ATTRIBUTES threadAttributes  = new SECURITY_ATTRIBUTES();

            processAttributes.Length = Marshal.SizeOf(processAttributes);
            threadAttributes.Length  = Marshal.SizeOf(threadAttributes );

            CreateProcess
            (
                filePath,
                null,
                ref processAttributes,
                ref threadAttributes,
                true,
                EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
                IntPtr.Zero,
                null,
                ref startupInfoEx,
                out processInformation
            );
        }

        #endregion
    }
}

 

▶ Program.cs

using System.Diagnostics;

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

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

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        /// <param name="argumentList">인자 리스트</param>
        private static void Main(string[] argumentList)
        {
            string filePath           = argumentList[0];
            string processNameToSpoof = argumentList[1];

            int parentProcessID;

            Process[] processArray = Process.GetProcessesByName(processNameToSpoof);

            parentProcessID = processArray[0].Id;

            ProcessHelper.ExecuteProcess(parentProcessID, filePath);
        }

        #endregion
    }
}

 

▶ 사용법

D:\TestProject\TestProject\bin\Release\TestProject.exe C:\Windows\System32\cmd.exe lsass

※ 관리자 모드에서 실행해야 한다.

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

댓글을 달아 주세요