2010-08-24 4 views
17

this 문서에 설명 된 것과 같은 메모리에서 실행 파일을 실행하려고합니다. 나는 .net/managed exes를 아주 쉽게 실행할 수있다. 하지만 notepad.exe 또는 calc.exe과 같은 실행 파일을 실행할 수 없습니다. 어떻게하면 관리되지 않는 exes를 실행할 수 있습니까?EXE 파일을로드하고 메모리에서 실행하십시오.

답변

23

메모리에서 .NET 실행 파일을 실행하는 경우 라이브러리와 CLR 자체가 많은 어려움을 겪고 있습니다. notepad.exe 및 calc.exe와 같은 기본 실행 파일의 경우 수동 작업을 많이 수행해야합니다. 기본적으로 Windows 로더처럼 행동해야합니다.

여기에는주의할만한 페이지가 있지만 this in-depth article에는 PE를 메모리에로드하고 올바른 리베이스 및 픽스 업을 수행하는 데 필요한 단계가 있습니다. 그런 다음 기사와 같이 진입 점을 찾아서 실행할 수 있어야합니다.

notepad.exe 및 calc.exe를 실행하고 싶다면 가장 쉬운 방법은 Process.Start을 사용하고 디스크에서 실행하는 것입니다. 그렇지 않으면 실행 파일이 프로세스의 리소스로 포함 된 경우 다음 가장 쉬운 방법은 내용을 임시 위치 (참조)의 디스크에 쓰고 거기에서 실행하는 것입니다.

+0

당신은 매우입니다 그 좋은 물건'크리스'': – Xaqron

-6

[Process.Start()][1] (또는 다른 과부하)을 사용하고 O/S가 메모리에로드되도록합니다.

17

나는 확실하지 않다 그러나이 thread에서 다음 코드 도움이 될 수 있습니다

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

내가 한 ......... –

+0

var dir = System.IO.Directory.GetCurrentDirectory(); 바이트 [] 파일 = Resource1.someExecutable; CMemoryExecute. 실행 (파일, 디렉터리), –

+0

어디 Resorurc e1.someExecutable은 실행하고 싶고 실행되지 않는 실행 파일입니다 ... –

-5

당신은 C#을 사용 EXE 파일을 실행을 찾고 있다면, 그럼 this link는 간단하지만 따라하기 쉬운 좋은 설명을 제공합니다 예 : ProcessProcess.Start을 사용해야합니다.

는 간단히 말해서, 당신은 관리되지 않는 EXE/응용 프로그램을 실행하는

Process.Start("notepad.exe")

할 수 있습니다.

즉, 작동

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

가 (난 그냥 notepad.exe 해당 폴더에 존재하는 가정입니다 같은 응용 프로그램의 fullpath에 제공,하지만 당신은 아이디어를 얻을하지 않는 경우.

+1

그는 HDD가 아닌 메모리에서 실행해야합니다. –

+0

'Process.Start()'를 사용하는 것이 어떻게 문제가되는지 모르겠습니다. – AceMark

+0

간단히 프로그램을 실행하는 방법을 간단하게 설명했습니다. 파일을 삭제하지 않고 파일을 실행하면 특히 특별한 경우에는 필요하지 않으므로 특히 중요하지 않습니다. – bytecode77

관련 문제