【学习记录】一点关于GetProcAddress的记录

遇到的一个样本,exe格式,有导出表,导出了一个char类型的数组

样本有这样的操作:

在自身导出的那个数组中,存入了一个系统函数的字符串,例如:kernel32.VIrtualProtect

然后将自己的导出表的size改的非常大,改成了0x80000000,这样,在使用GetProcAddress获取自身导出那个数组地址时,返回的就是数组中存放的字符串的函数地址了

大致看了一下GetProcAddress函数:

小插曲:GetProcAddress使用了一个RtlImageDirectoryEntryToData函数,可以返回数据目录表某一项的位置,

PVOID
IMAGEAPI
ImageDirectoryEntryToData (
    _In_ PVOID Base,  //PE文件的加载基址
    _In_ BOOLEAN MappedAsImage,  //这个如果为TRUE,返回的是区段拉伸后的位置,Base+RVA,如果为FALSE,返回的是区段未拉伸的位置,Base+FOA
    _In_ USHORT DirectoryEntry,  //数据目录项
    _Out_ PULONG Size  //数据目录项的大小
    );

 

修改导出表size的目的是为了走下面这个if分支,虽然我也不是很懂根本原理是什么

 

 

 

 

我自己写的代码,测试了一下

#include <iostream>
#include <Windows.h>


extern "C" _declspec(dllexport) char szFile[100] = {0};

int main()
{
    
    
    strcpy_s(szFile, "kernel32.VirtualProtect");

    HMODULE hMod = GetModuleHandleA(NULL);

    

    DWORD pszFile = (DWORD)GetProcAddress(hMod, "szFile");  //这里会返回szFile的地址
    printf("pszFile : %08X\n", pszFile);
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hMod;

    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD)pDos + pDos->e_lfanew);
    
    DWORD dwOld = 0;
    VirtualProtect((LPVOID)pDos, 0x1000, PAGE_EXECUTE_READWRITE, &dwOld);
    pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0x80000000;  //把自己的导出表size改的特别大
    
    pszFile = (DWORD)GetProcAddress(hMod, "szFile");  //这里返回的不再是szFile数组的地址了,而是变成了VirtualProtect的地址
    printf("pszFile : %08X\n", pszFile);
}

 

posted @ 2020-12-19 23:20  五仁月饼  阅读(190)  评论(0编辑  收藏  举报