1. 编写程序打印所有的导出表信息;
下面是相关代码,里面含有打印数据目录代码
| |
| VOID FileBufferPrintDataDirectory(IN LPVOID pFileBuffer) |
| { |
| PIMAGE_DOS_HEADER pDosHeader = NULL; |
| PIMAGE_NT_HEADERS pNTHeader = NULL; |
| PIMAGE_FILE_HEADER pPEHeader = NULL; |
| PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; |
| PIMAGE_SECTION_HEADER pSectionHeader = NULL; |
| PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; |
| PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; |
| DWORD FoaAddress = 0; |
| |
| if (pFileBuffer == NULL) |
| { |
| printf("FileBuffer 获取失败!\r\n"); |
| return; |
| } |
| |
| |
| if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE) |
| { |
| printf("无效的MZ标识\r\n"); |
| return; |
| } |
| pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; |
| |
| |
| if (*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE) |
| { |
| printf("无效的PE标记\r\n"); |
| return; |
| } |
| |
| 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); |
| |
| pDataDirectory = pOptionHeader->DataDirectory; |
| FoaAddress = RvaToFileOffset(pFileBuffer,pDataDirectory->VirtualAddress); |
| printf("FoaAddress: %#X \r\n",FoaAddress); |
| pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pDosHeader + FoaAddress); |
| |
| printf("\t\t RVA\t\t 大小\r\n"); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| for (DWORD i = 0; i< IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) |
| { |
| DirectoryString(i); |
| printf("%08X\t%08X\r\n",pDataDirectory[i].VirtualAddress,pDataDirectory[i].Size); |
| } |
| printf("***********************************************************\r\n"); |
| printf("pExportDirectory->AddressOfFunctions : \t\t%#08X \r\n",pExportDirectory->AddressOfFunctions); |
| printf("pExportDirectory->AddressOfNames : \t\t%#08X \r\n",pExportDirectory->AddressOfNames); |
| printf("pExportDirectory->AddressOfNameOrdinals : \t%#08X \r\n",pExportDirectory->AddressOfNameOrdinals); |
| printf("pExportDirectory->Base : \t\t\t%#08X \r\n",pExportDirectory->Base); |
| printf("pExportDirectory->Characteristics : \t\t%#08X \r\n",pExportDirectory->Characteristics); |
| printf("pExportDirectory->MajorVersion : \t\t%#08X \r\n",pExportDirectory->MajorVersion); |
| printf("pExportDirectory->MinorVersion : \t\t%#08X \r\n",pExportDirectory->MinorVersion); |
| printf("pExportDirectory->Name : \t\t\t%#08X \r\n",pExportDirectory->Name); |
| printf("pExportDirectory->NumberOfFunctions : \t\t%#08X \r\n",pExportDirectory->NumberOfFunctions); |
| printf("pExportDirectory->NumberOfNames : \t\t%#08X \r\n",pExportDirectory->NumberOfNames); |
| printf("***********************************************************\r\n"); |
| |
| |
| |
| DWORD dwNameFoa = RvaToFileOffset(pFileBuffer,pExportDirectory->Name); |
| DWORD dwAddressOfNamesFoa = RvaToFileOffset(pFileBuffer,pExportDirectory->AddressOfNames); |
| DWORD dwAddressOfFunctionsFoa = RvaToFileOffset(pFileBuffer,pExportDirectory->AddressOfFunctions); |
| DWORD dwAddressOfOrdinalsFoa = RvaToFileOffset(pFileBuffer,pExportDirectory->AddressOfNameOrdinals); |
| |
| |
| PBYTE pDllOrExeName = (PBYTE)((DWORD)pDosHeader + dwNameFoa); |
| |
| printf("导出表的名称: %s \r\n",pDllOrExeName); |
| |
| |
| PDWORD pAddressFunctionTable = (PDWORD)((DWORD)pDosHeader + dwAddressOfFunctionsFoa); |
| printf("函数地址表的位置: %#08X \r\n",pAddressFunctionTable); |
| |
| |
| PDWORD pOrdinaFunctionTable = (PDWORD)((DWORD)pDosHeader + dwAddressOfOrdinalsFoa); |
| printf("函数序号表的位置: %#08X \r\n",pOrdinaFunctionTable); |
| |
| |
| PDWORD pNameFunctionTable = (PDWORD)((DWORD)pDosHeader + dwAddressOfNamesFoa); |
| printf("函数名称表的位置: %#08X \r\n",pNameFunctionTable); |
| |
| |
| |
| |
| BOOL indexNumIsExist = FALSE; |
| |
| |
| |
| |
| |
| |
| |
| |
| for (DWORD n = 0; n< pExportDirectory->NumberOfFunctions; n++) |
| |
| { |
| |
| |
| indexNumIsExist = FALSE; |
| |
| for (DWORD nNameIndex = 0; nNameIndex < pExportDirectory->NumberOfNames; nNameIndex++) |
| { |
| |
| |
| |
| |
| |
| if (n == pOrdinaFunctionTable[nNameIndex]) |
| { |
| indexNumIsExist = TRUE; |
| break; |
| } |
| } |
| |
| if (indexNumIsExist == TRUE) |
| { |
| |
| DWORD dwNameFoa = pNameFunctionTable[nNameIndex]; |
| PBYTE pFunctionName = (PBYTE)((DWORD)pDosHeader + RvaToFileOffset(pFileBuffer,dwNameFoa)); |
| |
| |
| |
| printf("导出表函数名称-->[%s]",pFunctionName); |
| printf("导出表函数地址表的位置: %#08X",pAddressFunctionTable[n]); |
| |
| printf("导出表函数序列号表: [%d] \r\n", n - pExportDirectory->Base); |
| |
| |
| } |
| else |
| { |
| |
| if (pAddressFunctionTable[n] != 0) |
| { |
| |
| printf("导出表函数名称-->"); |
| printf("导出表函数地址表下标[%d]-->", n + pExportDirectory->Base); |
| printf("导出表函数地址表的位置:%#08X ",pAddressFunctionTable[n]); |
| } |
| } |
| printf("\r\n"); |
| } |
| |
| return; |
| } |
| |
| VOID DirectoryString(DWORD dwIndex) |
| { |
| switch(dwIndex) |
| { |
| case 0: |
| printf("输出表:\t\t"); |
| break; |
| case 1: |
| printf("输入表:\t\t"); |
| break; |
| case 2: |
| printf("资源:\t\t"); |
| break; |
| case 3: |
| printf("异常:\t\t"); |
| break; |
| case 4: |
| printf("安全:\t\t"); |
| break; |
| case 5: |
| printf("重定位:\t\t"); |
| break; |
| case 6: |
| printf("调试:\t\t"); |
| break; |
| case 7: |
| printf("版权:\t\t"); |
| break; |
| case 8: |
| printf("全局指针:\t"); |
| break; |
| case 9: |
| printf("TLS表:\t\t"); |
| break; |
| case 10: |
| printf("载入配置:\t"); |
| break; |
| case 11: |
| printf("输入范围:\t"); |
| break; |
| case 12: |
| printf("IAT:\t\t"); |
| break; |
| case 13: |
| printf("延时输入\t"); |
| break; |
| case 14: |
| printf("COM:\t\t"); |
| break; |
| case 15: |
| printf("保留:\t\t"); |
| break; |
| } |
| } |
执行效果:

2.GetFunctionAddrByName(FileBuffer指针,函数名指针)
| |
| DWORD GetFunctionAddrByName(IN PVOID pFileBuffer, IN LPSTR pFunctionOfName) |
| { |
| printf("Function Name: %s\n", pFunctionOfName); |
| |
| PIMAGE_DOS_HEADER pDosHeader = NULL; |
| PIMAGE_NT_HEADERS pNTHeader = NULL; |
| PIMAGE_FILE_HEADER pPEHeader = NULL; |
| PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; |
| PIMAGE_SECTION_HEADER pSectionHeader = NULL; |
| PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; |
| PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; |
| |
| |
| if (!pFileBuffer) |
| { |
| printf("pFileBuffer不是有效的指针\r\n"); |
| return 0; |
| } |
| |
| if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE) |
| { |
| printf("pFileBuffer不是有效的MZ文件\r\n"); |
| return 0; |
| } |
| |
| pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; |
| if (*((PWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE) |
| { |
| printf("pFileBuffer不是一个有效的PE标志\r\n"); |
| return 0; |
| } |
| |
| |
| pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew); |
| pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 0x04); |
| 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\r\n", pDataDirectory->VirtualAddress); |
| DWORD Foa_ExportTable = RvaToFileOffset(pFileBuffer, pDataDirectory->VirtualAddress); |
| printf("导出表FOA地址: %#X\r\n", Foa_ExportTable); |
| pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa_ExportTable); |
| |
| |
| if (!debug) |
| { |
| printf("Characteristics: %#X\r\n", pExportDirectory->Characteristics); |
| printf("TimeDateStamp: %#X\r\n", pExportDirectory->TimeDateStamp); |
| printf("MajorVersion: %#X\r\n", pExportDirectory->MajorVersion); |
| printf("MinorVersion: %#X\r\n", pExportDirectory->MinorVersion); |
| printf("Name: %s\r\n", (PVOID)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pExportDirectory->Name))); |
| printf("Base: %#X\r\n", pExportDirectory->Base); |
| printf("NumberOfFunctions: %#X\r\n", pExportDirectory->NumberOfFunctions); |
| printf("NumberOfNames: %#X\r\n", pExportDirectory->NumberOfNames); |
| printf("AddressOfFunctions: %#X\r\n", pExportDirectory->AddressOfFunctions); |
| printf("AddressOfNames: %#X\r\n", pExportDirectory->AddressOfNames); |
| printf("AddressOfNameOrdinals: %#X\r\n", pExportDirectory->AddressOfNameOrdinals); |
| } |
| |
| |
| DWORD Foa_AddressOfNames = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfNames); |
| DWORD Foa_AddressOfNameOrdinals = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfNameOrdinals); |
| DWORD Foa_AddressOfFunctions = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfFunctions); |
| |
| if (!debug) |
| { |
| DWORD Foa_Address_Names = (DWORD)pFileBuffer + Foa_AddressOfNames; |
| printf("AddressOfNames Offset Value: %#X\r\n", Foa_Address_Names); |
| printf("Foa_AddressOfNames: %#X\r\n", Foa_AddressOfNames); |
| printf("Foa_AddressOfNameOrdinals: %#X\r\n", Foa_AddressOfNameOrdinals); |
| printf("Foa_AddressOfFunctions: %#X\r\n", Foa_AddressOfFunctions); |
| } |
| |
| |
| DWORD ordIndex = -1; |
| for (DWORD i = 0; i < pExportDirectory->NumberOfNames; i++) |
| { |
| DWORD nameOffset = *(PDWORD)((DWORD)pFileBuffer + (DWORD)((LPDWORD)Foa_AddressOfNames + i)); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| LPSTR nameAddr = (LPSTR)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, nameOffset)); |
| if (!strcmp(nameAddr, pFunctionOfName)) |
| { |
| ordIndex = i; |
| break; |
| } |
| } |
| if (ordIndex == -1) |
| { |
| printf("导出表中没有这个函数名称.\n"); |
| return 0; |
| } |
| |
| |
| WORD ord = *(PWORD)((DWORD)pFileBuffer + (DWORD)((LPWORD)Foa_AddressOfNameOrdinals + ordIndex)); |
| |
| if (!debug) |
| { |
| DWORD Foa_AddressNameOrdinals = (DWORD)pFileBuffer + Foa_AddressOfNameOrdinals ; |
| printf("AddressOfNameOrdinals Offset Value: %#X\r\n", Foa_AddressNameOrdinals); |
| printf("Foa_AddressOfNameOrdinals: %#X\r\n", Foa_AddressOfNameOrdinals); |
| printf("ordInex in AddressOfNames: %#X\r\n", ordIndex); |
| printf("ordInex in AddressOfNameOrdinals: %#X\r\n", ord); |
| } |
| |
| |
| DWORD addr = *(PDWORD)((DWORD)pFileBuffer + (DWORD)((LPDWORD)Foa_AddressOfFunctions + ord)); |
| |
| |
| return addr; |
| } |
3.GetFunctionAddrByOrdinals(FileBuffer指针,函数名导出序号)
| |
| DWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD pFunctionOfOrdinal) |
| { |
| printf("Function Ordinal: %#x\n", pFunctionOfOrdinal); |
| |
| PIMAGE_DOS_HEADER pDosHeader = NULL; |
| PIMAGE_NT_HEADERS pNTHeader = NULL; |
| PIMAGE_FILE_HEADER pPEHeader = NULL; |
| PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; |
| PIMAGE_SECTION_HEADER pSectionHeader = NULL; |
| PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; |
| PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; |
| |
| |
| if (!pFileBuffer) |
| { |
| printf("pFileBuffer不是有效的指针\r\n"); |
| return 0; |
| } |
| |
| if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE) |
| { |
| printf("pFileBuffer不是有效的MZ文件\r\n"); |
| return 0; |
| } |
| |
| pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; |
| if (*((PWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE) |
| { |
| printf("pFileBuffer不是一个有效的PE标志\r\n"); |
| return 0; |
| } |
| |
| |
| pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew); |
| pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 0x04); |
| 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("这个程序没有导出表.\r\n"); |
| return 0; |
| } |
| |
| printf("导出表RVA地址: %#X\r\n", pDataDirectory->VirtualAddress); |
| DWORD Foa_ExportTable = RvaToFileOffset(pFileBuffer, pDataDirectory->VirtualAddress); |
| printf("导出表FOA地址: %#X\r\n", Foa_ExportTable); |
| pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa_ExportTable); |
| |
| if (!debug) |
| { |
| printf("Characteristics: %#X\r\n", pExportDirectory->Characteristics); |
| printf("TimeDateStamp:%#X\r\n", pExportDirectory->TimeDateStamp); |
| printf("MajorVersion: %#X\r\n", pExportDirectory->MajorVersion); |
| printf("MinorVersion: %#X\r\n", pExportDirectory->MinorVersion); |
| printf("Name: %s\r\n", (PVOID)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pExportDirectory->Name))); |
| printf("Base: %#X\r\n", pExportDirectory->Base); |
| printf("NumberOfFunctions: %#X\r\n", pExportDirectory->NumberOfFunctions); |
| printf("NumberOfNames: %#X\r\n", pExportDirectory->NumberOfNames); |
| printf("AddressOfFunctions: %#X\r\n", pExportDirectory->AddressOfFunctions); |
| printf("AddressOfNames: %#X\r\n", pExportDirectory->AddressOfNames); |
| printf("AddressOfNameOrdinals: %#X\r\n", pExportDirectory->AddressOfNameOrdinals); |
| } |
| |
| |
| DWORD Sequence = pFunctionOfOrdinal - pExportDirectory->Base; |
| DWORD Foa_AddressOfFunctions = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfFunctions); |
| |
| if (!debug) |
| { |
| DWORD Foa_AddressFunctions = Foa_AddressOfFunctions + (DWORD)pFileBuffer; |
| printf("AddressOfFunctions里面内容: %#X\r\n", Foa_AddressFunctions); |
| printf("Foa_AddressOfFunctions: %#X\r\n", Foa_AddressOfFunctions); |
| } |
| |
| PDWORD pFoa_AddressOfFunctions = (PDWORD)((DWORD)pFileBuffer + Foa_AddressOfFunctions); |
| for (DWORD n = 0; n < Sequence; n++) |
| { |
| pFoa_AddressOfFunctions++; |
| } |
| |
| return *pFoa_AddressOfFunctions; |
| } |
验证执行效果:
执行之前的要传入的参数:

调用函数传入参数的相关代码
| VOID PrintFunctionAddrByNameAndOrdinals() |
| { |
| LPVOID pFileBuffer = NULL; |
| DWORD FileBufferSize = 0; |
| DWORD BaseName_FunctionAddr = 0; |
| DWORD BaseOrdinals_FUnctionAddr = 0; |
| char pFunctionName[] = "png_set_rows"; |
| |
| |
| FileBufferSize = ReadPEFile(FilePath_In,&pFileBuffer); |
| if (FileBufferSize == 0 || !pFileBuffer) |
| { |
| printf("文件-->缓冲区失败\r\n"); |
| return ; |
| } |
| printf("FileBufferSize: %#X \r\n",FileBufferSize); |
| |
| BaseName_FunctionAddr = GetFunctionAddrByName(pFileBuffer,pFunctionName); |
| printf("GetFunctionAddrByName: %#X \r\n",BaseName_FunctionAddr); |
| |
| BaseOrdinals_FUnctionAddr = GetFunctionAddrByOrdinals(pFileBuffer,0x000000AE); |
| printf("GetFunctionAddrByOrdinals: %#X \r\n",BaseOrdinals_FUnctionAddr); |
| |
| free(pFileBuffer); |
| } |
执行结果:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2020-09-22 Vulnhub-靶机-SYMFONOS: 4