2012-04-05 2 views
1

Мой проект должен проверять файлы .c и .dll. он объединяет эти сведения для определения того, что он должен назвать, а затем вызывает это.Программно считывание вызываемых DLL-функций

Мне нужно проверить DLL, чтобы найти, какая DLL имеет какую функцию. Я дошел до того, что сопоставил dll в памяти, не инициализируя его. теперь мне нужно сопоставить заголовок с чем-то, чтобы я мог прочитать раздел, в котором есть вызываемые имена.

как я могу это сделать? это код до сих пор:

[DllImport("kernel32.dll")] 
    static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); 

    public static string[] GetFKTNames(string dll) 
    { 
     IntPtr lib = LoadLibraryEx(dll, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); 

     //INDICATES WHAT I WANT TO DO, BUT DOES NOT WORk 
     //Header header = GetHeader(lib); 
     //Unload(lib); 
     //return header.Names; 
} 

EDIT # 2:

я сделал немного прогресса и бросить его на сегодняшний день ... есть 4 свободных дней, приезжающие сюда в германии ...

Я не совсем уверен, правильно ли это сортировка - у меня не было возможности проверить его. Я хотел бы прочитать книгу по этой теме - так что прокомментируйте, если вы знаете хорошую книгу, в которой объясняется, как работает этот заголовок и какие разные заголовки есть.

private static List<string> ListDLLFunctions(string sADllName) 
    { 
     List<string> names = new List<string>(); 
     IntPtr LoadedImage = LoadLibraryEx(sADllName, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); 

     IMAGE_NT_HEADERS header = (IMAGE_NT_HEADERS) Marshal.PtrToStructure(libPtr, typeof(IMAGE_NT_HEADERS)); 

     // ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*) 
     //  ImageDirectoryEntryToData(LoadedImage.MappedAddress, 
     //  false, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize); 
     // if (ImageExportDirectory != NULL) 
     // { 
     //  dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader, 
     //   LoadedImage.MappedAddress, 
     //  ImageExportDirectory->AddressOfNames, NULL); 
     //  for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++) 
     //  { 
     //   sName = (char *)ImageRvaToVa(LoadedImage.FileHeader, 
     //     LoadedImage.MappedAddress, 
     //     dNameRVAs[i], NULL); 
     //   slListOfDllFunctions.push_back(sName); 
     //  } 
     // } 
     FreeLibrary(LoadedImage); 
     return names; 
    } 

    static void Main(string[] args) 
    { 
     List<string> names = ListDLLFunctions("KERNEL32.DLL"); 
    } 

ответ

0

Я решил проблему для моего USECASE:

загружаю Либерал в Momory, скопируйте его в ByteArray, а затем исследовать его с помощью информации PE ,

Есть несколько полезных RESSOURCES для этой темы, которые помогли мне много:

В ретроспективе я понимаю, как я мог использовать другие подходы для получения моей информации. Класс, который я написал, отлично изучает PE и исследует некоторые DLL, я рекомендую переписать его, если вы хотите понять, как работает PE.

Вот Класс:

public class DLLHelper 
{ 
    private byte[] dllInMemory; 
    private UInt32 PESizeOfImage; 
    private UInt32 VA_PE; 

    [DllImport("kernel32.dll")] 
    static public extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); 

    [DllImport("kernel32.dll")] 
    static public extern bool FreeLibrary(IntPtr hModule); 

    public enum LoadLibraryFlags : uint 
    { 
     DONT_RESOLVE_DLL_REFERENCES = 0x00000001, 
     LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, 
     LOAD_LIBRARY_AS_DATAFILE = 0x00000002, 
     LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, 
     LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, 
     LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 
    } 


    public DLLHelper(string dllpath) 
    { 
     PESizeOfImage = GetDllSizeInMemory(dllpath); 
     dllInMemory = GetDLLCopy(dllpath, PESizeOfImage); 
     UInt32 VA_p_PE = 0x3C; 
     VA_PE = Get4ByteFromLocation(VA_p_PE, dllInMemory); 
    } 

    private byte[] GetDLLCopy(string dllpath, uint PESizeOfImage) 
    { 
     IntPtr libPtr = LoadLibraryEx(dllpath, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); 
     byte[] dllInMemory = new byte[PESizeOfImage]; 
     Marshal.Copy(libPtr, dllInMemory, 0, (int)PESizeOfImage); 
     FreeLibrary(libPtr); 
     return dllInMemory; 
    } 

    private UInt32 GetDllSizeInMemory(string dllpath) 
    { 
     byte[] dllpreload = File.ReadAllBytes(dllpath); 
     UInt32 pp_PE = 0x3C; 
     UInt32 p_PE = Get4ByteFromLocation(pp_PE, dllpreload); 
     UInt32 p_PEOPTIONALHEADER = p_PE + 0x18; 
     UInt32 p_PESizeOfImage = p_PEOPTIONALHEADER + 0x38; 
     return Get4ByteFromLocation(p_PESizeOfImage, dllpreload); 
    } 

    public void DumpToFile(String filename) 
    { 
     File.WriteAllBytes(filename, dllInMemory); 
    } 

    public string GetDLLName() 
    { 
     UInt32 VAExport = GetVAExport(VA_PE, dllInMemory); 
     UInt32 VAName = GetVAName(VAExport, dllInMemory); 
     String Name = GetString(VAName, dllInMemory); 
     return Name; 
    } 

    public List<String> GetFunctionNames() 
    { 
     List<String> fkts = new List<String>(); 
     UInt32 VAExport = GetVAExport(VA_PE, dllInMemory); 
     UInt32 VA_p_firstFKT = GetVA_p_firstFKT(VAExport, dllInMemory); 
     UInt32 VA_p_lastFKT = GetVA_p_lastFKT(VAExport, dllInMemory); 
     for (UInt32 VA_p_fkt = VA_p_firstFKT; VA_p_fkt <= VA_p_lastFKT; VA_p_fkt += sizeof(UInt32)) 
     { 
      UInt32 VA_fkt = Get4ByteFromLocation(VA_p_fkt, dllInMemory); 
      fkts.Add(GetString(VA_fkt, dllInMemory)); 
     } 
     return fkts; 
    } 

    private UInt32 GetVA_p_lastFKT(UInt32 VAExport, byte[] dllInMemory) 
    { 
     UInt32 first = GetVA_p_firstFKT(VAExport, dllInMemory); 
     UInt32 count = GetfktCount(VAExport, dllInMemory); 
     UInt32 last = first + (count - 1) * sizeof(UInt32); 
     return last; 
    } 

    private UInt32 GetfktCount(UInt32 VAExport, byte[] dllInMemory) 
    { 
     UInt32 RVA_Count = 0x14; 
     UInt32 VA_Count = VAExport + RVA_Count; 
     return Get4ByteFromLocation(VA_Count, dllInMemory); 
    } 

    private UInt32 GetVA_p_firstFKT(UInt32 VAExport, byte[] dllInMemory) 
    { 
     UInt32 RVA_p_FIRST = 0x20; 
     UInt32 VA_p_FIRST = VAExport + RVA_p_FIRST; 
     return Get4ByteFromLocation(VA_p_FIRST, dllInMemory); 
    } 

    private UInt32 GetVAName(UInt32 VAExport, byte[] dllInMemory) 
    { 
     UInt32 RVA_p_NAME = 0x0C; 
     UInt32 VA_p_NAME = VAExport + RVA_p_NAME; 
     return Get4ByteFromLocation(VA_p_NAME, dllInMemory); 
    } 

    private UInt32 GetVAExport(UInt32 VAPE, byte[] dllInMemory) 
    { 
     UInt32 RVA_p_EXPORT = 0x78; 
     UInt32 VA_p_EXPORT = VAPE + RVA_p_EXPORT; 
     return Get4ByteFromLocation(VA_p_EXPORT, dllInMemory); 
    } 

    string GetString(UInt32 location, byte[] dll) 
    { 
     int length = 0; 
     while (dll[location + length] != 0x00) 
     { 
      length++; 
     } 
     if (location > int.MaxValue) throw new Exception("uncastable"); 
     return Encoding.UTF8.GetString(dll, (int)location, length); 
    } 

    private UInt32 Get4ByteFromLocation(UInt32 location, byte[] dll) 
    { 
     if (!(BitConverter.IsLittleEndian)) 
     { 
      byte[] partial = GetByteSubset(4, location, dll); 
      Array.Reverse(partial); 
      return BitConverter.ToUInt32(partial, 0); 
     } 
     return BitConverter.ToUInt32(dll, (int)location); 
    } 

    private byte[] GetByteSubset(int size, UInt32 location, byte[] dll) 
    { 
     byte[] val = new byte[size]; 
     for (int i = 0; i < size; i++) 
     { 
      val[i] = dll[location + i]; 
     } 
     return val; 
    } 
} 
+0

После использования этой функции для нескольких небольших проектов я столкнулся с проблемой, что не все DLL-файлы могут быть удалены таким образом. У меня были проблемы, просто используя два разных компилятора ... так что предстоит большая работа ... но я изменю свой подход к основной проблеме. – Johannes

0

Non из кода, но с консоли я обычно использую

DumpBin утилиты, чтобы увидеть экспорт DLL файлов.

Я думаю, вы можете использовать этот инструмент с помощью Process.Start(..) и проанализировать его вывод, чтобы получить необходимую информацию.

Надеюсь, это поможет.

+0

это может помочь в некоторых случаях, но я не хочу иметь дело с вызовом других исполняемых файлов из моей программы. я должен убедиться, что он установлен на всех целевых машинах вместе со своими зависимостями ... на моей машине он говорит, что ему не хватает dll smoe и вообще не запускается. – Johannes

+0

@Johannes: до сих пор я не встречал машину, где ее нет. Вы можете попытаться сделать его частью вашей программы. – Tigran

+0

У меня есть его здесь: C: \ Program Files \ Microsoft Visual Studio 10.0 \ VC \ bin, и он не запускается из-за некоторой DLL. Я нахожусь в довольно большой компании - установка чего-либо на самом деле не вариант. – Johannes

1

Не существует функции «одного вызова», которая может сделать это за вас. Вам нужно загрузить DLL и искать имена в таблице экспорта.

There is a post with some code to do it in c++ - может быть, вы можете попробовать портировать его на C#

+0

Я не думаю, что у меня есть все навыки, необходимые для этого, но я дам ему шанс. – Johannes

Смежные вопросы