Список функций из DLL AddressOfNames

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

В структуре IMAGE_DIRECTORY_ENTRY_EXPORT есть ссылки на три массива. Один из этих массивов ссылается на данные с именами функций:

typedef struct _IMAGE_EXPORT_DIRECTORY 
{
......
DWORD AddressOfFunctions;
DWORD AddressOfNames; // массив указателей на имена функций
DWORD AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

Итак, сейчас давайте создадим программу, которая будет выводить в файл список всех функций из модуля user32.dll. Сначала создадим ссылку на библиотеку работы с потоками:

// TestAPI.cpp : Defines the entry point for the application.
//


#include "stdafx.h"
#include "fstream.h"
.......

А теперь новый код:

	......
PIMAGE_EXPORT_DIRECTORY pImportDesc=NULL;
pImportDesc = MakePtr(PIMAGE_EXPORT_DIRECTORY,hUser32,
pPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);


PCSTR *l_ppszName = MakePtr(PCSTR*,pImportDesc->AddressOfNames, hUser32);
DWORD x=pImportDesc->NumberOfNames;

ofstream ofs("rez.txt");

for (DWORD i=0;i<x;i++)
{
char *p=MakePtr(char*,*l_ppszName,hUser32);
ofs << p << endl;
l_ppszName++;
}

ofs.close();

return TRUE;
}

Кстати эта программа тестировалась как на Windows 98, так и на Windows 2000. Были получены интересные выводы, которые я расскажу в следующем шаге. Ниже я приведу полный код программы, так как долго дописывал кусочки и Вы могли запутаться. Если Вы начали смотреть с этого шага, то прочитайте все предыдущие для лучшего понимания. Результат работы будет в файле rez.txt:

ActivateKeyboardLayout
AdjustWindowRect
AdjustWindowRectEx
AlignRects
AnimateWindow
AnyPopup
AppendMenuA
AppendMenuW
ArrangeIconicWindows
AttachThreadInput
......

Ну и полный код

// TestAPI.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "fstream.h"

#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + ((PIMAGE_DOS_HEADER)a)->e_lfanew))
#define MakePtr(Type, Base, Offset) ((Type)(DWORD(Base) + (DWORD)(Offset)))

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HMODULE hUser32=NULL;
hUser32=GetModuleHandle("user32");
if (hUser32==NULL)
{
MessageBox(NULL,"Error Load User32","Error",MB_OK);
return FALSE;
}

PIMAGE_DOS_HEADER pDOSHead;
pDOSHead = (PIMAGE_DOS_HEADER)hUser32;

if ( pDOSHead->e_magic != IMAGE_DOS_SIGNATURE )
{
MessageBox(NULL,"Error Dos Header signature MZ","Error",MB_OK);
return FALSE;
}

PIMAGE_NT_HEADERS pPEHeader;
pPEHeader=(PIMAGE_NT_HEADERS) NTSIGNATURE(pDOSHead);

if ( pPEHeader->Signature != IMAGE_NT_SIGNATURE )
{
MessageBox(NULL,"Error PE Header signature PE","Error",MB_OK);
return FALSE;
}

IMAGE_FILE_HEADER FileHeader;
FileHeader=(IMAGE_FILE_HEADER) pPEHeader->FileHeader;

if (FileHeader.Machine!=IMAGE_FILE_MACHINE_I386)
{
MessageBox(NULL,"Error Not 386 Proccesor","Error",MB_OK);
return FALSE;
}

IMAGE_OPTIONAL_HEADER32 OptionHeader;
OptionHeader=(IMAGE_OPTIONAL_HEADER32) pPEHeader->OptionalHeader;

PIMAGE_EXPORT_DIRECTORY pImportDesc=NULL;
pImportDesc = MakePtr(PIMAGE_EXPORT_DIRECTORY,hUser32,
pPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

PCSTR *l_ppszName = MakePtr(PCSTR*,pImportDesc->AddressOfNames, hUser32);
DWORD x=pImportDesc->NumberOfNames;

ofstream ofs("rez.txt");
for (DWORD i=0;i<x;i++)
{
char *p=MakePtr(char*,*l_ppszName,hUser32);
ofs << p << endl;
l_ppszName++;
}
ofs.close();
return TRUE;
}