Search code examples
c#vb.netdll-injection

C# Dll injector, VB.Net Dll injector


I had made the dll injector easy before, but i had Windows 7, I made it in C# and C++, it worked great! but now when i try the same codes in Windows 8, it seems that it doesn't inject the DLL in the right way! :) as the DLL is not working...

(The code which i'm trying is the public one <)

VB.Net Code:

Private TargetProcessHandle As Integer
Private pfnStartAddr As Integer
Private pszLibFileRemote As String
Private TargetBufferSize As Integer

Public Const PROCESS_VM_READ = &H10
Public Const TH32CS_SNAPPROCESS = &H2
Public Const MEM_COMMIT = 4096
Public Const PAGE_READWRITE = 4


Public Const PROCESS_CREATE_THREAD = (&H2)
Public Const PROCESS_VM_OPERATION = (&H8)
Public Const PROCESS_VM_WRITE = (&H20)
Dim DLLFileName As String
Public Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByVal lpBuffer As String, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Integer

Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _
ByVal lpLibFileName As String) As Integer

Public Declare Function VirtualAllocEx Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpAddress As Integer, _
ByVal dwSize As Integer, _
ByVal flAllocationType As Integer, _
ByVal flProtect As Integer) As Integer

Public Declare Function WriteProcessMemory Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByVal lpBuffer As String, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Integer

Public Declare Function GetProcAddress Lib "kernel32" ( _
ByVal hModule As Integer, ByVal lpProcName As String) As Integer

Private Declare Function GetModuleHandle Lib "Kernel32" Alias "GetModuleHandleA" ( _
ByVal lpModuleName As String) As Integer

Public Declare Function CreateRemoteThread Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpThreadAttributes As Integer, _
ByVal dwStackSize As Integer, _
ByVal lpStartAddress As Integer, _
ByVal lpParameter As Integer, _
ByVal dwCreationFlags As Integer, _
ByRef lpThreadId As Integer) As Integer

Public Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Integer, _
ByVal bInheritHandle As Integer, _
ByVal dwProcessId As Integer) As Integer

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Integer

Private Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" ( _
ByVal hObject As Integer) As Integer


Dim ExeName As String = IO.Path.GetFileNameWithoutExtension(Application.ExecutablePath)

Private Sub Inject()

    Try
        Timer1.Stop()
        Dim TargetProcess As Process() = Process.GetProcessesByName(TextBox1.Text)
        TargetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD Or PROCESS_VM_OPERATION Or PROCESS_VM_WRITE, False, TargetProcess(0).Id)
        pszLibFileRemote = OpenFileDialog1.FileName
        pfnStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")
        TargetBufferSize = 1 + Len(pszLibFileRemote)
        Dim Rtn As Integer
        Dim LoadLibParamAdr As Integer
        LoadLibParamAdr = VirtualAllocEx(TargetProcessHandle, 0, TargetBufferSize, MEM_COMMIT, PAGE_READWRITE)
        Rtn = WriteProcessMemory(TargetProcessHandle, LoadLibParamAdr, pszLibFileRemote, TargetBufferSize, 0)
        CreateRemoteThread(TargetProcessHandle, 0, 0, pfnStartAddr, LoadLibParamAdr, 0, 0)
        CloseHandle(TargetProcessHandle)
    Catch ex As Exception
        MessageBox.Show("EX:" + ex.ToString)
    End Try
End Sub

It was giving an error "System.EntryPointNotFoundException....." but after i changed this:

CloseHandle Lib "kernel32" Alias "CloseHandleA"

TO this:

CloseHandle Lib "kernel32" Alias "CloseHandle"

it doesn't show the error again, but it also doesn't inject it in right way!

For C# :

[DllImport("kernel32")]
    public static extern IntPtr CreateRemoteThread(
      IntPtr hProcess,
      IntPtr lpThreadAttributes,
      uint dwStackSize,
      UIntPtr lpStartAddress, // raw Pointer into remote process
      IntPtr lpParameter,
      uint dwCreationFlags,
      out IntPtr lpThreadId
    );

    [DllImport("kernel32.dll")]
    public static extern IntPtr OpenProcess(
        UInt32 dwDesiredAccess,
        Int32 bInheritHandle,
        Int32 dwProcessId
        );

    [DllImport("kernel32.dll")]
    public static extern Int32 CloseHandle(
    IntPtr hObject
    );

    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern bool VirtualFreeEx(
        IntPtr hProcess, 
        IntPtr lpAddress,
        UIntPtr dwSize, 
        uint dwFreeType
        );

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
    public static extern UIntPtr GetProcAddress(
        IntPtr hModule, 
        string procName
        );

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

    [DllImport("kernel32.dll")]
    static extern bool WriteProcessMemory(
        IntPtr hProcess,
        IntPtr lpBaseAddress,
        string lpBuffer,
        UIntPtr nSize,
        out IntPtr lpNumberOfBytesWritten
    );

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(
        string lpModuleName
        );

    [DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
    internal static extern Int32 WaitForSingleObject(
        IntPtr handle, 
        Int32 milliseconds
        );

    public Int32 GetProcessId(String proc)
    {
        Process[] ProcList;
        ProcList = Process.GetProcessesByName(proc);
        return ProcList[0].Id;
    }

    public void InjectDLL(IntPtr hProcess, String strDLLName)
    {
        IntPtr bytesout;

        // Length of string containing the DLL file name +1 byte padding
        Int32 LenWrite = strDLLName.Length + 1;
        // Allocate memory within the virtual address space of the target process
        IntPtr AllocMem = (IntPtr)VirtualAllocEx(hProcess, (IntPtr)null, (uint)LenWrite, 0x1000, 0x40); //allocation pour WriteProcessMemory

        // Write DLL file name to allocated memory in target process
        WriteProcessMemory(hProcess, AllocMem, strDLLName, (UIntPtr)LenWrite, out bytesout);
        // Function pointer "Injector"
        UIntPtr Injector = (UIntPtr)GetProcAddress( GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        if (Injector == null)
        {
            MessageBox.Show(" Injector Error! \n ");
            // return failed
            return;
        }

        // Create thread in target process, and store handle in hThread
        IntPtr hThread = (IntPtr)CreateRemoteThread(hProcess, (IntPtr)null, 0, Injector, AllocMem, 0, out bytesout);
        // Make sure thread handle is valid
        if ( hThread == null )
        {
            //incorrect thread handle ... return failed
            MessageBox.Show(" hThread [ 1 ] Error! \n ");
            return;
        }
        // Time-out is 10 seconds...
        int Result = WaitForSingleObject(hThread, 10 * 1000);
        // Check whether thread timed out...
        if (Result == 0x00000080L || Result == 0x00000102L || Result == 0xFFFFFFFF)
        {
            /* Thread timed out... */
            MessageBox.Show(" hThread [ 2 ] Error! \n ");
            // Make sure thread handle is valid before closing... prevents crashes.
            if (hThread != null)
            {
                //Close thread in target process
                CloseHandle(hThread);
            }
            return;
        }
        // Sleep thread for 1 second
        Thread.Sleep(1000);
        // Clear up allocated space ( Allocmem )
        VirtualFreeEx(hProcess, AllocMem, (UIntPtr)0, 0x8000);
        // Make sure thread handle is valid before closing... prevents crashes.
        if (hThread != null)
        {
            //Close thread in target process
            CloseHandle(hThread);
        }
        // return succeeded
        return;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        String strDLLName = "C:\\test.dll"; 
        String strProcessName = "notepad"; 

        Int32 ProcID = GetProcessId(strProcessName);
        if (ProcID >= 0)
        {
            IntPtr hProcess = (IntPtr)OpenProcess(0x1F0FFF, 1,ProcID);
            if (hProcess == null)
            {
                MessageBox.Show("OpenProcess() Failed!");
                return;
            }
            else
                InjectDLL(hProcess, strDLLName);
        }
    }

It doesn't give me errors, but it also doesn't inject in right way!

Thanks very much! :)


Solution

  • What happens?
    If the remote process crashes then it is likely that You should not use GetProcAddress since the remote API address may be different. It can be different for example when the injecting process is hooked using EAT hooking and the remote one isn't, so it does not have anything meaningful at the address You got from local GetProcAddress. It will be also different even when both processes are hooked using EAT hooking, since the hook implementations cause more random or entirely random locations.
    I had similar sitation where the crashes occurred under Windows 8, but not in earlier versions.

    One solution would be reading EAT table of the remote process and getting the address from there.

    Related code follows

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.Reflection;
    using System.IO;
    using System.Threading;
    using Microsoft.Win32.SafeHandles;
    using System.Runtime.CompilerServices;
    using System.Security;
    
    namespace Injection
    {
        public static class Remote_EAT_Reader
        {
    
            public static IntPtr? GetProcessModuleHandle(int processID, string moduleName) 
            {
                IntPtr snapshot = IntPtr.Zero;
    
                try
                {
                    //http://pastebin.com/BzD1jdmH
                    snapshot = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, processID);
    
                    MODULEENTRY32 mod = new MODULEENTRY32() { dwSize = MODULEENTRY32.SizeOf };
    
                    if (!Module32First(snapshot, ref mod))
                        return null;
    
    
                    string searchString = moduleName.ToLowerInvariant();
    
                    do
                    {
                        if (mod.szModule.ToLowerInvariant() == searchString)
                            return mod.modBaseAddr;
                    }
                    while (Module32Next(snapshot, ref mod));
    
                    return IntPtr.Zero;
                }
                finally
                {
                    if (snapshot != IntPtr.Zero)
                        CloseHandle(snapshot);
                }
            }
    
    
            public static IntPtr? GetProcessProcAddress(IntPtr hProcess, int processID, string moduleName, string procName)   
            {
                IntPtr? moduleHandle = GetProcessModuleHandle(processID, moduleName);
    
                if (!moduleHandle.HasValue)
                    return null;
    
    
    
                //code adapted from http://alter.org.ua/en/docs/nt_kernel/procaddr/index3.php
    
    
                UIntPtr hmodCaller = new UIntPtr(unchecked((ulong)moduleHandle.Value.ToInt64()));
    
    
                //http://stackoverflow.com/questions/769537/hook-loadlibrary-call-from-managed-code
    
                //parse dos header
                UIntPtr dos_header_ptr = hmodCaller;
                if (dos_header_ptr == UIntPtr.Zero)
                    return null;
    
                IMAGE_DOS_HEADER dos_header;
                if (!ReadProcessMemory(hProcess, dos_header_ptr, out dos_header, IMAGE_DOS_HEADER.SizeOf, IntPtr.Zero))
                    return null;
    
                if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
                    return null; //not a dos program
    
    
    
                IMAGE_DATA_DIRECTORY[] DataDirectory;
                if (IntPtr.Size == 4)
                {
                    //parse nt header
                    UIntPtr nt_header_ptr = new UIntPtr((uint)dos_header.e_lfanew + hmodCaller.ToUInt32());
                    if (nt_header_ptr == UIntPtr.Zero)
                        return null;
    
                    IMAGE_NT_HEADERS32 nt_header;
                    if (!ReadProcessMemory(hProcess, nt_header_ptr, out nt_header, IMAGE_NT_HEADERS32.SizeOf, IntPtr.Zero))
                        return null;
    
                    if (nt_header.Signature != IMAGE_NT_SIGNATURE)
                        return null; //not a windows program
    
    
                    //http://newgre.net/ncodehook
                    //if (ntHeaders.FileHeader.Characteristics & IMAGE_FILE_DLL)
                    //  throw std::runtime_error("Error while setting image base address: not the image base of an executable");
    
    
                    //optional header (pretty much not optional)
                    IMAGE_OPTIONAL_HEADER32 optional_header = nt_header.OptionalHeader32;
                    if (optional_header.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)     
                        return null; //no optional header
    
    
                    DataDirectory = optional_header.DataDirectory;
                }
                else    //if (IntPtr.Size == 4)
                {
                    //parse nt header
                    UIntPtr nt_header_ptr = new UIntPtr((uint)dos_header.e_lfanew + hmodCaller.ToUInt64());
                    if (nt_header_ptr == UIntPtr.Zero)
                        return null;
    
                    IMAGE_NT_HEADERS64 nt_header;
                    if (!ReadProcessMemory(hProcess, nt_header_ptr, out nt_header, IMAGE_NT_HEADERS64.SizeOf, IntPtr.Zero))
                        return null;
    
                    if (nt_header.Signature != IMAGE_NT_SIGNATURE)
                        return null; //not a windows program
    
    
                    //http://newgre.net/ncodehook
                    //if (ntHeaders.FileHeader.Characteristics & IMAGE_FILE_DLL)
                    //  throw std::runtime_error("Error while setting image base address: not the image base of an executable");
    
    
                    //optional header (pretty much not optional)
                    IMAGE_OPTIONAL_HEADER64 optional_header = nt_header.OptionalHeader64;
                    if (optional_header.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)     
                        return null; //no optional header
    
    
                    DataDirectory = optional_header.DataDirectory;
    
                }    //if (IntPtr.Size == 4)
    
    
    
                //http://stackoverflow.com/questions/3430718/thunk-table-in-import-address-table and http://forums.codeguru.com/showthread.php?512610-RESOLVED-api-hooking and especially http://svn.coderepos.org/share/lang/objective-cplusplus/i3/trunk/tmp/dwmedit/ApiHook.cc
                DirectoryEntries entryIndex = DirectoryEntries.IMAGE_DIRECTORY_ENTRY_EXPORT;   
    
                uint size = DataDirectory[(int)entryIndex].Size;
    
                if (size == 0)
                    return null; //no import table
    
                uint virtualAddress = DataDirectory[(int)entryIndex].VirtualAddress;
    
                //http://newgre.net/ncodehook
                if (virtualAddress == 0)
                    return null; //no import directory
    
    
                UIntPtr pExports_ptr = new UIntPtr((ulong)virtualAddress + hmodCaller.ToUInt64());
                if (pExports_ptr == UIntPtr.Zero)
                    return null;
    
                IMAGE_EXPORT_DIRECTORY pExports;
                if (!ReadProcessMemory(hProcess, pExports_ptr,
                    out pExports, IMAGE_EXPORT_DIRECTORY.SizeOf, IntPtr.Zero))
                {
                    return null;
                }
    
    
                UIntPtr functions_ptr = new UIntPtr(hmodCaller.ToUInt64() + (ulong)pExports.AddressOfFunctions);
                UIntPtr ordinals_ptr = new UIntPtr(hmodCaller.ToUInt64() + (ulong)pExports.AddressOfNameOrdinals);
                UIntPtr names_ptr = new UIntPtr(hmodCaller.ToUInt64() + (ulong)pExports.AddressOfNames);
    
                uint max_name = pExports.NumberOfNames;
                uint max_func = pExports.NumberOfFunctions;
    
                uint max_ordinal = max_name;   
    
    
    
                uint[] functions = new uint[max_func];
                if (!ReadProcessMemory(hProcess, functions_ptr, functions, (int)max_func * sizeof(uint), IntPtr.Zero))
                {
                    return null;
                }
    
                ushort[] ordinals = new ushort[max_ordinal];
                if (!ReadProcessMemory(hProcess, ordinals_ptr, ordinals, (int)max_ordinal * sizeof(ushort), IntPtr.Zero))
                {
                    return null;
                }
    
                uint[] names = new uint[max_name];
                if (!ReadProcessMemory(hProcess, names_ptr, names, (int)max_name * sizeof(uint), IntPtr.Zero))
                {
                    return null;
                }
    
    
    
                for (uint i = 0; i < max_ordinal; i++)    
                {
                    uint ord = ordinals[i];
                    if (i >= max_name || ord >= max_func)
                    {
                        return null;
                    }
    
                    if (functions[ord] < virtualAddress || functions[ord] >= virtualAddress + size)
                    {
                        UIntPtr name_ptr = new UIntPtr(hmodCaller.ToUInt64() + (ulong)names[i]);
    
                        if (name_ptr != UIntPtr.Zero)
                        {
                            byte[] name_buf = new byte[procName.Length + 1];    //NB! +1 for terminating zero
                            if (!ReadProcessMemory(hProcess, name_ptr, name_buf, name_buf.Length, IntPtr.Zero))
                            {
                                continue;
                            }
    
                            if (name_buf[name_buf.Length - 1] == 0)     //check for partial name that does not end with terminating zero
                            {
                                string name = Encoding.ASCII.GetString(name_buf, 0, name_buf.Length - 1);   //NB! buf length - 1
    
                                if (name == procName)
                                {
                                    var pFunctionAddress1 = new UIntPtr(hmodCaller.ToUInt64() + (ulong)functions[ord]);
    
                                    return new IntPtr(unchecked((long)pFunctionAddress1.ToUInt64()));
                                }
                            }
                        }   //if (name_ptr != UIntPtr.Zero)
                    }   //if (functions[ord] < virtualAddress || functions[ord] >= virtualAddress + size)
                }   //for (uint i = 0; i < pExports.AddressOfNames; i++)
    
                return null;
    
            }   //static IntPtr? GetProcessProcAddress(int procID, string moduleName, string procName)
    
            #region PE Structs
    
            private const uint IMAGE_DOS_SIGNATURE = 0x5A4D;      // MZ
            private const uint IMAGE_OS2_SIGNATURE = 0x454E;      // NE
            private const uint IMAGE_OS2_SIGNATURE_LE = 0x454C;      // LE
            private const uint IMAGE_VXD_SIGNATURE = 0x454C;      // LE
            private const uint IMAGE_NT_SIGNATURE = 0x00004550;  // PE00
    
            private const uint IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
            private const uint IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
    
            private enum DirectoryEntries
            {
                IMAGE_DIRECTORY_ENTRY_EXPORT = 0,   // Export Directory
                IMAGE_DIRECTORY_ENTRY_IMPORT = 1,   // Import Directory
                IMAGE_DIRECTORY_ENTRY_RESOURCE = 2,   // Resource Directory
                IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3,   // Exception Directory
                IMAGE_DIRECTORY_ENTRY_SECURITY = 4,   // Security Directory
                IMAGE_DIRECTORY_ENTRY_BASERELOC = 5,   // Base Relocation Table
                IMAGE_DIRECTORY_ENTRY_DEBUG = 6,   // Debug Directory
                //      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7,   // (X86 usage)
                IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7,   // Architecture Specific Data
                IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8,   // RVA of GP
                IMAGE_DIRECTORY_ENTRY_TLS = 9,   // TLS Directory
                IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10,   // Load Configuration Directory
                IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11,   // Bound Import Directory in headers
                IMAGE_DIRECTORY_ENTRY_IAT = 12,   // Import Address Table
                IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,   // Delay Load Import Descriptors
                IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14,   // COM Runtime descriptor
    
            }   //private enum DirectoryEntries
    
    
    
            //code taken from http://www.sergeyakopov.com/2010/11/reading-pe-format-using-data-marshaling-in-net
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_DOS_HEADER
            {
                public static int SizeOf = Marshal.SizeOf(typeof(IMAGE_DOS_HEADER));
    
                public UInt16 e_magic;
                public UInt16 e_cblp;
                public UInt16 e_cp;
                public UInt16 e_crlc;
                public UInt16 e_cparhdr;
                public UInt16 e_minalloc;
                public UInt16 e_maxalloc;
                public UInt16 e_ss;
                public UInt16 e_sp;
                public UInt16 e_csum;
                public UInt16 e_ip;
                public UInt16 e_cs;
                public UInt16 e_lfarlc;
                public UInt16 e_ovno;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
                public UInt16[] e_res1;
                public UInt16 e_oemid;
                public UInt16 e_oeminfo;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
                public UInt16[] e_res2;
                public UInt32 e_lfanew;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_NT_HEADERS32
            {
                public static int SizeOf = Marshal.SizeOf(typeof(IMAGE_NT_HEADERS32));
    
                public UInt32 Signature;
                public IMAGE_FILE_HEADER FileHeader;
                public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_NT_HEADERS64
            {
                public static int SizeOf = Marshal.SizeOf(typeof(IMAGE_NT_HEADERS64));
    
                public UInt32 Signature;
                public IMAGE_FILE_HEADER FileHeader;
                public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_FILE_HEADER
            {
                public UInt16 Machine;
                public UInt16 NumberOfSections;
                public UInt32 TimeDateStamp;
                public UInt32 PointerToSymbolTable;
                public UInt32 NumberOfSymbols;
                public UInt16 SizeOfOptionalHeader;
                public UInt16 Characteristics;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_OPTIONAL_HEADER32
            {
                public UInt16 Magic;
                public Byte MajorLinkerVersion;
                public Byte MinorLinkerVersion;
                public UInt32 SizeOfCode;
                public UInt32 SizeOfInitializedData;
                public UInt32 SizeOfUninitializedData;
                public UInt32 AddressOfEntryPoint;
                public UInt32 BaseOfCode;
                public UInt32 BaseOfData;
                public UInt32 ImageBase;
                public UInt32 SectionAlignment;
                public UInt32 FileAlignment;
                public UInt16 MajorOperatingSystemVersion;
                public UInt16 MinorOperatingSystemVersion;
                public UInt16 MajorImageVersion;
                public UInt16 MinorImageVersion;
                public UInt16 MajorSubsystemVersion;
                public UInt16 MinorSubsystemVersion;
                public UInt32 Win32VersionValue;
                public UInt32 SizeOfImage;
                public UInt32 SizeOfHeaders;
                public UInt32 CheckSum;
                public UInt16 Subsystem;
                public UInt16 DllCharacteristics;
                public UInt32 SizeOfStackReserve;
                public UInt32 SizeOfStackCommit;
                public UInt32 SizeOfHeapReserve;
                public UInt32 SizeOfHeapCommit;
                public UInt32 LoaderFlags;
                public UInt32 NumberOfRvaAndSizes;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
                public IMAGE_DATA_DIRECTORY[] DataDirectory;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_OPTIONAL_HEADER64
            {
                public UInt16 Magic;
                public Byte MajorLinkerVersion;
                public Byte MinorLinkerVersion;
                public UInt32 SizeOfCode;
                public UInt32 SizeOfInitializedData;
                public UInt32 SizeOfUninitializedData;
                public UInt32 AddressOfEntryPoint;
                public UInt32 BaseOfCode;
                public UInt64 ImageBase;
                public UInt32 SectionAlignment;
                public UInt32 FileAlignment;
                public UInt16 MajorOperatingSystemVersion;
                public UInt16 MinorOperatingSystemVersion;
                public UInt16 MajorImageVersion;
                public UInt16 MinorImageVersion;
                public UInt16 MajorSubsystemVersion;
                public UInt16 MinorSubsystemVersion;
                public UInt32 Win32VersionValue;
                public UInt32 SizeOfImage;
                public UInt32 SizeOfHeaders;
                public UInt32 CheckSum;
                public UInt16 Subsystem;
                public UInt16 DllCharacteristics;
                public UInt64 SizeOfStackReserve;
                public UInt64 SizeOfStackCommit;
                public UInt64 SizeOfHeapReserve;
                public UInt64 SizeOfHeapCommit;
                public UInt32 LoaderFlags;
                public UInt32 NumberOfRvaAndSizes;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
                public IMAGE_DATA_DIRECTORY[] DataDirectory;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_DATA_DIRECTORY
            {
                public UInt32 VirtualAddress;
                public UInt32 Size;
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct ImgDelayDescr
            {
                public static uint SizeOf = (uint)Marshal.SizeOf(typeof(ImgDelayDescr));
    
                public uint grAttrs;        // attributes
                public uint rvaDLLName;     // RVA to dll name
                public uint rvaHmod;        // RVA of module handle
                public uint rvaIAT;         // RVA of the IAT
                public uint rvaINT;         // RVA of the INT
                public uint rvaBoundIAT;    // RVA of the optional bound IAT
                public uint rvaUnloadIAT;   // RVA of optional copy of original IAT
                public uint dwTimeStamp;    // 0 if not bound,
                // O.W. date/time stamp of DLL bound to (Old BIND)
            } //ImgDelayDescr, * PImgDelayDescr;
    
    
            //http://www.gamedev.net/topic/409936-advanced-c-native-dll-image-import-reading/
            [StructLayout(LayoutKind.Explicit)]
            public struct IMAGE_IMPORT_DESCRIPTOR
            {
                public static uint SizeOf = (uint)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR));
    
                #region union
                /// <summary>
                /// CSharp doesnt really support unions, but they can be emulated by a field offset 0
                /// </summary>
                [FieldOffset(0)]
                public uint Characteristics;            // 0 for terminating null import descriptor
                [FieldOffset(0)]
                public uint OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
                #endregion
    
                [FieldOffset(4)]
                public uint TimeDateStamp;
                [FieldOffset(8)]
                public uint ForwarderChain;
                [FieldOffset(12)]
                public uint Name;
                [FieldOffset(16)]
                public uint FirstThunk;
            }
    
            //http://pinvoke.net/default.aspx/Structures/IMAGE_EXPORT_DIRECTORY.html
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_EXPORT_DIRECTORY
            {
                public static uint SizeOf = (uint)Marshal.SizeOf(typeof(IMAGE_EXPORT_DIRECTORY));
    
                public UInt32 Characteristics;
                public UInt32 TimeDateStamp;
                public UInt16 MajorVersion;
                public UInt16 MinorVersion;
                public UInt32 Name;
                public UInt32 Base;
                public UInt32 NumberOfFunctions;
                public UInt32 NumberOfNames;
                public UInt32 AddressOfFunctions;     // RVA from base of image
                public UInt32 AddressOfNames;     // RVA from base of image
                public UInt32 AddressOfNameOrdinals;  // RVA from base of image
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct IMAGE_THUNK_DATA        
            {
                public static uint SizeOf = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA));
    
                public IntPtr ForwarderString;      // PBYTE 
                public IntPtr Function;             // PDWORD
                public IntPtr Ordinal;
                public IntPtr AddressOfData;        // PIMAGE_IMPORT_BY_NAME
            }
    
    
    
            #endregion
    
    
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static public extern bool CloseHandle(IntPtr hHandle);
    
            [DllImport("kernel32.dll")]
            static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme);
    
            [DllImport("kernel32.dll")]
            static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static public extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, int th32ProcessID);
    
            public const short INVALID_HANDLE_VALUE = -1;
    
            [Flags]
            public enum SnapshotFlags : uint
            {
                HeapList = 0x00000001,
                Process = 0x00000002,
                Thread = 0x00000004,
                Module = 0x00000008,
                Module32 = 0x00000010,
                Inherit = 0x80000000,
                All = 0x0000001F
            }
    
            public struct MODULEENTRY32
            {
                public static uint SizeOf = (uint)Marshal.SizeOf(typeof(MODULEENTRY32));
    
                //http://pastebin.com/BzD1jdmH
                private const int MAX_PATH = 255;
                internal uint dwSize;    
                internal uint th32ModuleID;
                internal uint th32ProcessID;
                internal uint GlblcntUsage;
                internal uint ProccntUsage;
                internal IntPtr modBaseAddr;
                internal uint modBaseSize;
                internal IntPtr hModule;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
                internal string szModule;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 5)]
                internal string szExePath;
            }
    
    
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr baseAddress, [Out] byte[] buffer, int size, out IntPtr numBytesRead);  
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr baseAddress, [Out] byte[] buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, [Out] byte[] buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, [Out] uint[] buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, [Out] ushort[] buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr baseAddress, out IntPtr buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_DOS_HEADER buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_NT_HEADERS32 buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_NT_HEADERS64 buffer, int size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out ImgDelayDescr buffer, uint size, IntPtr numBytesRead);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_THUNK_DATA buffer, uint size, IntPtr numBytesRead);   
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_IMPORT_DESCRIPTOR buffer, uint size, IntPtr numBytesRead);   
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr baseAddress, out IMAGE_EXPORT_DIRECTORY buffer, uint size, IntPtr numBytesRead);   
    
    
    
        }
    }