这次模拟了系统在加载程序到内存时,程序的导入表中的FirstThunk被替换的过程。这里只演示了ImportByName的情形,仅供自娱自乐,233333。
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996)
#pragma warning(disable: 4018)
DWORD CalcFileOffset(PIMAGE_SECTION_HEADER pSectionHeader, DWORD dwVirtualAddr);
BOOL IsPeFormat(UCHAR *data);
bool FindCorrespondingDll(UCHAR *pImportTable, UCHAR *data);
BOOL FindCorrespondingDllFunction(PIMAGE_IMPORT_DESCRIPTOR pImageDescriptor, UCHAR *data);
DWORD FindCorrespondingImportFunctionByName(char *importedFunctionName, char * DllName);
UCHAR *GetFileData(char *fileName);
DWORD GetExportTableRVA(UCHAR *data);
DWORD numberOfSections = 0;//区块表数目
BOOL IsPeFormat(UCHAR *data)//check 是否是pe文件格式
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)data;
PIMAGE_NT_HEADERS pFileHeader = NULL;
if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
pFileHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
if (pFileHeader->Signature == IMAGE_NT_SIGNATURE)//若这两个签名都满足 说明是PE格式文件
return TRUE;
}
return FALSE;
}
bool FindCorrespondingDll(UCHAR *pImportTable, UCHAR *data)//找到给定pe文件的依赖dll,即导入的各项的dll,然后再分发给子函数
{
PIMAGE_IMPORT_DESCRIPTOR pImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)pImportTable;//输入表以一个全0的PIMAGE_IMPORT_DESCRIPTOR作为结束条件
UCHAR *zeroBuf = (UCHAR *)malloc(sizeof(IMAGE_IMPORT_DESCRIPTOR));
memset(zeroBuf, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR));
while (memcmp(pImageDescriptor, zeroBuf, sizeof(IMAGE_IMPORT_DESCRIPTOR)) != 0) {
//当输入表描述符不为全0时
//每个输入表描述符描述一个DLL的信息,送入相应的处理函数处理每一个DLL
FindCorrespondingDllFunction(pImageDescriptor, data);//送入一个DLL描述符
pImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImageDescriptor + sizeof(IMAGE_IMPORT_DESCRIPTOR));//获取下一个输入表描述符
}
return TRUE;
}
BOOL FindCorrespondingDllFunction(PIMAGE_IMPORT_DESCRIPTOR pImageDescriptor, UCHAR *data)//用于获得每个DLL的相应的函数的函数名用于二进制比较 函数名都是ASCII字符串
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)data;
PIMAGE_NT_HEADERS pFileHeader = (PIMAGE_NT_HEADERS)((DWORD)data + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pHeader = (PIMAGE_FILE_HEADER)(&pFileHeader->FileHeader);//获取fileHeader
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(&pFileHeader->OptionalHeader);//获得可选头地址
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pFileHeader);//获取区块表地址
DWORD offsetOfDllName = CalcFileOffset(pSectionHeader