Шаг 28 - Список функций из 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;
}

Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем.