public static bool GetExportDirectory(
            IntPtr PEBaseAddr,
            IntPtr ImageNTHeadersAddr,
            _IMAGE_NT_HEADERS ImageNTHeaders,
            out _IMAGE_EXPORT_DIRECTORY ImageExportDir)
        {
            ImageExportDir = new _IMAGE_EXPORT_DIRECTORY();
            IntPtr LastRvaSection = IntPtr.Zero;

            IntPtr ImageExportDirPtr = ImageRvaToVa(
                ImageNTHeadersAddr,
                PEBaseAddr,
                ImageNTHeaders.OptionalHeader.ExportDirectory.VirtualAddress,
                LastRvaSection);

            if (IsBadReadPtr(
                    ImageExportDirPtr,
                    (uint)Marshal.SizeOf(typeof(_IMAGE_EXPORT_DIRECTORY))))
            {
                return(false);
            }

            ImageExportDir = (_IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
                ImageExportDirPtr,
                typeof(_IMAGE_EXPORT_DIRECTORY));

            return(true);
        }
        private void loadExportTable(Process process, uint exportTableAddress, uint length, uint baseAddress, PEOptHeader optHeader, List<section> sections)
        {
          // Read in the first _IMAGE_EXPORT_DIRECTORY structure
          byte[] export_directory_rawData = MemoryFunctions.ReadMemory(process, exportTableAddress, (uint)Marshal.SizeOf(typeof(_IMAGE_EXPORT_DIRECTORY)));
          _IMAGE_EXPORT_DIRECTORY export_directory = (_IMAGE_EXPORT_DIRECTORY)MemoryFunctions.RawDataToObject(ref export_directory_rawData, typeof(_IMAGE_EXPORT_DIRECTORY));
          exports = new Hashtable(20);

          UInt64 functionNameArray = (UInt64)export_directory.AddressOfNames + address;
          string exportName = MemoryFunctions.ReadString(process, (UInt64)export_directory.Name + address, MemoryFunctions.STRING_TYPE.ascii);
          UInt64 functionOrdinalArray = (UInt64)export_directory.AddressOfNameOrdinal + address;
          UInt64 functionAddressArray = (UInt64)export_directory.AddressOfFunctions + address;
          for (int i = 0; i < export_directory.NumberOfNames; i++)
          {
              int ordinal_relative = (int)MemoryFunctions.ReadMemoryUShort(process, functionOrdinalArray + (UInt64)i * 2);
              int ordinal = ordinal_relative + (int)export_directory.Base;

              if (ordinal_relative < export_directory.NumberOfFunctions)
              {
                  // Continue with importing this function
                  string name = "";
                  if (i < export_directory.NumberOfNames)
                      name = MemoryFunctions.ReadString(process, (UInt64)MemoryFunctions.ReadMemoryDword(process, functionNameArray + (UInt64)i * 4) + address, MemoryFunctions.STRING_TYPE.ascii);
                  else
                      name = "oridinal" + ordinal.ToString();
                  
                  // Lookup the function rva now
                  try
                  {
                      UInt64 offset = (UInt64)MemoryFunctions.ReadMemoryDword(process, functionAddressArray + (UInt64)ordinal_relative * 4);
                      
                      // Check to see if this is a forwarded export
                      if (offset < optHeader.DataDirectory1_export.VirtualAddress ||
                          offset > optHeader.DataDirectory1_export.VirtualAddress + optHeader.DataDirectory1_export.Size)
                      {
                          // Lookup privilege of heap to confirm it requests execute privileges. We only want to list exported functions, not variables.
                          foreach (section exp in sections)
                          {
                              if (exp.Contains(offset))
                              {
                                  if (exp.IsExecutable())
                                  {
                                      // Add this exported function
                                      export new_export = new export(offset + address,
                                                          name,
                                                          ordinal);

                                      exports.Add(name.ToLower(), new_export);
                                  }
                                  break;
                              }
                          }
                      }
                      else
                      {
                          // Forwarded export. Ignore it.
                      }
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Warning, failed to parse PE header export directory entry for name '" + name + "'.");
                  }
              }
          }
      }
        public static bool GetExportedMethodsNames(
            IntPtr PEBaseAddr,
            IntPtr ImageNTHeadersAddr,
            _IMAGE_NT_HEADERS ImageNTHeaders,
            out string[] ExportedMethodsNames)
        {
            ExportedMethodsNames = new string[] {};

            _IMAGE_EXPORT_DIRECTORY ImageExportDir = new _IMAGE_EXPORT_DIRECTORY();

            IntPtr LastRvaSection = IntPtr.Zero;

            IntPtr ImageExportDirPtr = ImageRvaToVa(
                ImageNTHeadersAddr,
                PEBaseAddr,
                ImageNTHeaders.OptionalHeader.ExportDirectory.VirtualAddress,
                LastRvaSection);

            if (IsBadReadPtr(
                    ImageExportDirPtr,
                    (uint)Marshal.SizeOf(typeof(_IMAGE_EXPORT_DIRECTORY))))
            {
                return(false);
            }

            ImageExportDir = (_IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
                ImageExportDirPtr,
                typeof(_IMAGE_EXPORT_DIRECTORY));


            IntPtr TempPtr = ImageRvaToVa(
                ImageNTHeadersAddr,
                PEBaseAddr,
                (uint)ImageExportDir.AddressOfNames,
                LastRvaSection);

            if (TempPtr == IntPtr.Zero)
            {
                return(false);
            }

            ArrayList oMethodsNames = new ArrayList();

            IntPtr StringPtr;
            string sMethodName;

            for (int i = 0; i < ImageExportDir.NumberOfNames; i++)
            {
                if (TempPtr == IntPtr.Zero)
                {
                    continue;
                }

                StringPtr = ImageRvaToVa(
                    ImageNTHeadersAddr,
                    PEBaseAddr,
                    (uint)Marshal.ReadInt32(TempPtr),
                    LastRvaSection);

                sMethodName = Marshal.PtrToStringAnsi(StringPtr);

                if (sMethodName != String.Empty)
                {
                    oMethodsNames.Add(sMethodName);
                }

                TempPtr = new IntPtr(TempPtr.ToInt32() + Marshal.SizeOf(typeof(IntPtr)));
            }

            ExportedMethodsNames = (string[])oMethodsNames.ToArray(typeof(string));

            return(true);
        }