C#Dll喷油器,VB.Net Dll喷油器

时间:2014-07-07 07:41:46

标签: c# vb.net dll-injection

之前我已经让dll注入器变得容易了,但是我使用的是Windows 7,我用C#和C ++编写了它,效果很好!但是现在当我在Windows 8中尝试相同的代码时,似乎它没有以正确的方式注入DLL! :)因为DLL无法运行...

(我尝试的代码是公共代码<)

VB.Net代码:

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

发出错误" System.EntryPointNotFoundException ....."但在我改变之后:

CloseHandle Lib "kernel32" Alias "CloseHandleA"

对此:

CloseHandle Lib "kernel32" Alias "CloseHandle"

它没有再次显示错误,但它也没有以正确的方式注入错误!

对于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);
        }
    }

它没有给我错误,但它也没有正确注入!

非常感谢! :)

1 个答案:

答案 0 :(得分:0)

会发生什么?
如果远程进程崩溃,则可能不应使用GetProcAddress,因为远程API地址可能不同。它可以是不同的,例如当使用EAT钩子钩住注入过程而远程钩子不挂钩时,所以它在你从本地GetProcAddress得到的地址上没有任何意义。即使使用EAT钩子钩住两个进程也会有所不同,因为钩子实现会导致更多随机或完全随机的位置。 我在Windows 8下发生崩溃的情况类似,但早期版本没有。

一个解决方案是读取远程进程的EAT表并从那里获取地址。

相关代码如下

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);   



    }
}