设为首页 加入收藏

TOP

1.15 自实现GetProcAddress(四)
2023-09-09 10:25:34 】 浏览:172
Tags:1.15 GetProcAddress
MAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(dwBase + pDos->e_lfanew); // 获取64位NT头 // PIMAGE_NT_HEADERS64 pNt = (PIMAGE_NT_HEADERS64)(dwBase + pDos->e_lfanew); // 获取数据目录表 PIMAGE_DATA_DIRECTORY pExportDir = pNt->OptionalHeader.DataDirectory; pExportDir = &(pExportDir[IMAGE_DIRECTORY_ENTRY_EXPORT]); DWORD dwOffset = pExportDir->VirtualAddress; // 获取导出表信息结构 PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(dwBase + dwOffset); DWORD dwFunCount = pExport->NumberOfFunctions; DWORD dwFunNameCount = pExport->NumberOfNames; DWORD dwModOffset = pExport->Name; // 获取导出地址表 PDWORD pEAT = (PDWORD)(dwBase + pExport->AddressOfFunctions); // 获取导出名称表 PDWORD pENT = (PDWORD)(dwBase + pExport->AddressOfNames); // 获取导出序号表 PWORD pEIT = (PWORD)(dwBase + pExport->AddressOfNameOrdinals); for (DWORD dwOrdinal = 0; dwOrdinal < dwFunCount; dwOrdinal++) { if (!pEAT[dwOrdinal]) { continue; } // 获取序号 DWORD dwID = pExport->Base + dwOrdinal; // 获取导出函数地址 ULONGLONG dwFunAddrOffset = pEAT[dwOrdinal]; for (DWORD dwIndex = 0; dwIndex < dwFunNameCount; dwIndex++) { // 在序号表中查找函数的序号 if (pEIT[dwIndex] == dwOrdinal) { // 根据序号索引到函数名称表中的名字 ULONGLONG dwNameOffset = pENT[dwIndex]; char* pFunName = (char*)((ULONGLONG)dwBase + dwNameOffset); if (!strcmp(pFunName, "GetProcAddress")) { // 根据函数名称返回函数地址 return dwBase + dwFunAddrOffset; } } } } return 0; } // 定义名称指针 typedef ULONGLONG(WINAPI *fnGetProcAddress)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName); typedef HMODULE(WINAPI *fnLoadLibraryA)(_In_ LPCSTR lpLibFileName); int main(int argc, char *argv[]) { DWORD kernel32BaseAddress = GetModuleKernel32(); if (kernel32BaseAddress == 0) { return 0; } // 获取kernel32基址/获取GetProcAddress的基址 fnGetProcAddress pfnGetProcAddress = (fnGetProcAddress)MyGetProcAddress(); std::cout << pfnGetProcAddress << std::endl; // 获取Kernel32核心API地址 fnLoadLibraryA pfnLoadLibraryA = (fnLoadLibraryA)pfnGetProcAddress((HMODULE)kernel32BaseAddress, "LoadLibraryA"); printf("自定义读入LoadLibrary = %x \n", pfnLoadLibraryA); system("pause"); return 0; }

输出效果如下图所示,我们即可读入fnLoadLibraryA函数的内存地址;

上述代码的使用也很简单,当我们能够得到GetProcAddress的内存地址后,就可以使用该内存地址动态定位到任意一个函数地址,我们通过得到LoadLibrary函数地址,与GetModuleHandleA函数地址,通过两个函数就可以定位到Windows系统内任意一个函数,我们以调用MessageBox弹窗为例,动态输出一个弹窗,该调用方式如下所示。

// 定义名称指针
typedef ULONGLONG(WINAPI *fnGetProcAddress)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName);
typedef HMODULE(WINAPI *fnLoadLibraryA)(_In_ LPCSTR lpLibFileName);
typedef int(WINAPI *fnMessageBox)(HWND hWnd, LPSTR lpText, LPSTR lpCaption, UINT uType);
typedef HMODULE(WINAPI *fnGetModuleHandleA)(_In_opt_ LPCSTR lpModuleName);
typedef BOOL(WINAPI *fnVirtualProtect)(_In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect);
typedef void(WINAPI *fnExitProcess)(_In_ UINT uExitCode);

int main(int argc, char * argv[])
{
  // 获取kernel32基址 / 获取GetProcAddress的基址
  fnGetProcAddress pfnGetProcAddress = (fnGetProcAddress)MyGetProcAddress();
  ULONGLONG dwBase = GetModuleKernel32();
  printf("fnGetProcAddress = %x \n", pfnGetProcAddress);
  printf("GetKernel32Addr = %x \n", dwBase);

  // 获取Kernel32核心API地址
  fnLoadLibraryA pfnLoa
首页 上一页 1 2 3 4 下一页 尾页 4/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++算法之旅、05 基础篇 | 第二章.. 下一篇C++系列三:QT初识2

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目