通过导出表和函数名 获取特定进程下模块的导出函数地址

ring3下:

需要的头文件:

#include<windows.h>
#include<iostream>
#include<Psapi.h>
using namespace std;

获取进程下的模块基址:

PVOID GetProcessMoudleBase(HANDLE hProcess, char* moduleName)
{
	// 遍历进程模块,
	HMODULE hModule[100] = { 0 };
	DWORD dwRet = 0;
	BOOL bRet = ::EnumProcessModules(hProcess, (HMODULE*)(hModule), sizeof(hModule), &dwRet);
	if (FALSE == bRet)
	{
		::CloseHandle(hProcess);
		return NULL;
	}
	char name[50] = { 0 };
	for (int i = 0; i < dwRet; i++)
	{
		GetModuleBaseNameA(hProcess, hModule[i], name, 50);

		if (!_stricmp(moduleName, name))
		{
			cout << name << "     Addr:" << hex << hModule[i] <<endl;
			return hModule[i];
		}
	}

	::CloseHandle(hProcess);
	return NULL;
}

通过函数名获取函数地址(要改成64位只需要将IMAGE_OPTIONAL_HEADER改成MAGE_OPTIONAL_HEADER64):

UINT64 GetFunAddrByName32(HANDLE hProcess,char* ModName, char* FunName)
{
	HANDLE hMod;
	PVOID BaseAddress = NULL;
	IMAGE_DOS_HEADER dosheader;
	IMAGE_OPTIONAL_HEADER opthdr;//IMAGE_OPTIONAL_HEADER64
	IMAGE_EXPORT_DIRECTORY exports;
	USHORT index = 0;
	ULONG addr, i;
	char pFuncName[30] = {0};
	PULONG pAddressOfFunctions;
	PULONG pAddressOfNames;
	PUSHORT pAddressOfNameOrdinals;

	//获取模块基址
	BaseAddress = GetProcessMoudleBase(hProcess,ModName);
	if (!BaseAddress) return 0;

	//获取PE头
	hMod = BaseAddress;
	ReadProcessMemory(hProcess, hMod, &dosheader, sizeof(IMAGE_DOS_HEADER), 0);
	ReadProcessMemory(hProcess, (BYTE*)hMod + dosheader.e_lfanew + 24, &opthdr, sizeof(IMAGE_OPTIONAL_HEADER), 0);
	//ReadProcessMemory(hProcess, (BYTE*)hMod + dosheader.e_lfanew + 24, &opthdr, sizeof(IMAGE_OPTIONAL_HEADER64), 0);

	//查找导出表 
	ReadProcessMemory(hProcess, ((BYTE*)hMod + opthdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), &exports, sizeof(IMAGE_EXPORT_DIRECTORY), 0);

	pAddressOfFunctions = (ULONG*)((BYTE*)hMod + exports.AddressOfFunctions);
	pAddressOfNames = (ULONG*)((BYTE*)hMod + exports.AddressOfNames);
	pAddressOfNameOrdinals = (USHORT*)((BYTE*)hMod + exports.AddressOfNameOrdinals);

	//对比函数名 
	for (i = 0; i < exports.NumberOfNames; i++)
	{
		ReadProcessMemory(hProcess, pAddressOfNameOrdinals + i, &index, sizeof(USHORT), 0);
		ReadProcessMemory(hProcess, pAddressOfFunctions + index, &addr, sizeof(ULONG), 0);

		ULONG a = 0;
		ReadProcessMemory(hProcess, pAddressOfNames + i, &a, sizeof(ULONG), 0);
		ReadProcessMemory(hProcess, (BYTE*)hMod + a, pFuncName, 30, 0);
		ReadProcessMemory(hProcess, pAddressOfFunctions + index, &addr, sizeof(ULONG), 0);

		if (!_stricmp(pFuncName, FunName))
		{
			UINT64 funAddr = (UINT64)BaseAddress + addr;
			cout << pFuncName << "   " << hex << funAddr << endl;
			return funAddr;
		}
	}
	return 0;
}

ring0下 (获取模块基质请参考:获取模块基质):

需要的头文件及结构体:

#include<ntifs.h>
#include<windef.h>

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
	WORD   e_magic;                     // Magic number
	WORD   e_cblp;                      // Bytes on last page of file
	WORD   e_cp;                        // Pages in file
	WORD   e_crlc;                      // Relocations
	WORD   e_cparhdr;                   // Size of header in paragraphs
	WORD   e_minalloc;                  // Minimum extra paragraphs needed
	WORD   e_maxalloc;                  // Maximum extra paragraphs needed
	WORD   e_ss;                        // Initial (relative) SS value
	WORD   e_sp;                        // Initial SP value
	WORD   e_csum;                      // Checksum
	WORD   e_ip;                        // Initial IP value
	WORD   e_cs;                        // Initial (relative) CS value
	WORD   e_lfarlc;                    // File address of relocation table
	WORD   e_ovno;                      // Overlay number
	WORD   e_res[4];                    // Reserved words
	WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
	WORD   e_oeminfo;                   // OEM information; e_oemid specific
	WORD   e_res2[10];                  // Reserved words
	LONG   e_lfanew;                    // File address of new exe header
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;

typedef struct _IMAGE_DATA_DIRECTORY {
	DWORD   VirtualAddress;
	DWORD   Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

typedef struct _IMAGE_OPTIONAL_HEADER64 {
	WORD        Magic;
	BYTE        MajorLinkerVersion;
	BYTE        MinorLinkerVersion;
	DWORD       SizeOfCode;
	DWORD       SizeOfInitializedData;
	DWORD       SizeOfUninitializedData;
	DWORD       AddressOfEntryPoint;
	DWORD       BaseOfCode;
	ULONGLONG   ImageBase;
	DWORD       SectionAlignment;
	DWORD       FileAlignment;
	WORD        MajorOperatingSystemVersion;
	WORD        MinorOperatingSystemVersion;
	WORD        MajorImageVersion;
	WORD        MinorImageVersion;
	WORD        MajorSubsystemVersion;
	WORD        MinorSubsystemVersion;
	DWORD       Win32VersionValue;
	DWORD       SizeOfImage;
	DWORD       SizeOfHeaders;
	DWORD       CheckSum;
	WORD        Subsystem;
	WORD        DllCharacteristics;
	ULONGLONG   SizeOfStackReserve;
	ULONGLONG   SizeOfStackCommit;
	ULONGLONG   SizeOfHeapReserve;
	ULONGLONG   SizeOfHeapCommit;
	DWORD       LoaderFlags;
	DWORD       NumberOfRvaAndSizes;
	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;

typedef struct _IMAGE_OPTIONAL_HEADER {
	//
	// Standard fields.
	//

	WORD    Magic;
	BYTE    MajorLinkerVersion;
	BYTE    MinorLinkerVersion;
	DWORD   SizeOfCode;
	DWORD   SizeOfInitializedData;
	DWORD   SizeOfUninitializedData;
	DWORD   AddressOfEntryPoint;
	DWORD   BaseOfCode;
	DWORD   BaseOfData;

	//
	// NT additional fields.
	//

	DWORD   ImageBase;
	DWORD   SectionAlignment;
	DWORD   FileAlignment;
	WORD    MajorOperatingSystemVersion;
	WORD    MinorOperatingSystemVersion;
	WORD    MajorImageVersion;
	WORD    MinorImageVersion;
	WORD    MajorSubsystemVersion;
	WORD    MinorSubsystemVersion;
	DWORD   Win32VersionValue;
	DWORD   SizeOfImage;
	DWORD   SizeOfHeaders;
	DWORD   CheckSum;
	WORD    Subsystem;
	WORD    DllCharacteristics;
	DWORD   SizeOfStackReserve;
	DWORD   SizeOfStackCommit;
	DWORD   SizeOfHeapReserve;
	DWORD   SizeOfHeapCommit;
	DWORD   LoaderFlags;
	DWORD   NumberOfRvaAndSizes;
	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;

typedef struct _IMAGE_EXPORT_DIRECTORY {
	DWORD   Characteristics;
	DWORD   TimeDateStamp;
	WORD    MajorVersion;
	WORD    MinorVersion;
	DWORD   Name;
	DWORD   Base;
	DWORD   NumberOfFunctions;
	DWORD   NumberOfNames;
	DWORD   AddressOfFunctions;     // RVA from base of image
	DWORD   AddressOfNames;         // RVA from base of image
	DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, * PIMAGE_EXPORT_DIRECTORY;

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory

代码实现:

VOID CharToWchar(PCHAR src, PWCHAR dst)
{
	UNICODE_STRING uString;
	ANSI_STRING aString;
	RtlInitAnsiString(&aString, src);
	RtlAnsiStringToUnicodeString(&uString, &aString, TRUE);  	
	wcscpy(dst, uString.Buffer);
	RtlFreeUnicodeString(&uString);
}

UINT64 GetFunAddrByName64(PEPROCESS process, char* ModName, char* FunName)
{
	USHORT index = 0;
	ULONG addr, i;
	HANDLE hMod;
	PVOID BaseAddress = NULL;
	PUCHAR pFuncName = NULL;
	UINT64 funAddr = 0;
	UNICODE_STRING str;
	wchar_t wChar[30] = { 0 };

	IMAGE_DOS_HEADER* dosheader;
	IMAGE_OPTIONAL_HEADER64* opthdr;
	PIMAGE_EXPORT_DIRECTORY exports;
	PULONG pAddressOfFunctions;
	PULONG pAddressOfNames;
	PUSHORT pAddressOfNameOrdinals;

    if (!process || !ModName || !FunName) return 0;

	CharToWchar(ModName, wChar);
	RtlInitUnicodeString(&str, wChar);
	BaseAddress = GetProcessModuleByName(process,&str);
	if (!BaseAddress) return 0;
	hMod = BaseAddress;

	KAPC_STATE ApcState;
	KeStackAttachProcess(process, &ApcState);

	dosheader = (IMAGE_DOS_HEADER*)hMod;
	opthdr = (IMAGE_OPTIONAL_HEADER64*)((BYTE*)hMod + dosheader->e_lfanew + 24);

	//查找导出表 
	exports = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)dosheader + opthdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	pAddressOfFunctions = (ULONG*)((BYTE*)hMod + exports->AddressOfFunctions);
	pAddressOfNames = (ULONG*)((BYTE*)hMod + exports->AddressOfNames);
	pAddressOfNameOrdinals = (USHORT*)((BYTE*)hMod + exports->AddressOfNameOrdinals);

	//对比函数名 
	for (i = 0; i < exports->NumberOfNames; i++)
	{
		index = pAddressOfNameOrdinals[i];
		addr = pAddressOfFunctions[index];
		pFuncName = (PUCHAR)((BYTE*)hMod + pAddressOfNames[i]);
		addr = pAddressOfFunctions[index];

		//DbgPrint("Name:%s \t Addr:%p\n", pFuncName, (UINT64)BaseAddress + addr);
		if (!strcmp((const char*)pFuncName, FunName))
		{
			funAddr = (UINT64)BaseAddress + addr;
		}
	}

	KeUnstackDetachProcess(&ApcState);
	return funAddr;
}
发布了23 篇原创文章 · 获赞 51 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44286745/article/details/105722426