C# 遍历DLL导出函数
C#如何去遍历一个由C++或E语言编写的本地DLL导出函数呢 不过在这里我建议对PE一无所知的人
你或许应先补补这方面的知识,我不知道为什么PE方面的 应用在C#中怎么这么少,我查阅过相关
C#的知识大概只见一个人写过关于PE的应用 还只是从PE信息中判断执行文件是X86还是X64方式
编译,难道C#程序员真的很差 真的只能会点Asp.Net / MVC?想想看雪论坛那些玩inline-asm /
inline-hook的牛牛 真是感到有很大差距 不过不论什么语言 在我看来其实都差不多 重点在于人是否
有心。虽然我不敢保证C#可以嵌入动态汇编(auto-asm)但是我可以保证C#可以做inline-hook虽然会
的人比较少,不过也还好,至少C#程序员不会是一群渣渣。不过我在写下述代码时,可是累得紧 写
结构体部分有些麻烦 而且C#与C++有些不同 当然也可以动态偏移地址搞定不过那个有些麻烦了,你
想推敲地址可不是那么好玩的事情,可能你自己推敲半天结果发现你推敲错了,那种方法用在结构体
层次较少的情况下的确可以提升逼格 反正别人看不懂就好嘛? 呵呵。下面的代码需要在X86的环境下
使用主要在于该代码中使用的PE信息全是32位的结构体而非64位的PE信息结构体 所以需要X86环境
不过不论是X86还是X64方法都是相等的,只是两者的结构体与对称不太一样而已。
PE格式,是微软Win32环境可移植执行文件如(exe / sys / dll / vxd / vdm)等都是标准的文件格式
PE格式衍生于VAX / VMS上的COFF文件格式,Portable是指对于不同的Windows版本和不同的
CPU类型上PE文件的格式是一样的,或许CPU不一指令与二进制编码不一,但是文件中各种东
西的布局是一至的。
PE文件中第一个字节是MS-DOS信息头即IMAGE_DOS_HEADER与IMAGE_NT_HEADER中包
含许多PE装载器用到。
- [STAThread]
- unsafe static void Main()
- {
- IntPtr hFileBase = Win32Native._lopen(@"C:/Windows/System32/ATL.dll", Win32Native.OF_SHARE_COMPAT);
- IntPtr hFileMapping = Win32Native.CreateFileMapping(hFileBase, Win32Native.NULL, Win32Native.PAGE_READONLY, 0, 0, null);
- IntPtr psDos32pe = Win32Native.MapViewOfFile(hFileMapping, Win32Native.FILE_MAP_READ, 0, 0, Win32Native.NULL); // e_lfanew 248
- IMAGE_DOS_HEADER sDos32pe = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(psDos32pe, typeof(IMAGE_DOS_HEADER));
- IntPtr psNt32pe = (IntPtr)(sDos32pe.e_lfanew + (long)psDos32pe);
- IMAGE_NT_HEADERS sNt32pe = (IMAGE_NT_HEADERS)Marshal.PtrToStructure(psNt32pe, typeof(IMAGE_NT_HEADERS));
- // 63 63 72 75 6E 2E 63 6F 6D
- IntPtr psExportDirectory = Win32Native.ImageRvaToVa(psNt32pe, psDos32pe, sNt32pe.OptionalHeader.ExportTable.VirtualAddress, Win32Native.NULL);
- IMAGE_EXPORT_DIRECTORY sExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(psExportDirectory, typeof(IMAGE_EXPORT_DIRECTORY));
- IntPtr ppExportOfNames = Win32Native.ImageRvaToVa(psNt32pe, psDos32pe, sExportDirectory.AddressOfNames, Win32Native.NULL);
- for (uint i = 0, nNoOfExports = sExportDirectory.NumberOfNames; i < nNoOfExports; i++)
- {
- 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;
- // #include "stdafx.h"
- // #include <ImageHlp.h>
- // #include <Windows.h>
- // #pragma comment(lib, "ImageHlp.lib")
- static partial class Win32Native
- {
- [DllImport("dbghelp", SetLastError = true)] // PIMAGE_SECTION_HEADER LastRvaSection
- public static extern IntPtr ImageRvaToVa(IntPtr NtHeaders, IntPtr Base, uint Rva, int LastRvaSection);
- [DllImport("kernel32", SetLastError = true)]
- public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern IntPtr CreateFileMapping(IntPtr hFile, int lpFileMappingAttributes, int flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, int dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, int dwNumberOfBytesToMap);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern int UnmapViewOfFile(IntPtr hMapFile);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern int _lclose(IntPtr hFile);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern int CloseHandle(IntPtr hObject);
- }
- static partial class Win32Native
- {
- public const int NULL = 0;
- public const int OF_SHARE_COMPAT = 0;
- public const int PAGE_READONLY = 2;
- public const int FILE_MAP_READ = 4;
- public const int IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct IMAGE_DOS_HEADER
- {
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
- public char[] e_magic; // Magic number
- public ushort e_cblp; // Bytes on last page of file
- public ushort e_cp; // Pages in file
- public ushort e_crlc; // Relocations
- public ushort e_cparhdr; // Size of header in paragraphs
- public ushort e_minalloc; // Minimum extra paragraphs needed
- public ushort e_maxalloc; // Maximum extra paragraphs needed
- public ushort e_ss; // Initial (relative) SS value
- public ushort e_sp; // Initial SP value
- public ushort e_csum; // Checksum
- public ushort e_ip; // Initial IP value
- public ushort e_cs; // Initial (relative) CS value
- public ushort e_lfarlc; // File address of relocation table
- public ushort e_ovno; // Overlay number
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
- public ushort[] e_res1; // Reserved words
- public ushort e_oemid; // OEM identifier (for e_oeminfo)
- public ushort e_oeminfo; // OEM information; e_oemid specific
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
- public ushort[] e_res2; // Reserved words
- public int e_lfanew; // File address of new exe header
- private string _e_magic
- {
- get { return new string(e_magic); }
- }
- public bool isValid
- {
- get { return _e_magic == "MZ"; }
- }
- }
- [StructLayout(LayoutKind.Explicit)]
- public struct IMAGE_OPTIONAL_HEADERS
- {
- [FieldOffset(0)]
- public MagicType Magic;
- [FieldOffset(2)]
- public byte MajorLinkerVersion;
- [FieldOffset(3)]
- public byte MinorLinkerVersion;
- [FieldOffset(4)]
- public uint SizeOfCode;
- [FieldOffset(8)]
- public uint SizeOfInitializedData;
- [FieldOffset(12)]
- public uint SizeOfUninitializedData;
- [FieldOffset(16)]
- public uint AddressOfEntryPoint;
- [FieldOffset(20)]
- public uint BaseOfCode;
- // PE32 contains this additional field
- [FieldOffset(24)]
- public uint BaseOfData;
- [FieldOffset(28)]
- public uint ImageBase;
- [FieldOffset(32)]
- public uint SectionAlignment;
- [FieldOffset(36)]
- public uint FileAlignment;
- [FieldOffset(40)]
- public ushort MajorOperatingSystemVersion;
- [FieldOffset(42)]
- public ushort MinorOperatingSystemVersion;
- [FieldOffset(44)]
- public ushort MajorImageVersion;
- [FieldOffset(46)]
- public ushort MinorImageVersion;
- [FieldOffset(48)]
- public ushort MajorSubsystemVersion;
- [FieldOffset(50)]
- public ushort MinorSubsystemVersion;
- [FieldOffset(52)]
- public uint Win32VersionValue;
- [FieldOffset(56)]
- public uint SizeOfImage;
- [FieldOffset(60)]
- public uint SizeOfHeaders;
- [FieldOffset(64)]
- public uint CheckSum;
- [FieldOffset(68)]
- public SubSystemType Subsystem;
- [FieldOffset(70)]
- public DllCharacteristicsType DllCharacteristics;
- [FieldOffset(72)]
- public uint SizeOfStackReserve;
- [FieldOffset(76)]
- public uint SizeOfStackCommit;
- [FieldOffset(80)]
- public uint SizeOfHeapReserve;
- [FieldOffset(84)]
- public uint SizeOfHeapCommit;
- [FieldOffset(88)]
- public uint LoaderFlags;
- [FieldOffset(92)]
- public uint NumberOfRvaAndSizes;
- [FieldOffset(96)]
- public IMAGE_DATA_DIRECTORY ExportTable;
- [FieldOffset(104)]
- public IMAGE_DATA_DIRECTORY ImportTable;
- [FieldOffset(112)]
- public IMAGE_DATA_DIRECTORY ResourceTable;
- [FieldOffset(120)]
- public IMAGE_DATA_DIRECTORY ExceptionTable;
- [FieldOffset(128)]
- public IMAGE_DATA_DIRECTORY CertificateTable;
- [FieldOffset(136)]
- public IMAGE_DATA_DIRECTORY BaseRelocationTable;
- [FieldOffset(144)]
- public IMAGE_DATA_DIRECTORY Debug;
- [FieldOffset(152)]
- public IMAGE_DATA_DIRECTORY Architecture;
- [FieldOffset(160)]
- public IMAGE_DATA_DIRECTORY GlobalPtr;
- [FieldOffset(168)]
- public IMAGE_DATA_DIRECTORY TLSTable;
- [FieldOffset(176)]
- public IMAGE_DATA_DIRECTORY LoadConfigTable;
- [FieldOffset(184)]
- public IMAGE_DATA_DIRECTORY BoundImport;
- [FieldOffset(192)]
- public IMAGE_DATA_DIRECTORY IAT;
- [FieldOffset(200)]
- public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
- [FieldOffset(208)]
- public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
- [FieldOffset(216)]
- public IMAGE_DATA_DIRECTORY Reserved;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct IMAGE_FILE_HEADER
- {
- public ushort Machine;
- public ushort NumberOfSections;
- public uint TimeDateStamp;
- public uint PointerToSymbolTable;
- public uint NumberOfSymbols;
- public ushort SizeOfOptionalHeader;
- public ushort Characteristics;
- }
- public enum MachineType : ushort
- {
- Native = 0,
- I386 = 0x014c,
- Itanium = 0x0200,
- x64 = 0x8664
- }
- public enum MagicType : ushort
- {
- IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b,
- IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
- }
- public enum SubSystemType : ushort
- {
- IMAGE_SUBSYSTEM_UNKNOWN = 0,
- IMAGE_SUBSYSTEM_NATIVE = 1,
- IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
- IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
- IMAGE_SUBSYSTEM_POSIX_CUI = 7,
- IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
- IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
- IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
- IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
- IMAGE_SUBSYSTEM_EFI_ROM = 13,
- IMAGE_SUBSYSTEM_XBOX = 14
- }
- public enum DllCharacteristicsType : ushort
- {
- RES_0 = 0x0001,
- RES_1 = 0x0002,
- RES_2 = 0x0004,
- RES_3 = 0x0008,
- IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040,
- IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
- IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100,
- IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
- IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
- IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
- RES_4 = 0x1000,
- IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
- IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct IMAGE_DATA_DIRECTORY
- {
- public uint VirtualAddress;
- public uint Size;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct IMAGE_EXPORT_DIRECTORY
- {
- public uint Characteristics;
- public uint TimeDateStamp;
- public ushort MajorVersion;
- public ushort MinorVersion;
- public uint Name;
- public uint Base;
- public uint NumberOfFunctions;
- public uint NumberOfNames;
- public uint AddressOfFunctions; // RVA from base of image
- public uint AddressOfNames; // RVA from base of image
- public uint AddressOfNameOrdinals; // RVA from base of image
- }
- [StructLayout(LayoutKind.Explicit)]
- public struct IMAGE_NT_HEADERS
- {
- [FieldOffset(0)]
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
- public char[] Signature;
- [FieldOffset(4)]
- public IMAGE_FILE_HEADER FileHeader;
- [FieldOffset(24)]
- public IMAGE_OPTIONAL_HEADERS OptionalHeader;
- private string _Signature
- {
- get { return new string(Signature); }
- }
- public bool isValid
- {
- get { return _Signature == "PE\0\0" && (OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC || OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC); }
- }
- }
C# 遍历DLL导出函数的更多相关文章
- DLL导出函数和类的定义区别 __declspec(dllexport)
DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...
- AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源
AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...
- dll 导出函数名的那些事
dll 导出函数名的那些事 关键字: VC++ DLL 导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...
- dll导出函数的两种方式的比较
最初的网页链接已经挂了, 在此贴一个中间的转载链接 https://blog.csdn.net/zhazhiqiang/article/details/51577523 一 概要 vs中导出 dll的 ...
- 动态链接库DLL导出函数并导入使用
动态链接库DLL导出函数并导入使用 本文完全参考自<vs2008制作dll笔记,回带值样例>. 首先制作DLL文件,在vs2010中新建Win32控制台项目,选择DLL选项,简历头文件,源 ...
- Dll 导出函数那些破事
经常使用VC6的Dependency查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系. VC++支持两种语言:即 ...
- 使用dumpbin命令查看dll导出函数及重定向输出到文件【轉】
查看dll导出函数,一般使用Viewdll等第三方工具. VS开发环境中,可以查看32位和64位的dll.具体使用方法如下: 1. 进入VS开发环境,然后Tools -> Visual stud ...
- 使用dumpbin命令查看dll导出函数及重定向输出到文件(VS自带)
以前查看dll导出函数,一般使用Viewdll等第三方工具.但由于Viewdll采用dephi编写,因此仅能查看32位的dll.其实微软已经帮我们提供一个查看dll导出函数的命令,嵌在VS开发环境中, ...
- DLL导出函数
使用DEF文件从DLL导出 模块定义(.def)文件时包含一个或多个描述DLL各种属性的Module语句的文本文件.如果不使用_declspec(dllexport)关键字导出DLL的函数,则DLL需 ...
随机推荐
- HtmlHelper和强类型转换
MVC HtmlHelper;1.Url():<%= Html.ActionLink("用户列表","方法","控制器") %> ...
- Rtp 协议实现网络广播台网络收音机
RTP协议介绍:http://www.360doc.com/content/11/1009/15/496343_154624612.shtml 本文中使用了 StreamCoders 的 RTP.ne ...
- linux 常用命令大全
linux 常用命令大全 系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统 ...
- Entity Framework 4、5 多字段排序
public interface IOrderByExpression<TEntity> where TEntity : class { IOrderedQueryable<TEnt ...
- Spec模板
Spec模板 一.概述 1.项目背景 图书馆在正常运营中面对大量书籍.读者信息以及两者间相互联系产生的借书信息.还书信息.现有的人工记录方法既效率低又错误过多,大大影响了图书馆 ...
- JPA 使用
本文以JPA+Hibernate 角色与权限示例说明. 角色实体定义: @Entity @Table public class Role { private long id; private Stri ...
- 设置jenkins代理
http://stackoverflow.com/documentation/jenkins/919/introduction-to-jenkins Natively, Jenkins runs on ...
- 为什么心跳包(HeartBeat)是必须的?
几乎所有的网游服务端都有心跳包(HeartBeat或Ping)的设计,在最近开发手游服务端时,也用到了心跳包.思考思考,心跳包是必须的吗?为什么需要心跳包?TCP没有提供断线检测的方法吗?TCP提供的 ...
- [BTS] Error Can't update assemblies.
Removal of the assembly failed. Make sure that all items in the assembly you are trying to remove fu ...
- H5常用代码:页面框架
万变不离其宗,道法自然! 虽然H5的小项目一波又一波,但有一个东东基本没什么变化,那就是整个页面的框架结构. 我所常用的H5常用页面框架如下: <!DOCTYPE html> <ht ...