如何以编程方式读取 C# 中的本机 DLL 导入?

2023-12-13

如何以编程方式分析本机 DLL 以读取其导入?


[编辑:我原来的问题如下所示,以及大量有缺陷的代码。请参阅下面的答案以获得更正确的代码。]

C# 代码位于这个链接旨在打印本机 DLL 的导入。

我发现当我使用原始示例的目标 MSCOREE.DLL 运行示例代码时,它可以正常打印所有导入。但是当我使用其他 dll(如 GDI32.DLL 或 WSOCK32.DLL)时,导入不会被打印。这段代码缺少什么来让它像 DUMPBIN.EXE 那样打印所有导入?


代码中有一个很大的问题(即THUNK_DATA)以及其他各种较小的问题,主要涉及表尾检测(使用IsBadReadPtr而不是 NULL 检查,并且也不根据需要添加基地址)。

这是一个固定版本,产生与以下相同的输出dumpbin至少对于wsock32:

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace PETest2
{
    [StructLayout(LayoutKind.Explicit)]
    public unsafe struct IMAGE_IMPORT_BY_NAME
    {
        [FieldOffset(0)]
        public ushort Hint;
        [FieldOffset(2)]
        public fixed char Name[1];
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_IMPORT_DESCRIPTOR
    {
        #region union
        /// <summary>
        /// CSharp doesnt really support unions, but they can be emulated by a field offset 0
        /// </summary>

        [FieldOffset(0)]
        public uint Characteristics;            // 0 for terminating null import descriptor
        [FieldOffset(0)]
        public uint OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
        #endregion

        [FieldOffset(4)]
        public uint TimeDateStamp;
        [FieldOffset(8)]
        public uint ForwarderChain;
        [FieldOffset(12)]
        public uint Name;
        [FieldOffset(16)]
        public uint FirstThunk;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct THUNK_DATA
    {
        [FieldOffset(0)]
        public uint ForwarderString;      // PBYTE 
        [FieldOffset(0)]
        public uint Function;             // PDWORD
        [FieldOffset(0)]
        public uint Ordinal;
        [FieldOffset(0)]
        public uint AddressOfData;        // PIMAGE_IMPORT_BY_NAME
    }

    public unsafe class Interop
    {
        #region Public Constants
        public static readonly ushort IMAGE_DIRECTORY_ENTRY_IMPORT = 1;
        #endregion
        #region Private Constants
        #region CallingConvention CALLING_CONVENTION
        /// <summary>
        ///     Specifies the calling convention.
        /// </summary>
        /// <remarks>
        ///     Specifies <see cref="CallingConvention.Winapi" /> for Windows to 
        ///     indicate that the default should be used.
        /// </remarks>
        private const CallingConvention CALLING_CONVENTION = CallingConvention.Winapi;
        #endregion CallingConvention CALLING_CONVENTION
        #region IMPORT DLL FUNCTIONS
        private const string KERNEL_DLL = "kernel32";
        private const string DBGHELP_DLL = "Dbghelp";
        #endregion
        #endregion Private Constants

        [DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "GetModuleHandleA"), SuppressUnmanagedCodeSecurity]
        public static extern void* GetModuleHandleA(/*IN*/ char* lpModuleName);

        [DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "GetModuleHandleW"), SuppressUnmanagedCodeSecurity]
        public static extern void* GetModuleHandleW(/*IN*/ char* lpModuleName);

        [DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "IsBadReadPtr"), SuppressUnmanagedCodeSecurity]
        public static extern bool IsBadReadPtr(void* lpBase, uint ucb);

        [DllImport(DBGHELP_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "ImageDirectoryEntryToData"), SuppressUnmanagedCodeSecurity]
        public static extern void* ImageDirectoryEntryToData(void* Base, bool MappedAsImage, ushort DirectoryEntry, out uint Size);


    }


    static class Foo
    {
        // From winbase.h in the Win32 platform SDK.
        //
        const uint DONT_RESOLVE_DLL_REFERENCES = 0x00000001;
        const uint LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010;

        [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
        static extern uint LoadLibraryEx(string fileName, uint notUsedMustBeZero, uint flags);

        public static void Main()
        {
            //var path = @"c:\windows\system32\mscoree.dll";
            //var path = @"c:\windows\system32\gdi32.dll";
            var path = @"c:\windows\system32\wsock32.dll";
            var hLib = LoadLibraryEx(path, 0,
                                     DONT_RESOLVE_DLL_REFERENCES | LOAD_IGNORE_CODE_AUTHZ_LEVEL);
            TestImports(hLib, true);

        }


        // using mscoree.dll as an example as it doesnt export any thing
        // so nothing shows up if you use your own module.
        // and the only none delayload in mscoree.dll is the Kernel32.dll
        private static void TestImports(uint hLib, bool mappedAsImage)
        {
            unsafe
            {
                //fixed (char* pszModule = "mscoree.dll")
                {
                    //void* hMod = Interop.GetModuleHandleW(pszModule);
                    void* hMod = (void*)hLib;

                    uint size = 0;
                    uint BaseAddress = (uint)hMod;

                    if (hMod != null)
                    {
                        Console.WriteLine("Got handle");

                        IMAGE_IMPORT_DESCRIPTOR* pIID = (IMAGE_IMPORT_DESCRIPTOR*)Interop.ImageDirectoryEntryToData((void*)hMod, mappedAsImage, Interop.IMAGE_DIRECTORY_ENTRY_IMPORT, out size);
                        if (pIID != null)
                        {
                            Console.WriteLine("Got Image Import Descriptor");
                            while (pIID->OriginalFirstThunk != 0)
                            {
                                try
                                {
                                    char* szName = (char*)(BaseAddress + pIID->Name);
                                    string name = Marshal.PtrToStringAnsi((IntPtr)szName);
                                    Console.WriteLine("pIID->Name = {0} BaseAddress - {1}", name, (uint)BaseAddress);

                                    THUNK_DATA* pThunkOrg = (THUNK_DATA*)(BaseAddress + pIID->OriginalFirstThunk);

                                    while (pThunkOrg->AddressOfData != 0)
                                    {
                                        char* szImportName;
                                        uint Ord;

                                        if ((pThunkOrg->Ordinal & 0x80000000) > 0)
                                        {
                                            Ord = pThunkOrg->Ordinal & 0xffff;
                                            Console.WriteLine("imports ({0}).Ordinal{1} - Address: {2}", name, Ord, pThunkOrg->Function);
                                        }
                                        else
                                        {
                                            IMAGE_IMPORT_BY_NAME* pIBN = (IMAGE_IMPORT_BY_NAME*)(BaseAddress + pThunkOrg->AddressOfData);

                                            if (!Interop.IsBadReadPtr((void*)pIBN, (uint)sizeof(IMAGE_IMPORT_BY_NAME)))
                                            {
                                                Ord = pIBN->Hint;
                                                szImportName = (char*)pIBN->Name;
                                                string sImportName = Marshal.PtrToStringAnsi((IntPtr)szImportName); // yes i know i am a lazy ass
                                                Console.WriteLine("imports ({0}).{1}@{2} - Address: {3}", name, sImportName, Ord, pThunkOrg->Function);
                                            }
                                            else
                                            {
                                                Console.WriteLine("Bad ReadPtr Detected or EOF on Imports");
                                                break;
                                            }
                                        }

                                        pThunkOrg++;
                                    }
                                }
                                catch (AccessViolationException e)
                                {
                                    Console.WriteLine("An Access violation occured\n" +
                                                      "this seems to suggest the end of the imports section\n");
                                    Console.WriteLine(e);
                                }

                                pIID++;
                            }

                        }

                    }
                }
            }

            Console.WriteLine("Press Any Key To Continue......");
            Console.ReadKey();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何以编程方式读取 C# 中的本机 DLL 导入? 的相关文章

  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • .NET 中是否有内置函数可以对密码进行哈希处理?

    我看到这个问题加密 散列数据库中的纯文本密码 https stackoverflow com questions 287517 encrypting hashing plain text passwords in database 我知道我
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐

  • 模板类型检查 C++

    我有一个接受对象的模板函数 我需要确定该对象是否派生自特定基类 如果它是从基类派生的 我需要调用附加函数 无论如何我可以在 C Linux 中做到这一点吗 class baseA class derivedA baseA class tes
  • 如何在手动按单个片段的后退按钮时返回到上一个片段?

    我只有一个activity和多个fragments在我的应用程序中 两个主要片段A 左 和B 右 Fragment A1 called from A B1 called from B B2 called from B1 All fragme
  • 将 String 转换为 Double 时的双精度无效

    我得到一个 NumberFormatException 这行代码中的双 111 000 000 无效 double SalePotential Double valueOf EtPotential getText toString 一开始
  • PHP 如何在没有 HTML 标签的情况下进行回显

    我有一种系统 每个人都可以输入他想要的任何内容 不过 他们似乎也可以使用诸如 img src a href a etc 你怎样才能完全防止这种情况发生呢 举例来说 如果有人输入 h1 Hello h1 文字不会变大 但只会显示 h1 Hel
  • 在 MS Access 和 SQL Server 中处理图片

    具体是如何进行的 将图像 图片存入 SQL 数据库 使用 MS Access 表单查看 SQL 数据库中的图片 我目前在两个数据库之间使用 ODBC 链接 没有任何问题 但我很难理解我需要做什么才能实现我想要实现的目标 我已经尝试过谷歌 但
  • 如果使用 vb 脚本调用宏将被禁用

    我正在尝试使用 vbs 调用我的 Excel 宏 这是我的代码片段 Set objExcel CreateObject Excel Application Set objWorkbook objExcel Workbooks Open C
  • Android JNI字符串加密/解密

    我正在尝试在本机代码 C 中进行 aes 加密 解密 加密确实有效 但是当我尝试解密字符串时 它最终不会成为原始字符串 下面是基于模式参数进行加密 解密的 JNI 方法 jbyteArray Java com example hellojn
  • 读取崩溃日志

    我看到抛出了 ArrayIndexOutOfBounds 异常 但代码中的以下几行有三种不同的方法 我将如何阅读日志来找出以下哪一行抛出了错误 请指教 这是写入加密存储的一个例外 它是由密码抛出的 目前尚不清楚为什么失败或由于什么操作而失败
  • 通过代码从最近的菜单中排除活动

    我需要排除某个活动出现在最近启动的菜单中 但我无法添加android excludeFromRecents true in AndroidManifest xml 我必须在运行时执行此操作 有谁知道是否可以设置FLAG EXCLUDE FR
  • JSON 嵌套太深...我应该切换到 XML 吗?

    我收到一个 JSONException 抱怨嵌套非常深 超过 30 个 我知道该值是在 JSONWriter 中硬编码的 我能做什么最好 如果存在这种情况 请使用另一个没有此限制的库 切换到 XML UPDATE 我正在将带标签的树结构序列
  • SQLite 删除表别名[重复]

    这个问题在这里已经有答案了 我正在尝试为 SQLite 中的表添加别名 例如通过以下命令 它来自我正在阅读的 Ramakrishnan 的数据库管理系统 一书 DELETE FROM Students S WHERE S sid 12546
  • 无法理解 JavaScript 中删除变量的行为

    问题是这样的 var x 5 window x x true x as it seems is a property of window delete x false delete window x false BUT window x 5
  • 如何在 Java 中解析 iCal RRULE [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我有以下内容iCal 重复规则例子 RRULE FREQ YEARLY INTERVAL 2 RRULE FREQ WEEKLY INTERVAL
  • 如何在 ~/.gdbinit 中设置这些断点?

    以下是放置在 gdbinit 中的断点列表 它们对于调试内存问题非常有帮助 fb NSException raise fb NSAssertionHandler handleFailureInFunction file lineNumber
  • Android 示例评论BEGIN_INCLUDE END_INCLUDE

    在阅读一些 Android 示例时 我通常会看到类似的评论 BEGIN INCLUDE something END INCLUDE something 但是 我当前的 IDE Android Studio 1 1 无法识别它们 或者可能是我
  • Python a、b = b、a +b

    这是我的第一个问题 我开始学习Python 之间有区别吗 a b b a b and a b b a b 当您在下面的示例中编写它时 它会显示不同的结果 def fib n a b 0 1 while a lt n print a end
  • 二元运算符 + 不能应用于 CGfloat int 类型的操作数

    我遇到了与之前相同的问题 但使用了不同的代码行 但这一次 我无法使用与上次相同的方法修复它 var Y Int 0 var X Int 0 IBOutlet var ball UIImageView ball center CGPointM
  • 使用 BufferedImage 和 ImageIO 将图像转换为 byte[] 后图像大小减小

    我正在使用以下代码将图像转换为 byte public static byte extractBytes String ImageName throws IOException ByteArrayOutputStream baos new
  • Chrome 扩展 API:后台页面上的 chrome.tabs.captureVisibleTab 到内容脚本

    我的总体目标是使用以下方法通过后台页面截取屏幕截图 http developer chrome com extensions tabs html method captureVisibleTab 并将其传递给内容脚本 以便我可以使用页面的
  • 如何以编程方式读取 C# 中的本机 DLL 导入?

    如何以编程方式分析本机 DLL 以读取其导入 编辑 我原来的问题如下所示 以及大量有缺陷的代码 请参阅下面的答案以获得更正确的代码 C 代码位于这个链接旨在打印本机 DLL 的导入 我发现当我使用原始示例的目标 MSCOREE DLL 运行