读取dll导出的函数名

本文详细介绍了如何在C++中读取DLL文件的导出函数名和地址,包括使用`RvaToOffset`函数定位函数信息和`IMAGE_EXPORT_DIRECTORY`的数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读取dll导出的函数名

导出库代码

struct TEa {

};

extern "C"
{
    DLLDEMO_EXPORTS_EXPORT void hello(){}
    DLLDEMO_EXPORTS_EXPORT void hello1() {}
	DLLDEMO_EXPORTS_EXPORT void hello2() {}
	DLLDEMO_EXPORTS_EXPORT void ver(int a) {}
    DLLDEMO_EXPORTS_EXPORT void ver6(TEa s) {}
	DLLDEMO_EXPORTS_EXPORT void vers(void* s) {}
}
class DLLDEMO_EXPORTS_EXPORT AA {
public:
    AA(){}
    ~AA(){}
	 void ver(int s) {}
	 void ver(char s) {}

};

运行结果
输出dll函数
depends展示
depends显示导出的接口
测试代码

// PaserDll.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <windows.h>

DWORD RvaToOffset(IMAGE_NT_HEADERS* pNtHdr, DWORD dwRva) {

	// 1. 找Rva所在的区段
	// 2. 用Rva减去所在区段的首Rva ,再用减出来的差,加上所在
	//    区段的首区段偏移
	IMAGE_SECTION_HEADER* pSechdr = NULL;
	pSechdr = IMAGE_FIRST_SECTION(pNtHdr);
	for (int i = 0; i < pNtHdr->FileHeader.NumberOfSections; ++i) {
		if (dwRva >= pSechdr[i].VirtualAddress
			&& dwRva <= pSechdr[i].VirtualAddress + pSechdr[i].SizeOfRawData) {

			dwRva -= pSechdr[i].VirtualAddress;
			dwRva += pSechdr[i].PointerToRawData;
			return dwRva;
		}
	}
	return -1;
}

BOOL CheckFunction(PCHAR pf)
{
	int iCount = strlen(pf);

	for (int i = 0; i < iCount; i++)
	{
		if ((pf[i] < '0') || (pf[i] > 'z')) return FALSE;
	}
	return TRUE;
}

int main(int argc, char* argv[])
{

	if (argc >= 2)
	{
		std::cout << std::string() << std::endl;
		std::string ss = argv[1];
		HANDLE fileHandle = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (INVALID_HANDLE_VALUE != fileHandle)
		{
			DWORD dwFileSize = GetFileSize(fileHandle, NULL);

			char* buffer = new char[dwFileSize];
			unsigned long readBytes = 0;

			if (!ReadFile(fileHandle, buffer, dwFileSize, &readBytes, NULL))
			{
				std::cerr << "read file error" << GetLastError() << std::endl;
			}
			CloseHandle(fileHandle);

			IMAGE_DOS_HEADER* dosHeader = NULL;
			dosHeader = (IMAGE_DOS_HEADER*)buffer;

			if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
			{
				std::cout << "read IMAGE_DOS_HEADER::e_magic errror " << std::endl;
				return 0;
			}


			IMAGE_NT_HEADERS* neHeaders = NULL;
			neHeaders = (IMAGE_NT_HEADERS*)(buffer + dosHeader->e_lfanew);

			if (neHeaders->Signature != IMAGE_NT_SIGNATURE)
			{
				std::cout << "read IMAGE_NT_HEADERS::Signature errror " << std::endl;
				return 0;
			}

			IMAGE_OPTIONAL_HEADER64 optionHead = neHeaders->OptionalHeader;
			IMAGE_DATA_DIRECTORY exportTableDe = optionHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

			IMAGE_EXPORT_DIRECTORY* pExortTable = NULL;
			int dwImpOfs = RvaToOffset(neHeaders, exportTableDe.VirtualAddress);
			pExortTable = (IMAGE_EXPORT_DIRECTORY*)(dwImpOfs + (ULONG_PTR)dosHeader);
			ULONG_PTR dwNameOfs = RvaToOffset(neHeaders, pExortTable->Name);

			char* pName = nullptr;
			pName = (char*)(dwNameOfs + (ULONG_PTR)dosHeader);
			std::cout << "动态库名称:" << std::string(pName) << std::endl;

			ULONG_PTR addresNames = RvaToOffset(neHeaders, pExortTable->AddressOfNames);
			PDWORD  nn = (PDWORD)(addresNames + (ULONG_PTR)dosHeader);
			
			for (int i = 0;i < pExortTable->NumberOfNames;++i)
			{
				ULONG_PTR n1 = RvaToOffset(neHeaders, nn[i]);
				char* n1Name = nullptr;
				n1Name = (char*)(n1 + (ULONG_PTR)dosHeader);

// 				if (IsBadReadPtr(n1Name, 1)) 
// 					continue;
// 				if ((!IsCharAlpha(n1Name[0])) && (!IsCharAlphaNumeric(n1Name[0]))) 
// 					continue;
// 				if (IsBadCodePtr((FARPROC)n1Name)) 
// 					continue;
// 				if (!CheckFunction(n1Name)) 
// 					continue;


				std::cout << "函数名称 :" << i << "," << std::string(n1Name) << std::endl;
			}
			

		}
		else {
			std::cout << GetLastError() << std::endl;
		}
	}

	std::cout << "Hello World!\n";
 }


// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件


/*


#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include <tchar.h>
#include <imagehlp.h>

void PrintUsage(char* msg)
{
	printf("|---------------------------------------------------------|\n");
	printf("| CreateDate: 2000-02-15 |\n");
	printf("| Usage: <Path>\\GetFunction[.exe] <Exe file|DLL file> |\n");
	printf("|---------------------------------------------------------|\n");
	return;
}

BOOL CheckFunction(PCHAR pf)
{
	int iCount = strlen(pf);

	for (int i = 0; i < iCount; i++)
	{
		if ((pf[i] < '0') || (pf[i] > 'z')) return FALSE;
	}
	return TRUE;
}
//需要附加  Imagehlp.lib 
int main(int argc, char** argv)
{
	PIMAGE_NT_HEADERS nt_headers;
	PIMAGE_EXPORT_DIRECTORY export_data;
	DWORD export_data_size;
	PDWORD FunctionsNames, FunctionsPtrs;
	PWORD NameOrdinals;
	HANDLE hFile, hFileMap;
	DWORD file_attributes;
	PVOID mod_base, func_ptr = 0, image_base;
	char file_path[MAX_PATH];
	char* func_name;
	LPWIN32_FIND_DATA lpwfd_first = new WIN32_FIND_DATA;
	DWORD i, dwretcode;
	char* lpTmp = new char[MAX_PATH];
	BOOLEAN bcp = FALSE;

	if (argc < 2)
	{
		PrintUsage(argv[0]);
		return 0;
	}

	// GetFullPathName (argv[1],MAX_PATH,file_path ,NULL);
	sprintf(file_path, argv[1]);

	if (FindFirstFile(file_path, lpwfd_first) == NULL)
	{
		//file_attributes=0;
		PrintUsage(argv[0]);
		return 0;
	}
	else
	{
		file_attributes = lpwfd_first->dwFileAttributes;
	}
goto_continue:
	hFile = CreateFile(file_path, GENERIC_READ,
		0, 0, OPEN_EXISTING,
		file_attributes, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		dwretcode = GetLastError();
		if (dwretcode == 32)
		{
			bcp = TRUE;
			sprintf(lpTmp, argv[0]);
			lpTmp[(strrchr(argv[0], 92) - argv[0]) + 1] = NULL;
			sprintf(lpTmp + strlen(lpTmp), lpwfd_first->cFileName);
			CopyFile(argv[1], lpTmp, TRUE);
			sprintf(file_path, lpTmp);
			delete lpTmp;
			goto goto_continue;
		}
		else return 0;
	}

	delete lpwfd_first;

	hFileMap = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);
	if (hFileMap == NULL)
	{
		printf("Create File Map Error!\n");
		CloseHandle(hFile);
		return 0;
	}
	mod_base = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
	if (mod_base == NULL)
	{
		printf("Create MapView of file error!\n");
		CloseHandle(hFileMap);
		CloseHandle(hFile);
		return 0;
	}
	nt_headers = ImageNtHeader(mod_base);
	image_base = (PVOID)nt_headers->OptionalHeader.ImageBase;

	export_data = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(mod_base,
		FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &export_data_size);
	if (export_data == NULL)
	{
		DWORD dwError = GetLastError();
		printf("ImageDirectoryEntryToData Error!(Errorcode:%d)\n", dwError);
		return 0;
	}
	FunctionsNames = (PDWORD)ImageRvaToVa(nt_headers, mod_base,
		(DWORD)export_data->AddressOfNames, 0);
	FunctionsPtrs = (PDWORD)ImageRvaToVa(nt_headers, mod_base,
		(DWORD)export_data->AddressOfFunctions, 0);
	NameOrdinals = (PWORD)ImageRvaToVa(nt_headers, mod_base,
		(DWORD)export_data->AddressOfNameOrdinals, 0);

	printf("Order FunctionName FunctionAddress\n");
	for (i = 0; i < export_data->NumberOfFunctions; i++)
	{
		func_name = (PCHAR)ImageRvaToVa(nt_headers, mod_base, (DWORD)FunctionsNames[i], 0);
		if (IsBadReadPtr(func_name, 1)) continue;
		if ((!IsCharAlpha(func_name[0])) && (!IsCharAlphaNumeric(func_name[0]))) continue;
		if (IsBadCodePtr((FARPROC)func_name)) continue;
		if (!CheckFunction(func_name)) continue;
		if (strlen(func_name) > 32) continue;
		// func_ptr=NULL;
	   // if (IsBadReadPtr(&FunctionsPtrs[NameOrdinals[i]],1)) continue;
	   // if (NameOrdinals[i]>10000) continue;

		func_ptr = (PVOID)FunctionsPtrs[NameOrdinals[i]];
		printf("%d", i);
		char* temp = new char[10];
		sprintf(temp, "%d", i);
		for (int w = 0; w < (18 - (int)strlen(temp)); w++)
			printf(" ");
		printf("%s", func_name);
		for (int j = 0; j < (50 - (int)strlen(func_name)); j++)
			printf(" ");
		printf("%d\n", func_ptr);
	}

	UnmapViewOfFile(mod_base);
	CloseHandle(hFileMap);
	CloseHandle(hFile);
	if (bcp)
		DeleteFile(file_path);
	return 0;
}
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跑过那座山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值