Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Аналог DumpBin

Delphi , Файловая система , DLL и PlugIns

Иногда на форуме проскакивает такой вопрос: "Как можно поглядеть экспортируемые ф-ии какой либо длл'ины?". Можно конечно же воспользоваться стандартными утилитами, но можно попробовать написать и что нить свое. Сейчас я попробую показать такой пример. Напишем пример, который делает именно это - вытаскивает экспорт модуля. Подробно расписывать тут ничего не буду, тут идет разбор элементов PE заголовка - нахождение таблицы экспорта, перечисление ф-ий. Недостаток этого примера в том, что он работает уже с подгруженными модулями, т.к. для нахождения базы используется GetModuleHandle().

Вставка:

The GetModuleHandle function returns a module handle for the specified module if the file has been mapped into the address space of the calling process.

Для расширения возможностей - простмотра всех модулей, надо использовать что нить другое, например "мэпирование" (CreateFileMapping() итд). Ведь надо хоть что нить самому сделать....

Code:

program ExpDump;
 
uses windows;
 
var
   ImageBase : DWord;
   DosHeader : PImageDosHeader;
   PeHeader  : PImageNtHeaders;
   PExport   : PImageExportDirectory;
   pname     : PDWord;
   name      : PChar;
   i         : Integer;
   cmdline   : string;
 
//#### ?-??: ????? ? ????
function Dump(const log: PChar): boolean;
Var hFile     : THandle;
   dwError   : DWord;
   dwWritten : DWord;
   buffer    : PChar;
begin
hFile := CreateFile(PChar(cmdline + '_fexport.txt'), GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile = INVALID_HANDLE_VALUE) then begin
result := FALSE;
exit;
end;
 
dwError := SetFilePointer(hFile, 0, nil, FILE_END);
if (dwError = $FFFFFFFF) then begin
CloseHandle(hFile);
result := FALSE;
exit;
end;
 
buffer := PChar(log + #13#10);
WriteFile(hFile, buffer^, length(buffer), dwWritten, nil);
if (dwWritten < DWord(length(buffer))) then begin
CloseHandle(hFile);
result := FALSE;
exit;
end;
CloseHandle(hFile);
result := TRUE;
end;
//####
 
//#### Start
begin
if (ParamCount < 1) then halt(0) else cmdline := ParamStr(1);
 
ImageBase := GetModuleHandle(PChar(cmdline));
if (ImageBase = 0) then begin
   MessageBox(0, 'Error Load Module', 'Error', MB_OK);
   halt(0);
end;
 
DosHeader := PImageDosHeader(ImageBase);
if (DosHeader^.e_magic <> IMAGE_DOS_SIGNATURE) then begin
   MessageBox(0,'Error Dos Header','Error',MB_OK);
   halt(0);
end;
 
PEHeader := PImageNtHeaders(DWord(ImageBase) + DWord(DosHeader^._lfanew));
if (PEHeader^.Signature <> IMAGE_NT_SIGNATURE) then begin
   MessageBox(0,'Error PE Header', 'Error', MB_OK);
   halt(0);
end;
 
PExport := PImageExportDirectory(ImageBase + DWord(PEHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
pname   := PDWord(ImageBase + DWord(PExport^.AddressOfNames));
 
 
Dump(PChar('Programm ExpDump =)'));
Dump(PChar(cmdline + ' functions:'));
Dump(PChar(#13#10));
 
For i := 0 to PExport^.NumberOfNames - 1 do begin
 name := PChar(PDWord(DWord(ImageBase)  + PDword(pname)^));
 if (not Dump(name)) then halt(0);
  inc(pname);
end;
end.
//#### End

Пример использования:

ExpDump.Exe User32.dll

В рехультате:

Programm ExpDump =)
user32.dll functions:
 
 
ActivateKeyboardLayout
AdjustWindowRect
AdjustWindowRectEx
AlignRects
AllowForegroundActivation
AllowSetForegroundWindow
AnimateWindow
AnyPopup
AppendMenuA
AppendMenuW
ArrangeIconicWindows
AttachThreadInput
BeginDeferWindowPos
BeginPaint
BlockInput

...

Для улучшения можно доделать так:

Code:

ImageBase := GetModuleHandle(PChar(cmdline));
if (ImageBase = 0) then begin
   ImageBase := LoadLibrary(PChar(cmdline));
   if (ImageBase = 0) then begin
    MessageBox(0, 'Error Load Module', 'Error', MB_OK);
    halt(0);
   end;
end;

И не забудте в конце FreeLibrary()

Автор x2er0

Взято из http://forum.sources.ru

Here's the translation of the content into Russian:

Неприятный вопрос "экспортировать функции из DLL"!

Ваш пример - хороший старт, но он имеет некоторые ограничения. Вы только загружаете модули, которые уже были загружены в процесс, что означает, что вы не сможете дампить экспорты из DLL, которые еще не были загружены.

Чтобы преодолеть это ограничение, можно использовать функцию LoadLibrary для загрузки DLL в память и затем использовать GetModuleHandle для получения ее модульного хэндла. Это позволит вам дампить экспорты из любого DLL, даже если он еще не был загружен.

Вот обновленная версия вашего кода, которая включает эти изменения:

program ExpDump;
uses
  Windows;

var
  ImageBase: DWord;
  DosHeader: PImageDosHeader;
  PeHeader: PImageNtHeaders;
  PExport: PImageExportDirectory;
  pname: PDWord;
  name: PChar;
  i: Integer;
  cmdline: string;

function Dump(const log: PChar): boolean;
var
  hFile: THandle;
  dwError: DWord;
  dwWritten: DWord;
  buffer: PChar;
begin
   // ... (rest of the function remains the same)
end;

begin
  if ParamCount < 1 then halt(0) else cmdline := ParamStr(1);

  ImageBase := LoadLibrary(PChar(cmdline));
  if ImageBase = 0 then begin
    MessageBox(0, 'Ошибка загрузки модуля', 'Ошибка', MB_OK);
    halt(0);
  end;

  DosHeader := PImageDosHeader(ImageBase);
  if DosHeader^.e_magic <> IMAGE_DOS_SIGNATURE then begin
    MessageBox(0, 'Ошибка DOS-галереи', 'Ошибка', MB_OK);
    halt(0);
  end;

  PeHeader := PImageNtHeaders(DWord(ImageBase) + DWord(DosHeader^._lfanew));
  if PeHeader^.Signature <> IMAGE_NT_SIGNATURE then begin
    MessageBox(0, 'Ошибка PE-галереи', 'Ошибка', MB_OK);
    halt(0);
  end;

  PExport := PImageExportDirectory(ImageBase + DWord(PeHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
  pname := PDWord(ImageBase + DWord(PExport^.AddressOfNames));

  Dump(PChar('Программа ExpDump =)'));
  Dump(PChar(cmdline + ' функции:'));
  Dump(PChar(#13#10));

  for i := 0 to PExport^.NumberOfNames - 1 do begin
    name := PChar(PDWord(DWord(ImageBase) + PDword(pname)^));
    if not Dump(name) then halt(0);
    inc(pname);
  end;

  FreeLibrary(ImageBase); // Не забудьте освободить библиотеку!
end.

С этой обновленной кодом вы должны сможете дампить экспорты из любого DLL, даже если он еще не был загружен. Помните только вызвать FreeLibrary после использования DLL для освобождения ее ресурсов.

Что касается улучшения кода, я бы предложил добавить механизмы обработки ошибок и журналирования для сделать его более robust и легче отлаживать. Вы также можете рассмотреть использование более эффективного метода дампа экспортов, например, используя хеш-таблицу или массив для хранения имен функций и адресов.

Написанный программистом пример Delphi-приложения, которое позволяет вытаскивать и выводить экспортируемые функции из динамически загруженной DLL.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: DLL и PlugIns ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-04-09 16:07:26/0.0061089992523193/1