PE_导出表

具体流程参考:Revival_S

#include<stdio.h>
#include<windows.h>

DWORD Rva2Foa(PVOID pFileBuffer, DWORD dwRva);
DWORD Align(int add, int alignment);
DWORD printExportTable(PVOID pFileBuffer);
DWORD getFuncAddrByName(PVOID pFileBuffer, PSTR name);
DWORD getFuncAddrByOrdinal(PVOID pFileBuffer, DWORD ord);

DWORD toLoardPE(PVOID* pFileBuffer, PSTR file_path){
	FILE *fp;
	DWORD FileSize;
	PVOID pFileBufferTemp;

	fp = fopen(file_path, "rb");
	if(!fp){
		printf("读取文件失败!\n");
		return 0;
	}
	fseek(fp, 0, SEEK_END);
	FileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	
	pFileBufferTemp = malloc(FileSize);
	if(!pFileBufferTemp){
		printf("读取文件开辟内存失败\n");
		return 0;
	}

	DWORD n = fread(pFileBufferTemp, FileSize, 1, fp);

	*pFileBuffer = pFileBufferTemp;
	pFileBufferTemp = NULL;
	fclose(fp);

	return FileSize;
}

DWORD Align(int add, int alignment){
	if(add % alignment == 0){
		return add;
	}
	return ((add / alignment) + 1) * alignment;
}

DWORD Rva2Foa(PVOID pFileBuffer, DWORD dwRva){
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;

	if(!pFileBuffer){
		printf("从磁盘读取文件为空!\n");
		return 0;
	}

	if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
		printf("(Rva2Foa)没有MZ标志!\n");
		return 0;
	}

	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if(*(PDWORD)((DWORD)pDosHeader + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE){
		printf("(Rva2Foa)没有PE标志!\n");
		return 0;
	}

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
	PIMAGE_SECTION_HEADER pNextSectionHeaderTemp = pSectionHeader + 1;


	if(dwRva <= pOptionHeader->SizeOfHeaders){
		return dwRva;
	}else{
		for(int n=1; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++, pNextSectionHeaderTemp++){
			if((dwRva >= pSectionHeaderTemp->VirtualAddress) && (dwRva < (pNextSectionHeaderTemp->VirtualAddress)))
				return dwRva - pSectionHeaderTemp->VirtualAddress + pSectionHeaderTemp->PointerToRawData;
		}
	}
	if (dwRva >= pSectionHeader->VirtualAddress && dwRva < pOptionHeader->SizeOfImage)
	{
		return pSectionHeader->PointerToRawData + dwRva - pSectionHeader->VirtualAddress;
	}
	printf("RVA TO FOA Failed!\n");

	return 0;
}

DWORD printExportTable(PVOID pFileBuffer){
	if(!pFileBuffer){
		printf("文件不存在!\n");
		return 0;
	}
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	printf("%x\n",pDosHeader->e_magic);
	if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){
		printf("(printExportTable)没有MZ标志!\n");
		return 0;
	}

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	if(pNTHeader->Signature != IMAGE_NT_SIGNATURE){
		printf("(printExportTable)没有PE标志!\n");
		return 0;
	}
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;

	if(!pDataDirectory->VirtualAddress){
		printf("没有导出表!\n");
		return 0;
	}

	printf("导出表的RVA:%x\n", pDataDirectory->VirtualAddress);

	DWORD exportFoa = Rva2Foa(pFileBuffer, pDataDirectory->VirtualAddress);
	printf("导出表的FOA:%x\n", exportFoa);
	
	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + exportFoa);

	/*
	typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     // RVA from base of image
    DWORD   AddressOfNames;         // RVA from base of image
    DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
*/
	printf("=================导出表=================\n");
	printf("Characteristics:%#x\n", pExportDirectory->Characteristics);
	printf("TimeDateStamp:%#x\n", pExportDirectory->TimeDateStamp);
	printf("MajorVersion:%#x\n", pExportDirectory->MajorVersion);
	printf("MinorVersion:%#x\n", pExportDirectory->MinorVersion);
	DWORD namefoa = Rva2Foa(pFileBuffer, pExportDirectory->Name);
	printf("Name:%s\n", (PVOID)((DWORD)pFileBuffer + namefoa));
	printf("Base:%#x\n", pExportDirectory->Base);
	printf("NumberOfFunctions:%#x\n", pExportDirectory->NumberOfFunctions);
	printf("NumberOfNames:%#x\n", pExportDirectory->NumberOfNames);
	printf("AddressOfFunctions(RVA):%#x\n", pExportDirectory->AddressOfFunctions);
	printf("AddressOfNames(RVA):%#x\n", pExportDirectory->AddressOfNames);
	printf("AddressOfNameOrdinals(RVA):%#x\n", pExportDirectory->AddressOfNameOrdinals);

	printf("=================导出函数地址表=================\n");
	DWORD addrFuncFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfFunctions);
	printf("函数地址表的FOA:%#x\n", addrFuncFoa);
	for(size_t i=0; i < pExportDirectory->NumberOfFunctions; i++){
		DWORD addrfunc = *(PDWORD)((DWORD)pFileBuffer + addrFuncFoa + i * 4);
		printf("下标:%#x 函数地址:%#x\n", i, addrfunc);
	}


	printf("=================导出函数名称表=================\n");
	DWORD nameFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfNames);
	printf("函数名称表的FOA:%#x\n", nameFoa);
	for(i=0; i < pExportDirectory->NumberOfNames; i++){
		DWORD funcName = Rva2Foa(pFileBuffer, *(PDWORD)((DWORD)pFileBuffer + nameFoa + i*4));
		PCHAR name = (PCHAR)((DWORD)pFileBuffer + funcName);
		printf("下标:%#x 函数名称:%s\n", i, name);
	}

	printf("=================导出函数序号表=================\n");
	DWORD ordinalNumberFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfNameOrdinals);
	printf("函数序号表的FOA:%#x\n", ordinalNumberFoa);
	for(i=0; i < pExportDirectory->NumberOfNames; i++){
		WORD funcOrdinal = *(PWORD)((DWORD)pFileBuffer + ordinalNumberFoa + i*2);
		printf("下标:%#x 函数序号:%#x\n",i, funcOrdinal);
	}
	return 0;

}

DWORD getFuncAddrByName(PVOID pFileBuffer, PSTR byname){

	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);

	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;

	DWORD exportFoa = Rva2Foa(pFileBuffer, pDataDirectory->VirtualAddress);

	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + exportFoa);

	printf("=================函数名称查找函数地址=================\n");
	DWORD nameFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfNames);

	for(size_t i=0; i < pExportDirectory->NumberOfNames; i++){
		DWORD funcName = Rva2Foa(pFileBuffer, *(PWORD)((DWORD)pFileBuffer + nameFoa + i*4));
		PCHAR name = (PCHAR)((DWORD)pFileBuffer + funcName);
		if(!strcmp(byname, name)){
			printf("找到相同函数名称\n");
			break;
		}
	}
	if(i == pExportDirectory->NumberOfNames){
		printf("不存在该函数名称\n");
		return 0;
	}
	DWORD ordinalNumberFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfNameOrdinals);
	WORD funcOrdinal = *(PWORD)((DWORD)pFileBuffer + ordinalNumberFoa + i*2);

	DWORD addrFuncFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfFunctions);
	DWORD addrfunc = *(PDWORD)((DWORD)pFileBuffer + addrFuncFoa + funcOrdinal * 4);

	return addrfunc;
	

}
DWORD getFuncAddrByOrdinal(PVOID pFileBuffer, DWORD ord){
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);

	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;


	DWORD exportFoa = Rva2Foa(pFileBuffer, pDataDirectory->VirtualAddress);
	
	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + exportFoa);
	
	printf("=================函数序号查找函数地址=================\n");
	if(ord - pExportDirectory->Base > pExportDirectory->NumberOfFunctions || ord - pExportDirectory->Base < 0){
		printf("找不到序号对应的函数地址\n");
		return 0;
	}
	DWORD funcAddrFoa = Rva2Foa(pFileBuffer, pExportDirectory->AddressOfFunctions);
	DWORD funcAddr = *(PDWORD)((DWORD)pFileBuffer + funcAddrFoa + (ord - pExportDirectory->Base) * 4);
	printf("%d\n",pExportDirectory->Base);
	return funcAddr;

}

int main(){

	PSTR file_path = "C:\\Users\\lolol\\Desktop\\11.dll";
	PSTR write_path = "";

	PVOID pFileBuffer = NULL;
	PVOID pImageBuffer = NULL;
	

	DWORD FileSize = toLoardPE(&pFileBuffer, file_path);
	//printf("%x\n",((char*)pFileBuffer)[0]);
	//printf("%x\n",pFileBuffer);
	printExportTable(pFileBuffer);

	DWORD addrfunc = getFuncAddrByName(pFileBuffer, "CreateFile2");
	printf("根据函数名查询结果:%x\n",addrfunc);

	DWORD funcAddrByord = getFuncAddrByOrdinal(pFileBuffer, 3);
	printf("根据序号查询结果:%x\n",funcAddrByord);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值