2011-01-05 86 views
3

我目前正在嘗試創建一個C#應用程序,它將允許我從非託管DLL查看導出表。我的問題是,一旦我掌握了所有需要的指針,我就不知道如何循環API提供給我的信息。這裏是我現在所擁有的:在C#中的非託管dll上查看導出表

using System; 
using System.ComponentModel; 
using System.Runtime.InteropServices; 

namespace DLLMapper 
{ 
class DLLExportViewer 
{ 
     #region APIs 
     [DllImport("imagehlp.dll")] 
     public static extern Boolean MapAndLoad(String ImageName, String DllPath, ref LOADED_IMAGE LoadedImage, Boolean DotDll, Boolean ReadOnly); 

     [DllImport("imagehlp.dll")] 
     public static extern Boolean UnMapAndLoad(ref LOADED_IMAGE LoadedImage); 

     [DllImport("dbghelp.dll")] 
     public static extern IntPtr ImageDirectoryEntryToData(IntPtr Base, Boolean MappedAsImage, UInt16 DirectoryEntry, ref Int32 Size); 

     [DllImport("dbghelp.dll")] 
     public static extern IntPtr ImageRvaToVa(ref IMAGE_NT_HEADERS NtHeaders, IntPtr Base, UInt32 Rva, ref IMAGE_SECTION_HEADER LastRvaSection); 
     #endregion 

     #region Structures 
     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct LOADED_IMAGE 
     { 
      public String ModuleName; 
      public IntPtr hFile; 
      public IntPtr MappedAddress; 
      public IMAGE_NT_HEADERS FileHeader; 
      public IMAGE_SECTION_HEADER LastRvaSection; 
      public Int32 NumberOfSections; 
      public IMAGE_SECTION_HEADER Sections; 
      public Int32 Characteristics; 
      public Boolean fSystemImage; 
      public Boolean fDOSImage; 
      public LIST_ENTRY Links; 
      public Int32 SizeOfImage; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct 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; 
      public UInt32 AddressOfNames; 
      public UInt32 AddressOfOrdinals; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct IMAGE_NT_HEADERS 
     { 
      public Int32 Signature; 
      public IMAGE_FILE_HEADER FileHeader; 
      public IMAGE_OPTIONAL_HEADER OptionalHeader; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct LIST_ENTRY 
     { 
      public IntPtr Flink; 
      public IntPtr Blink; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct IMAGE_SECTION_HEADER 
     { 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = IMAGE_SIZEOF_SHORT_NAME)] 
      public Byte[] Name; 
      public Misc Misc; 
      public UInt32 PhysicalAddress; 
      public UInt32 VirtualAddress; 
      public UInt32 SizeOfRawData; 
      public UInt32 PointerToRawData; 
      public UInt32 PointerToRelocations; 
      public UInt32 PointerToLinenumbers; 
      public Int16 NumberOfRelocations; 
      public Int16 NumberOfLinenumbers; 
      public UInt32 Characteristics; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     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, Pack = 4)] 
     public struct IMAGE_OPTIONAL_HEADER 
     { 
      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 = IMAGE_NUMBEROF_DIRECTORY_ENTRIES)] 
      public IMAGE_DATA_DIRECTORY[] DataDirectory; 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct IMAGE_DATA_DIRECTORY 
     { 
      public UInt32 VirtualAddress; 
      public UInt32 Size; 
     } 

     [StructLayout(LayoutKind.Explicit)] 
     public struct Misc 
     { 
      [FieldOffset(0)] 
      public UInt32 PhysicalAddress; 
      [FieldOffset(0)] 
      public UInt32 VirtualSize; 
     } 
     #endregion 

     #region Variables & Constants 
     public const Int32 IMAGE_SIZEOF_SHORT_NAME = 8; 
     public const Int32 IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; 
     public const UInt16 IMAGE_DIRECTORY_ENTRY_EXPORT = 0; 

     /// <summary> 
     /// String value holding the path to the DLL file. This value is also returned by the FileName property. 
     /// </summary> 
     private String sDLLFilePath; 

     /// <summary> 
     /// Boolean value that is return by the LibraryLoaded property. 
     /// </summary> 
     private Boolean bLibraryLoaded; 

     /// <summary> 
     /// Int32 value that is returned by the FunctionCount property. 
     /// </summary> 
     private Int32 iFunctionCount; 

     /// <summary> 
     /// Int32 value that is returned by the SizeOfImage property. 
     /// </summary> 
     private Int32 iSizeOfCode; 

     /// <summary> 
     /// String array value that is returned by the ImageFunctions property. 
     /// </summary> 
     private String[] sFunctions; 
     #endregion 

     #region Properties 
     /// <summary> 
     /// Gets a boolean value indicating if the library has been loaded successfully. 
     /// </summary> 
     public Boolean LibraryLoaded { get { return bLibraryLoaded; } } 

     /// <summary> 
     /// Gets a string value indicating what file the class was initialized with. 
     /// </summary> 
     public String FileName { get { return sDLLFilePath; } } 

     /// <summary> 
     /// Gets a string array of the functions within the image. 
     /// </summary> 
     public String[] ImageFunctions { get { return sFunctions; } } 

     /// <summary> 
     /// Gets an Int32 value indicating the number of functions within the image. 
     /// </summary> 
     public Int32 FunctionCount { get { return iFunctionCount; } } 
     #endregion 

     /// <summary> 
     /// Initilizes the DLLExportViewer class. 
     /// </summary> 
     /// <param name="sFilePath">Path to the DLL file to initilize the class with.</param> 
     public DLLExportViewer(String sFilePath) 
     { 
      IMAGE_SECTION_HEADER ishSectionHeader = new IMAGE_SECTION_HEADER(); 
      LOADED_IMAGE liLoadedImage = new LOADED_IMAGE(); 
      IMAGE_EXPORT_DIRECTORY iedExportDirectory; 
      IntPtr pImageExportDirectory; 
      IntPtr pVirtualAddressOfNames; 
      Int32 iDirectoryExportSize = 0; 

      sDLLFilePath = sFilePath; 

      if (MapAndLoad(sDLLFilePath, null, ref liLoadedImage, true, true)) 
      { 
       bLibraryLoaded = true; 

       pImageExportDirectory = ImageDirectoryEntryToData(liLoadedImage.MappedAddress, false, IMAGE_DIRECTORY_ENTRY_EXPORT, ref iDirectoryExportSize); 
       iedExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(pImageExportDirectory, typeof(IMAGE_EXPORT_DIRECTORY)); 

       iFunctionCount = (Int32)iedExportDirectory.NumberOfFunctions; 

       pVirtualAddressOfNames = ImageRvaToVa(ref liLoadedImage.FileHeader, liLoadedImage.MappedAddress, iedExportDirectory.AddressOfNames, ref ishSectionHeader); 
      } 
      else 
      { 
       throw new Exception(String.Format("Failed to load library {0}\n\nError Number:{1]\nError:{2}", sDLLFilePath, Marshal.GetLastWin32Error(), new Win32Exception(Marshal.GetLastWin32Error()).Message)); 
      } 
     } 
    } 
} 

我最擔心的是我可能有一些錯誤的結構編組。但總而言之,我不確定該從哪裏出發。任何人都可以提供一些幫助嗎?

+2

你正在重新發明一個車輪。使用Dumpbin.exe/exports – 2011-01-05 16:54:18

+0

我知道我正在重新發明輪子。我正在努力學習如何去做,而不是僅僅使用其他工具。 – QuantumPhysGuy 2011-01-05 16:55:03

+0

@dotNetNin​​ja請改變你的用戶名 - 如果你是一個dotNetNin​​ja你會回答這個問題,而不是問它! ;-) – 2011-01-05 16:59:46

回答

2

下面介紹如何利用對做/調用到DBGHELP。請注意,我使用了來自pinvoke.net的多個聲明。

using System; 
using System.Text; 
using System.Runtime.InteropServices; 
using Microsoft.Win32.SafeHandles; 
using System.ComponentModel; 

internal static class NativeMethods 
{ 
    [Flags] 
    public enum EFileAccess : uint 
    { 
     // 
     // Standard Section 
     // 

     AccessSystemSecurity = 0x1000000, // AccessSystemAcl access type 
     MaximumAllowed = 0x2000000,  // MaximumAllowed access type 

     Delete = 0x10000, 
     ReadControl = 0x20000, 
     WriteDAC = 0x40000, 
     WriteOwner = 0x80000, 
     Synchronize = 0x100000, 

     StandardRightsRequired = 0xF0000, 
     StandardRightsRead = ReadControl, 
     StandardRightsWrite = ReadControl, 
     StandardRightsExecute = ReadControl, 
     StandardRightsAll = 0x1F0000, 
     SpecificRightsAll = 0xFFFF, 

     FILE_READ_DATA = 0x0001,  // file & pipe 
     FILE_LIST_DIRECTORY = 0x0001,  // directory 
     FILE_WRITE_DATA = 0x0002,  // file & pipe 
     FILE_ADD_FILE = 0x0002,   // directory 
     FILE_APPEND_DATA = 0x0004,  // file 
     FILE_ADD_SUBDIRECTORY = 0x0004,  // directory 
     FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe 
     FILE_READ_EA = 0x0008,   // file & directory 
     FILE_WRITE_EA = 0x0010,   // file & directory 
     FILE_EXECUTE = 0x0020,   // file 
     FILE_TRAVERSE = 0x0020,   // directory 
     FILE_DELETE_CHILD = 0x0040,  // directory 
     FILE_READ_ATTRIBUTES = 0x0080,  // all 
     FILE_WRITE_ATTRIBUTES = 0x0100,  // all 

     // 
     // Generic Section 
     // 

     GenericRead = 0x80000000, 
     GenericWrite = 0x40000000, 
     GenericExecute = 0x20000000, 
     GenericAll = 0x10000000, 

     SPECIFIC_RIGHTS_ALL = 0x00FFFF, 
     FILE_ALL_ACCESS = 
     StandardRightsRequired | 
     Synchronize | 
     0x1FF, 

     FILE_GENERIC_READ = 
     StandardRightsRead | 
     FILE_READ_DATA | 
     FILE_READ_ATTRIBUTES | 
     FILE_READ_EA | 
     Synchronize, 

     FILE_GENERIC_WRITE = 
     StandardRightsWrite | 
     FILE_WRITE_DATA | 
     FILE_WRITE_ATTRIBUTES | 
     FILE_WRITE_EA | 
     FILE_APPEND_DATA | 
     Synchronize, 

     FILE_GENERIC_EXECUTE = 
     StandardRightsExecute | 
      FILE_READ_ATTRIBUTES | 
      FILE_EXECUTE | 
      Synchronize 
    } 

    [Flags] 
    public enum EFileShare : uint 
    { 
     /// <summary> 
     /// 
     /// </summary> 
     None = 0x00000000, 
     /// <summary> 
     /// Enables subsequent open operations on an object to request read access. 
     /// Otherwise, other processes cannot open the object if they request read access. 
     /// If this flag is not specified, but the object has been opened for read access, the function fails. 
     /// </summary> 
     Read = 0x00000001, 
     /// <summary> 
     /// Enables subsequent open operations on an object to request write access. 
     /// Otherwise, other processes cannot open the object if they request write access. 
     /// If this flag is not specified, but the object has been opened for write access, the function fails. 
     /// </summary> 
     Write = 0x00000002, 
     /// <summary> 
     /// Enables subsequent open operations on an object to request delete access. 
     /// Otherwise, other processes cannot open the object if they request delete access. 
     /// If this flag is not specified, but the object has been opened for delete access, the function fails. 
     /// </summary> 
     Delete = 0x00000004 
    } 

    public enum ECreationDisposition : uint 
    { 
     /// <summary> 
     /// Creates a new file. The function fails if a specified file exists. 
     /// </summary> 
     New = 1, 
     /// <summary> 
     /// Creates a new file, always. 
     /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 
     /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies. 
     /// </summary> 
     CreateAlways = 2, 
     /// <summary> 
     /// Opens a file. The function fails if the file does not exist. 
     /// </summary> 
     OpenExisting = 3, 
     /// <summary> 
     /// Opens a file, always. 
     /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW. 
     /// </summary> 
     OpenAlways = 4, 
     /// <summary> 
     /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist. 
     /// The calling process must open the file with the GENERIC_WRITE access right. 
     /// </summary> 
     TruncateExisting = 5 
    } 

    [Flags] 
    public enum EFileAttributes : uint 
    { 
     Readonly = 0x00000001, 
     Hidden = 0x00000002, 
     System = 0x00000004, 
     Directory = 0x00000010, 
     Archive = 0x00000020, 
     Device = 0x00000040, 
     Normal = 0x00000080, 
     Temporary = 0x00000100, 
     SparseFile = 0x00000200, 
     ReparsePoint = 0x00000400, 
     Compressed = 0x00000800, 
     Offline = 0x00001000, 
     NotContentIndexed = 0x00002000, 
     Encrypted = 0x00004000, 
     Write_Through = 0x80000000, 
     Overlapped = 0x40000000, 
     NoBuffering = 0x20000000, 
     RandomAccess = 0x10000000, 
     SequentialScan = 0x08000000, 
     DeleteOnClose = 0x04000000, 
     BackupSemantics = 0x02000000, 
     PosixSemantics = 0x01000000, 
     OpenReparsePoint = 0x00200000, 
     OpenNoRecall = 0x00100000, 
     FirstPipeInstance = 0x00080000 
    } 

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    public static extern SafeFileHandle CreateFile(
     string lpFileName, 
     EFileAccess dwDesiredAccess, 
     EFileShare dwShareMode, 
     IntPtr lpSecurityAttributes, 
     ECreationDisposition dwCreationDisposition, 
     EFileAttributes dwFlagsAndAttributes, 
     IntPtr hTemplateFile 
    ); 

    [Flags] 
    public enum FileMapProtection : uint 
    { 
     PageReadonly = 0x02, 
     PageReadWrite = 0x04, 
     PageWriteCopy = 0x08, 
     PageExecuteRead = 0x20, 
     PageExecuteReadWrite = 0x40, 
     SectionCommit = 0x8000000, 
     SectionImage = 0x1000000, 
     SectionNoCache = 0x10000000, 
     SectionReserve = 0x4000000, 
    } 

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    public static extern SafeFileHandle CreateFileMapping(
     SafeFileHandle hFile, 
     IntPtr lpFileMappingAttributes, 
     FileMapProtection flProtect, 
     uint dwMaximumSizeHigh, 
     uint dwMaximumSizeLow, 
     string lpName 
    ); 

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    public static extern SafeFileHandle CreateFileMapping(
     SafeFileHandle hFile, 
     IntPtr lpFileMappingAttributes, 
     FileMapProtection flProtect, 
     uint dwMaximumSizeHigh, 
     uint dwMaximumSizeLow, 
     IntPtr lpName 
    ); 

    [Flags] 
    public enum FileMapAccess : uint 
    { 
     FileMapCopy = 0x0001, 
     FileMapWrite = 0x0002, 
     FileMapRead = 0x0004, 
     FileMapAllAccess = 0x001f, 
     FileMapExecute = 0x0020, 
    } 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern IntPtr MapViewOfFile(
     SafeFileHandle hFileMappingObject, 
     FileMapAccess dwDesiredAccess, 
     UInt32 dwFileOffsetHigh, 
     UInt32 dwFileOffsetLow, 
     UIntPtr dwNumberOfBytesToMap 
    ); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); 

    [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_DATA_DIRECTORY 
    { 
     public UInt32 VirtualAddress; 
     public UInt32 Size; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct IMAGE_OPTIONAL_HEADER 
    { 
     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_NT_HEADERS 
    { 
     public UInt32 Signature; 
     public IMAGE_FILE_HEADER FileHeader; 
     public IMAGE_OPTIONAL_HEADER OptionalHeader; 
    } 

    [DllImport("dbghelp.dll", SetLastError = true)] 
    public static extern IntPtr ImageNtHeader(
     IntPtr ImageBase 
    ); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct 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 
    } 

    [DllImport("dbghelp.dll", SetLastError = true)] 
    public static extern IntPtr ImageRvaToVa(
     IntPtr NtHeaders, 
     IntPtr Base, 
     UInt32 Rva, 
     IntPtr LastRvaSection 
    ); 
} 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     private static string[] GetExports(string ModuleFileName) 
     { 
      SafeFileHandle FileHandle = NativeMethods.CreateFile(
       ModuleFileName, 
       NativeMethods.EFileAccess.GenericRead, 
       NativeMethods.EFileShare.Read, 
       IntPtr.Zero, 
       NativeMethods.ECreationDisposition.OpenExisting, 
       NativeMethods.EFileAttributes.Normal, 
       IntPtr.Zero 
      ); 
      if (FileHandle.IsInvalid) 
       throw new Win32Exception(); 

      try 
      { 
       SafeFileHandle ImageHandle = NativeMethods.CreateFileMapping(
        FileHandle, 
        IntPtr.Zero, 
        NativeMethods.FileMapProtection.PageReadonly, 
        0, 
        0, 
        IntPtr.Zero 
       ); 
       if (ImageHandle.IsInvalid) 
        throw new Win32Exception(); 

       try 
       { 
        IntPtr ImagePointer = NativeMethods.MapViewOfFile(
         ImageHandle, 
         NativeMethods.FileMapAccess.FileMapRead, 
         0, 
         0, 
         UIntPtr.Zero 
        ); 
        if (ImagePointer == IntPtr.Zero) 
         throw new Win32Exception(); 

        try 
        { 
         IntPtr HeaderPointer = NativeMethods.ImageNtHeader(ImagePointer); 
         if (HeaderPointer == IntPtr.Zero) 
          throw new Win32Exception(); 

         NativeMethods.IMAGE_NT_HEADERS Header = (NativeMethods.IMAGE_NT_HEADERS)Marshal.PtrToStructure(
          HeaderPointer, 
          typeof(NativeMethods.IMAGE_NT_HEADERS) 
         ); 
         if (Header.Signature != 0x00004550)// "PE\0\0" as a DWORD 
          throw new Exception(ModuleFileName + " is not a valid PE file"); 

         IntPtr ExportTablePointer = NativeMethods.ImageRvaToVa(
          HeaderPointer, 
          ImagePointer, 
          Header.OptionalHeader.DataDirectory[0].VirtualAddress, 
          IntPtr.Zero 
         ); 
         if (ExportTablePointer == IntPtr.Zero) 
          throw new Win32Exception(); 
         NativeMethods.IMAGE_EXPORT_DIRECTORY ExportTable = (NativeMethods.IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
          ExportTablePointer, 
          typeof(NativeMethods.IMAGE_EXPORT_DIRECTORY) 
         ); 

         IntPtr NamesPointer = NativeMethods.ImageRvaToVa(
          HeaderPointer, 
          ImagePointer, 
          ExportTable.AddressOfNames, 
          IntPtr.Zero 
         ); 
         if (NamesPointer == IntPtr.Zero) 
          throw new Win32Exception(); 

         NamesPointer = NativeMethods.ImageRvaToVa(
          HeaderPointer, 
          ImagePointer, 
          (UInt32)Marshal.ReadInt32(NamesPointer), 
          IntPtr.Zero 
         ); 
         if (NamesPointer == IntPtr.Zero) 
          throw new Win32Exception(); 

         string[] exports = new string[ExportTable.NumberOfNames]; 
         for (int i = 0; i < exports.Length; i++) 
         { 
          exports[i] = Marshal.PtrToStringAnsi(NamesPointer); 
          NamesPointer += exports[i].Length + 1; 
         } 

         return exports; 
        } 
        finally 
        { 
         if (!NativeMethods.UnmapViewOfFile(ImagePointer)) 
          throw new Win32Exception(); 
        } 
       } 
       finally 
       { 
        ImageHandle.Close(); 
       } 
      } 
      finally 
      { 
       FileHandle.Close(); 
      } 
     } 

     static void Main(string[] args) 
     { 
      foreach (string s in GetExports(@"C:\Windows\System32\kernel32.dll")) 
      { 
       Console.WriteLine(s); 
      } 
      Console.ReadLine(); 
     } 
    } 
} 
+0

沒有爲我工作,ImageRvaToVa返回IntPtr.Zero,導致異常。 – TarmoPikaro 2017-04-13 06:59:51