Вопрос по createprocess, c#, reparenting, .net, pinvoke – Как вызвать CreateProcess () с помощью STARTUPINFOEX из C # и переопределить дочерний элемент

2

Мне нужно создать новый процесс, но чтобы он был «потомком» другого процесса, а не текущего процесса, например, переопределить новый процесс.

Следующие слова почти привели меня туда .NET: Как вызвать CreateProcessAsUser () с помощью STARTUPINFOEX из C # а также .NET: как вызвать UpdateProcThreadAttribute а такжеhttp: //winprogger.com/launching-a-non-child-process

<code>using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

public class ProcessCreator
{
    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CreateProcess(
        string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo,
        out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UpdateProcThreadAttribute(
        out IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue,
        IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool InitializeProcThreadAttributeList(
        out IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);

    public static bool CreateProcess(int parentProcessId)
    {
        const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
        const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;

        var pInfo = new PROCESS_INFORMATION();
        var sInfoEx = new STARTUPINFOEX();
        sInfoEx.StartupInfo = new STARTUPINFO();

        if (parentProcessId > 0)
        {
            var lpSize = IntPtr.Zero;
            IntPtr dummyPtr;
            var success = InitializeProcThreadAttributeList(out dummyPtr, 1, 0, ref lpSize);
            if (success || lpSize == IntPtr.Zero)
            {
                return false;
            }

            sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
            if (sInfoEx.lpAttributeList == IntPtr.Zero)
            {
                return false;
            }

            success = InitializeProcThreadAttributeList(out sInfoEx.lpAttributeList, 1, 0, ref lpSize);
            if (!success)
            {
                return false;
            }

            var parentHandle = Process.GetProcessById(parentProcessId).Handle;
            success = UpdateProcThreadAttribute(
                out sInfoEx.lpAttributeList,
                0,
                (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                parentHandle,
                (IntPtr)IntPtr.Size,
                IntPtr.Zero,
                IntPtr.Zero);
            if (!success)
            {
                return false;
            }

            sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
        }


        var pSec = new SECURITY_ATTRIBUTES();
        var tSec = new SECURITY_ATTRIBUTES();
        pSec.nLength = Marshal.SizeOf(pSec);
        tSec.nLength = Marshal.SizeOf(tSec);
        var lpApplicationName = Path.Combine(Environment.SystemDirectory, "notepad.exe");
        return CreateProcess(lpApplicationName, null, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFOEX
    {
        public STARTUPINFO StartupInfo;
        public IntPtr lpAttributeList;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }
}
</code>

ProcessCreator.CreateProcess (0) запускает Блокнот как дочерний элемент текущего процесса, который является поведением по умолчанию. Все идет нормально

Если переданное значение не равно 0, код пытается запустить Блокнот как дочерний элемент процесса, чей идентификатор процесса совпадает с входным значением (я предполагаю, что процесс существует на данный момент).

К сожалению, эта часть не работает и выдает следующее исключение:

FatalExecutionEngineError обнаружено: Сообщение: во время выполнения обнаружена фатальная ошибка. Адрес ошибки был 0x69a2c7ad в потоке 0x1de0. Код ошибки 0xc0000005. Эта ошибка может быть ошибкой в CLR или в небезопасных или не поддающихся проверке частях пользовательского кода. Распространенными источниками этой ошибки являются ошибки пользовательского маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек.

Любые указатели очень ценятся.

Mabe / Stackoverflow.com вопросы / 1427196 / ... имеет полезную информацию Peter Ritchie
Но я бы не ожидал, что система разрешит переопределение процесса; это похоже на Огромный проблема безопасности. Peter Ritchie
Спасибо, Питер, я нашел вопрос, который вы связываете, полезным, но только до того момента, на котором я сейчас нахожусь. Эта статья Winprogger.com / запуска-а-не-ребенок-процессажется, что @ означает, что то, чего я хочу достичь, должно быть возможным. Я, вероятно, что-то неправильно перевел на C # из этой статьи, просто не могу понять, что. Kaarel Saal

Ваш Ответ

1   ответ
4

В вашем коде есть две проблемы. Во-первых,lpAttributeList параметрInitializeProcThreadAttributeList а такжеUpdateProcThreadAttribute функции должны быть набраны какIntPtr безout модификатор. Во-вторых,lpValue параметрUpdateProcThreadAttribute функция должна бытьуказател к значению атрибута (в вашем случае,parentHandle), а не само значение. Ниже приведен фиксированный код.

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

public class ProcessCreator
{
    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CreateProcess(
        string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo,
        out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UpdateProcThreadAttribute(
        IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue,
        IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool InitializeProcThreadAttributeList(
        IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hObject);

    public static bool CreateProcess(int parentProcessId)
    {
        const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
        const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;

        var pInfo = new PROCESS_INFORMATION();
        var sInfoEx = new STARTUPINFOEX();
        sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
        IntPtr lpValue = IntPtr.Zero;

        try
        {
            if (parentProcessId > 0)
            {
                var lpSize = IntPtr.Zero;
                var success = InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize);
                if (success || lpSize == IntPtr.Zero)
                {
                    return false;
                }

                sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
                success = InitializeProcThreadAttributeList(sInfoEx.lpAttributeList, 1, 0, ref lpSize);
                if (!success)
                {
                    return false;
                }

                var parentHandle = Process.GetProcessById(parentProcessId).Handle;
                // This value should persist until the attribute list is destroyed using the DeleteProcThreadAttributeList function
                lpValue = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(lpValue, parentHandle);

                success = UpdateProcThreadAttribute(
                    sInfoEx.lpAttributeList,
                    0,
                    (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                    lpValue,
                    (IntPtr)IntPtr.Size,
                    IntPtr.Zero,
                    IntPtr.Zero);
                if (!success)
                {
                    return false;
                }
            }

            var pSec = new SECURITY_ATTRIBUTES();
            var tSec = new SECURITY_ATTRIBUTES();
            pSec.nLength = Marshal.SizeOf(pSec);
            tSec.nLength = Marshal.SizeOf(tSec);
            var lpApplicationName = Path.Combine(Environment.SystemDirectory, "notepad.exe");
            return CreateProcess(lpApplicationName, null, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
        }
        finally
        {
            // Free the attribute list
            if (sInfoEx.lpAttributeList != IntPtr.Zero)
            {
                DeleteProcThreadAttributeList(sInfoEx.lpAttributeList);
                Marshal.FreeHGlobal(sInfoEx.lpAttributeList);
            }
            Marshal.FreeHGlobal(lpValue);

            // Close process and thread handles
            if (pInfo.hProcess != IntPtr.Zero)
            {
                CloseHandle(pInfo.hProcess);
            }
            if (pInfo.hThread != IntPtr.Zero)
            {
                CloseHandle(pInfo.hThread);
            }
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFOEX
    {
        public STARTUPINFO StartupInfo;
        public IntPtr lpAttributeList;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }
}

Похожие вопросы