Загрузите файл EXE и запустите его из памяти - PullRequest
21 голосов
/ 24 августа 2010

Я пытаюсь запустить исполняемый файл из памяти, как описано в этой статье.Я могу легко запустить любой .net / управляемый exe.Но я не могу запустить исполняемые файлы, такие как notepad.exe или calc.exe.Как получить его, чтобы я мог запускать неуправляемые exe-файлы?

Ответы [ 4 ]

25 голосов
/ 24 августа 2010

В случае запуска исполняемых файлов .NET из памяти библиотеки и сам CLR делают для вас очень тяжелую работу. Для нативных исполняемых файлов, таких как notepad.exe и calc.exe, вам придется проделать большую ручную работу, чтобы это произошло. По сути, вы должны действовать как загрузчик Windows.

Возможно, здесь есть страницы предостережений, но эта углубленная статья содержит шаги, необходимые для загрузки PE wiki , msdn в память и сделайте правильные перебазировки и исправления. Затем вы сможете найти точку входа (как в статье) и запустить ее.

Если вы действительно хотите запустить notepad.exe и calc.exe, конечно, самый простой способ - использовать Process.Start и запускать их с диска. В противном случае, если в ваш процесс встроен исполняемый файл как ресурс, то следующим простым способом будет просто записать содержимое на диск во временном месте (см. Path.GetTempFileName) и затем выполнить его. оттуда.

18 голосов
/ 10 февраля 2012

Я не уверен, но следующий код из этой темы может быть полезен:

using System;
using System.Runtime.InteropServices;

/* 
 * Title: CMemoryExecute.cs
 * Description: Runs an EXE in memory using native WinAPI. Very optimized and tiny.
 * 
 * Developed by: affixiate 
 * Release date: December 10, 2010
 * Released on: http://opensc.ws
 * Credits:
 *          MSDN (http://msdn.microsoft.com)
 *          NtInternals (http://undocumented.ntinternals.net)
 *          Pinvoke (http://pinvoke.net)
 *          
 * Comments: If you use this code, I require you to give me credits. Don't be a ripper! ;]
 */

// ReSharper disable InconsistentNaming
public static unsafe class CMemoryExecute
{
    public struct STARTUPINFO
    {
        public uint cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    /// <summary>
    /// Runs an EXE (which is loaded in a byte array) in memory.
    /// </summary>
    /// <param name="exeBuffer">The EXE buffer.</param>
    /// <param name="hostProcess">Full path of the host process to run the buffer in.</param>
    /// <param name="optionalArguments">Optional command line arguments.</param>
    /// <returns></returns>
    public static bool Run(byte[] exeBuffer, string hostProcess, string optionalArguments = "")
    {
        // STARTUPINFO
        STARTUPINFO StartupInfo = new STARTUPINFO();
        StartupInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
        StartupInfo.wShowWindow = SW_HIDE;

        var IMAGE_SECTION_HEADER = new byte[0x28]; // pish
        var IMAGE_NT_HEADERS = new byte[0xf8]; // pinh
        var IMAGE_DOS_HEADER = new byte[0x40]; // pidh
        var PROCESS_INFO = new int[0x4]; // pi
        var CONTEXT = new byte[0x2cc]; // ctx

        byte* pish;
        fixed (byte* p = &IMAGE_SECTION_HEADER[0])
            pish = p;

        byte* pinh;
        fixed (byte* p = &IMAGE_NT_HEADERS[0])
            pinh = p;

        byte* pidh;
        fixed (byte* p = &IMAGE_DOS_HEADER[0])
            pidh = p;

        byte* ctx;
        fixed (byte* p = &CONTEXT[0])
            ctx = p;

        // Set the flag.
        *(uint*)(ctx + 0x0 /* ContextFlags */) = CONTEXT_FULL;

        // Get the DOS header of the EXE.
        Buffer.BlockCopy(exeBuffer, 0, IMAGE_DOS_HEADER, 0, IMAGE_DOS_HEADER.Length);

        /* Sanity check:  See if we have MZ header. */
        if (*(ushort*)(pidh + 0x0 /* e_magic */) != IMAGE_DOS_SIGNATURE)
            return false;

        var e_lfanew = *(int*)(pidh + 0x3c);

        // Get the NT header of the EXE.
        Buffer.BlockCopy(exeBuffer, e_lfanew, IMAGE_NT_HEADERS, 0, IMAGE_NT_HEADERS.Length);

        /* Sanity check: See if we have PE00 header. */
        if (*(uint*)(pinh + 0x0 /* Signature */) != IMAGE_NT_SIGNATURE)
            return false;

        // Run with parameters if necessary.
        if (!string.IsNullOrEmpty(optionalArguments))
            hostProcess += " " + optionalArguments;

        if (!CreateProcess(null, hostProcess, IntPtr.Zero, IntPtr.Zero, false, CREATE_SUSPENDED, IntPtr.Zero, null, ref StartupInfo, PROCESS_INFO))
            return false;

        var ImageBase = new IntPtr(*(int*)(pinh + 0x34));
        NtUnmapViewOfSection((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase);
        if (VirtualAllocEx((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, *(uint*)(pinh + 0x50 /* SizeOfImage */), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) == IntPtr.Zero)
            Run(exeBuffer, hostProcess, optionalArguments); // Memory allocation failed; try again (this can happen in low memory situations)

        fixed (byte* p = &exeBuffer[0])
            NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, (IntPtr)p, *(uint*)(pinh + 84 /* SizeOfHeaders */), IntPtr.Zero);

        for (ushort i = 0; i < *(ushort*)(pinh + 0x6 /* NumberOfSections */); i++)
        {
            Buffer.BlockCopy(exeBuffer, e_lfanew + IMAGE_NT_HEADERS.Length + (IMAGE_SECTION_HEADER.Length * i), IMAGE_SECTION_HEADER, 0, IMAGE_SECTION_HEADER.Length);
            fixed (byte* p = &exeBuffer[*(uint*)(pish + 0x14 /* PointerToRawData */)])
                NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)((int)ImageBase + *(uint*)(pish + 0xc /* VirtualAddress */)), (IntPtr)p, *(uint*)(pish + 0x10 /* SizeOfRawData */), IntPtr.Zero);
        }

        NtGetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
        NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)(*(uint*)(ctx + 0xAC /* ecx */)), ImageBase, 0x4, IntPtr.Zero);
        *(uint*)(ctx + 0xB0 /* eax */) = (uint)ImageBase + *(uint*)(pinh + 0x28 /* AddressOfEntryPoint */);
        NtSetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
        NtResumeThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, IntPtr.Zero);


        return true;
    }

    #region WinNT Definitions

    private const uint CONTEXT_FULL = 0x10007;
    private const int CREATE_SUSPENDED = 0x4;
    private const int MEM_COMMIT = 0x1000;
    private const int MEM_RESERVE = 0x2000;
    private const int PAGE_EXECUTE_READWRITE = 0x40;
    private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
    private const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00

    private static short SW_SHOW = 5;
    private static short SW_HIDE = 0;
    private const uint STARTF_USESTDHANDLES = 0x00000100;
    private const uint STARTF_USESHOWWINDOW = 0x00000001;


    #region WinAPI
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, int[] lpProcessInfo);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);

    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtWriteVirtualMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, IntPtr lpNumberOfBytesWritten);

    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtGetContextThread(IntPtr hThread, IntPtr lpContext);

    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtSetContextThread(IntPtr hThread, IntPtr lpContext);

    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern uint NtResumeThread(IntPtr hThread, IntPtr SuspendCount);
    #endregion

    #endregion
}
0 голосов
/ 15 февраля 2012

если вы ищете для запуска Exe-файлов с использованием C #, то эта ссылка дает хорошее объяснение с простым, но простым для понимания примером того, как следует использовать Process и Process.Start.

В двух словах, вы можете сделать

Process.Start("notepad.exe")

для запуска неуправляемых exe / приложений.

, если это не работает, укажите полный путь к приложению, например

Process.Start(@"c:\windows\system32\notepad.exe")

(я просто предполагаю, что notepad.exe существует в этой папке, но выполучить идею.

0 голосов
/ 24 августа 2010

Используйте [Process.Start()][1] (или другую перегрузку), и пусть O / S выполняет загрузку в память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...