Ⅰ.知识点:
1.如何定位导出表:
数据目录项的第一个结构,就是导出表.
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
VirtualAddress 导出表的RVA
Size 导出表大小
2.导出表结构
上面的结构,只是说明导出表在哪里,有多大,并不是真正的导出表.
如何在FileBuffer中找到这个结构呢?在VirtualAddress中存储的是RVA,如果想在FileBuffer中定位
必须要先将该RVA转换成FOA.
真正的导出表结构如下:
3.AddressOfFunctions说明:
该表中元素宽度为4个字节
该表中存储所有导出函数的地址
该表中个数由NumberOfFunctions决定
该表项中的值是RVA, 加上ImageBase才是函数真正的地址
定位:
IMAGE_EXPORT_DIRECTORY->AddressOfFunctions 中存储的是该表的RVA 需要先转换成FOA
4.AddressOfNames说明:
该表中元素宽度为4个字节
该表中存储所有以名字导出函数的名字的RVA
该表项中的值是RVA, 指向函数真正的名称
5.AddressOfNameOrdinals
Ⅱ.关键点:
为什么要分成3张表?
1、函数导出的个数与函数名的个数未必一样.所以要将函数地址表和函数名称表分开.
2、函数地址表是不是一定大于函数名称表?
未必,一个相同的函数地址,可能有多个不同的名字.
3、如何根据函数的名字获取一个函数的地址?
Ⅲ.问题描述:
打印导出表
根据函数的导出序号获取一个函数的地址
Ⅳ.代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#define test 1
#define ordianl 3
DWORD ToLoaderPE(LPSTR file_path, PVOID* pFileBuffer);
BOOL MemoryToFile(PVOID pMemBuffer, DWORD size, LPSTR lpszFile);
DWORD FoaToImageOffset(PVOID pBuffer, DWORD dwFoa);
DWORD RvaToFileOffset(PVOID pBuffer, DWORD dwRva);
DWORD GetSctionEmptySpace(PVOID pFileBuffer, DWORD SectionOrdinal);
DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address);
DWORD GetFunctionAddrByName(PVOID pFileBuffer, LPSTR fun_name);
DWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD fun_ordinal);
VOID LogExportTable(PVOID pFileBuffer);
//char file_path[] = "c:\\users\\desktop\\notepad.exe";
char file_path[] = "c:\\users\\desktop\\dll1test.dll";
//char file_path[] = "c:\\users\\desktop\\ipmsg2007.exe";
char fun_name[] = "Mul";
char write_file_path[] = "D:\\Lib\\cp_XX.exe";
char write_adddata_file_path[] = "D:\\Lib\\cp_adddata_XX.exe";
char write_addsec_file_path[] = "D:\\Lib\\cp_addsec_XX.exe";
char write_enlargersec_file_path[] = "D:\\Lib\\cp_enlargersec_XX.exe";
char write_mergesec_file_path[] = "D:\\Lib\\cp_mergesec_XX.exe";
//返回PE文件大小
DWORD ToLoaderPE(LPSTR file_path, PVOID* pFileBuffer)
{
FILE *pFile = NULL;
DWORD FileSize = 0;
PVOID pFileBufferTemp = NULL;
pFile = fopen(file_path, "rb");
if (!pFile)
{
printf("(ToLoaderPE)Can't open file!\n");
return 0;
}
fseek(pFile, 0, SEEK_END);
FileSize = ftell(pFile);
printf("FileBuffer: %#x\n", FileSize);
fseek(pFile, 0, SEEK_SET);
pFileBufferTemp = malloc(FileSize);
if (!pFileBufferTemp)
{
printf("(ToLoaderPE)Allocate dynamic memory failed!\n");
fclose(pFile);
return 0;
}
DWORD n = fread(pFileBufferTemp, FileSize, 1, pFile);
if (!n)
{
printf("(ToLoaderPE)Read file failed!\n");
free(pFileBufferTemp);
fclose(pFile);
return 0;
}
*pFileBuffer = pFileBufferTemp;
pFileBufferTemp = NULL;
fclose(pFile);
return FileSize;
}
BOOL MemoryToFile(PVOID pMemBuffer, DWORD size, LPSTR lpszFile)
{
FILE *fp;
fp = fopen(lpszFile, "wb");
if (fp != NULL)
{
fwrite(pMemBuffer, size, 1, fp);
}
fclose(fp);
printf("Store file success!\n");
return 1;