遇到的一个样本,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); }
原文:https://www.cnblogs.com/bCPTdtPtp/p/14162009.html