;IntPtr pstrExportOfName = Win32Native.ImageRvaToVa(psNt32pe, psDos32pe, (uint)Marshal.ReadInt32(ppExportOfNames, (int)(i * 4)), Win32Native.NULL);
Console.WriteLine(Marshal.PtrToStringAnsi(pstrExportOfName));
}
Win32Native.UnmapViewOfFile(psDos32pe);
Win32Native.CloseHandle(hFileMapping);
Win32Native._lclose(hFileBase);
Console.ReadKey(false);
}
包含 入口点 Entry Point
文件偏移地址 File Offset
虚拟地址 Virtual Address(VA)
基地址 Image Base
相对虚拟地址 Relative Virual Address(RVA)
公式:RVA (相对虚拟地址) = VA(虚拟地址) - Image Base (基地址)
文件偏移地址和虚拟地址转换
在X86系统中,每个内存页的大小是4KB
文件偏移地址 File Offset = RVA(相对虚拟地址) - ΔK
文件偏移地址 File Offset = VA(虚拟地址) - Image Base (基地址) - ΔK
详细解释内容请参考百度百科,反正你想真正理解还需要自己去研究PE文件
IMAGE_NT_HEADERS在MS-DOS信息头后面它是标准的Win32执行文件信息头,其中包含了
导入的函数表,导出函数表,资源信息表、CLR运行时头,IAT、TLS表、包括调试信息 等等
我们现在要做的就是获取在DLL中导出的函数名,而DLL是属于标准Win32执行文件中的一种
那么我们则必须要获取到IMAGE_NT_HEADERS结构,实际上需要定位NT结构是很简单的,
因为在规定中NT信息头在DOS信息头后面,即IMAGE_DOS_HEADER.e_lfanew + IMAGE_DOS_HEADER
所以你会看到我在代码中有这样一句话IntPtr psNt32pe = (IntPtr)(sDos32pe.e_lfanew + (long)psDos32pe);
IMAGE_OPTIONAL_HEADER可选映像头是一个可选结构,但是IMAGE_FILE_HEADER结构不满足PE文件
需求定义的属性,因此这些属性在OPTIONAL结构中定义,因此FILE+OPTIONAL两个结构联合起来 才是一
个完整的PE文件结构,在其中包含了很多重要的信息字段 如 AddressOfEntryPoint、DataDirectory、Subsystem
不过提到DataDirectory我想说一下,在C#中不好定义所以在代码中该字段换了另一种方式定义,DataDirectory
默认是有16个IMAGE_DATA_DIRECTORY的尺寸,所以在代码中你可以看到有很多该类型的定义。它们则是表
示DataDirectory中信息IMAGE_DIRECTORY_ENTRY_EXPORT导出表 我们现在只需要获取它的信息,在这里
我们需要用到ImageRvaToVa(相对虚拟地址到虚拟地址)有人是这样理解的, 物理地址到虚拟地址 不过原来我在
理解时这个地方也是小小纠结了一番,不过后来则释然了。ImageRvaToVa(NT_H, DOS_H, RVA, RvaSection);
IMAGE_DATA_DIRECTORY中包含两个字段,一个VirtualAddress(RVA)另一个为Size(尺寸)获取到结构体中的
RVA但是这个地址我们不管怎么转换都没法使用,对的因为提供给我的地址根本没法用 那么我们则需要把RVA
转换为VA利用上面提到函数,只有默默的感谢微软一番 呵呵,当转换后会得到IMAGE_EXPORT_DIRECTORY
在这里我需要提示一下大家,不是每个DataDirectory包含的RVA对应的结构都是EXPORT每个都有自己独立的
解释结构,不要搞混了 不然肯定会飞高的。
我们需要IMAGE_EXPORT_DIRECTORY中NumberOfNames(函数名总数)与AddressOfNames(函数名地址)
两个字段中的内容,不过AddressOfNames中包含的是相对虚拟地址RVA,所以我们需要做一次转换,会返回有
效char**的指针前提你提供的数据有效否则返回NULL,由于C#中你懂的char占两个字节,即char=wchar_t那么
我们查看指针中的数据肯定会有问题DLL导出函数名全部是Ascii编码,所以为了方便在C#专用干脆IntPtr方便通过
Marshal进行转换最后只是进行一个资源释放的操作好了基本就是这个样子剩下的还需要大家自己去理解多说无益
- using System;
- using System.Runtime.InteropServices;
-
- static partial class Win32Native
- {
- [DllImport("dbghelp", SetLastError = true)]