通过名称去找
// MyGETPRCOADDRESS.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<Windows.h>
/*WINBASEAPI //导出不需要使用,那么我们注释掉*/
FARPROC
WINAPI
MyGetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
)
{
PIMAGE_DOS_HEADER pIMAGE_DOS_HEADER = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pIMAGE_NT_HEADERS = (PIMAGE_NT_HEADERS)(pIMAGE_DOS_HEADER->e_lfanew + (DWORD)hModule); //NT头
PIMAGE_EXPORT_DIRECTORY pIMAGE_EXPORT_DIRECTORYRVA = (PIMAGE_EXPORT_DIRECTORY)(pIMAGE_NT_HEADERS->OptionalHeader.DataDirectory[0].VirtualAddress); //导出表项,获得RVA RVA并不是真正的导出表项需要转VA,转VA需要加上image_base(也就是加载地址)
PIMAGE_EXPORT_DIRECTORY pIMAGE_EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pIMAGE_EXPORT_DIRECTORYRVA + (DWORD)hModule); //这个才是真正的VA,真正的导出表项,因为RVA在内存中是没有的
DWORD ModuleName = pIMAGE_EXPORT_DIRECTORY->Name + (DWORD)hModule;
printf("%s", ModuleName);
return NULL;
}
int main()
{
std::cout << "Hello World!\n";
HMODULE Hmodule = GetModuleHandleA("ntdll.dll"); //为了防止同名函数,所以先要获得哪个模块 那么Hmodule相当于模块基址
//void *p = GetProcAddress(Hmodule, "RtlDispatchAPC");
//void *p2 = GetProcAddress(Hmodule, (LPCSTR)1);
void* p1 = MyGetProcAddress(Hmodule, "RtlDispatchAPC");
printf("%s", p1);
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

可以看到找成功了
接下来获取名称表格

可以看到0x777727D4就是函数的地址,那么函数地址第一个就是0x0011626c,因为DWORD是4字节
但是还需要加基址hModule(0x77660000),那么就是0x0011626c+0x77660000,也就是如下

可以看到成功定位到了函数,那么可以正确获取到名称表格
然后我们写循环
for (size_t i = 0; i < pIMAGE_EXPORT_DIRECTORY->NumberOfNames; i++)
{
DWORD FunNameRVA = NameAddress[i];
char * FunName = (char *)(FunNameRVA + (DWORD)hModule);
printf("%s\n", FunName);
}


#include <iostream>
#include<Windows.h>
/*WINBASEAPI //导出不需要使用,那么我们注释掉*/
FARPROC
WINAPI
MyGetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
)
{
PIMAGE_DOS_HEADER pIMAGE_DOS_HEADER = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pIMAGE_NT_HEADERS = (PIMAGE_NT_HEADERS)(pIMAGE_DOS_HEADER->e_lfanew + (DWORD)hModule); //NT头
PIMAGE_EXPORT_DIRECTORY pIMAGE_EXPORT_DIRECTORYRVA = (PIMAGE_EXPORT_DIRECTORY)(pIMAGE_NT_HEADERS->OptionalHeader.DataDirectory[0].VirtualAddress); //导出表项,获得RVA RVA并不是真正的导出表项需要转VA,转VA需要加上image_base(也就是加载地址)
PIMAGE_EXPORT_DIRECTORY pIMAGE_EXPORT_DIRECTORY = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pIMAGE_EXPORT_DIRECTORYRVA + (DWORD)hModule); //这个才是真正的VA,真正的导出表项,因为RVA在内存中是没有的
DWORD ModuleName = pIMAGE_EXPORT_DIRECTORY->Name + (DWORD)hModule;
//printf("%s", ModuleName);
DWORD NameAddressRVA = pIMAGE_EXPORT_DIRECTORY->AddressOfNames;
DWORD* NameAddress = (DWORD *)(NameAddressRVA + (DWORD)hModule);
for (size_t i = 0; i < pIMAGE_EXPORT_DIRECTORY->NumberOfNames; i++)
{
DWORD FunNameRVA = NameAddress[i];
char * FunName = (char *)(FunNameRVA + (DWORD)hModule);
printf("%s\n", FunName);
}
printf("%s\n", ModuleName);

文章讲述了如何通过WindowsAPI在DLL中查找导出的函数名称、序号和地址,使用`MyGetProcAddress`函数结合导出表、名称地址和序号表进行动态链接库函数查找,并展示了从`ntdll.dll`和`Kernel32.dll`中找到特定函数的过程。
最低0.47元/天 解锁文章
1509

被折叠的 条评论
为什么被折叠?



