C# 实现从签名文件中获取 SignedCms

2023-12-05

我正在使用 C++ CRYPT32.DLL 实现从签名的 c# 程序集 dll 中提取 SignedCms 对象。

signed c# assembly

用于签署 dll 的证书已过期,但内部具有有效的证书链。重要的是该证书由我都想提取的三个证书组成。

CertificateChain

    private static readonly int CERT_QUERY_OBJECT_FILE = 0x00000001;
    private static readonly int CERT_QUERY_CONTENT_FLAG_ALL = 0x00003ffe;
    private static readonly int CERT_QUERY_FORMAT_FLAG_ALL = 0x0000000e;
    private static readonly int CMSG_ENCODED_MESSAGE = 29;

    [DllImport("CRYPT32.DLL", EntryPoint = "CryptQueryObject", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CryptQueryObject(
        int dwObjectType,
        IntPtr pvObject,
        int dwExpectedContentTypeFlags,
        int dwExpectedFormatTypeFlags,
        int dwFlags,
        IntPtr pdwMsgAndCertEncodingType,
        IntPtr pdwContentType,
        IntPtr pdwFormatType,
        IntPtr phCertStore,
        IntPtr phMsg,
        IntPtr ppvContext
    );

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CryptMsgGetParam(
        IntPtr hCryptMsg, int dwParamType, int dwIndex, IntPtr pvData, ref int pcbData );

    public static SignedCms GetSignedCmsFromFile(string fileName)
    {
        var pvObject = Marshal.StringToHGlobalUni(fileName);
        var phMessage = Marshal.AllocHGlobal(IntPtr.Size);
        var pvData = IntPtr.Zero;

        try
        {
            SignedCms signedCms = null;
            var success = CryptQueryObject(
                CERT_QUERY_OBJECT_FILE,
                pvObject,
                CERT_QUERY_CONTENT_FLAG_ALL,
                CERT_QUERY_FORMAT_FLAG_ALL,
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                phMessage,
                IntPtr.Zero);

            if (success)
            {
                var hMessage = Marshal.ReadIntPtr(phMessage);
                var cbData = 0;
                success = CryptMsgGetParam(
                    hMessage,
                    CMSG_ENCODED_MESSAGE,
                    0,
                    IntPtr.Zero,
                    ref cbData);

                if (success)
                {
                    var data = new byte[cbData];
                    pvData = Marshal.AllocHGlobal(sizeof(byte) * data.Length);

                    success = CryptMsgGetParam(
                        hMessage,
                        CMSG_ENCODED_MESSAGE,
                        0,
                        pvData,
                        ref cbData);

                    if (success)
                    {
                        Marshal.Copy(pvData, data, 0, cbData);
                        signedCms = new SignedCms();

                        try
                        {
                            signedCms.Decode(data);
                            File.WriteAllBytes(fileName + ".export", data);
                        }
                        catch (CryptographicException)
                        {
                            signedCms = null;
                        }
                    }
                }
            }

            return signedCms;
        }
        finally
        {
            if (pvObject != IntPtr.Zero)
                Marshal.FreeHGlobal(pvObject);

            if (phMessage != IntPtr.Zero)
                Marshal.FreeHGlobal(phMessage);

            if (pvData != IntPtr.Zero)
                Marshal.FreeHGlobal(pvData);
        }
    }

该函数工作得很好,但由于 crypt32.dll 函数已被废弃,我正在寻找一个纯 C# 实现,它可以执行相同的操作并提供 SignedCms 对象。

到目前为止我能找到的最接近的是 X509Certificate。

X509Certificate2 cert = new X509Certificate2(fileName)

CryptQueryObject 函数


Solution

感谢下面的帖子,我可以实现一个纯 C# 方法来提取 SignedCms。

唯一不完美的是 startindex 偏移了 8 个字节,大小也小了 10 个字节。

    public static SignedCms GetSignedCmsFromFile(string fileName)
    {
        var result = new SignedCms();

        uint startIndex = 0;
        uint size = 0;

        var reader = new PeHeaderReader(fileName);
        if (reader.Is32BitHeader)
        {
            startIndex = reader.OptionalHeader32.CertificateTable.VirtualAddress;
            size = reader.OptionalHeader32.CertificateTable.Size;
        }
        else
        {
            startIndex = reader.OptionalHeader64.CertificateTable.VirtualAddress;
            size = reader.OptionalHeader64.CertificateTable.Size;
        }

        //var data = File.ReadAllBytes(fileName).Skip((int)startIndex).Take((int)size).ToArray();

        //Somehow the start index and size are not fitting perfectly and I have to adapt them
        var data = File.ReadAllBytes(fileName).Skip((int)startIndex + 8).Take((int)size - 10).ToArray();

        result.Decode(data);

        return result;
    }

我还没有找到相当于该调用的 CNG,但这是规格这应该让您提取 PKCS#7,这是 SignedCms 的字节:

Signature in executable

规范说:

Authenticode 签名可以“嵌入”到 Windows PE 文件中 由可选标头中的证书表条目指定的位置 数据目录

以下是 PE 标头中字节的精彩概述: -https://resources.infosecinstitute.com/presenting-the-pe-header/ - https://www.red-gate.com/simple-talk/blogs/anatomy-of-a-net- assembly-pe-headers/

以及几乎所有细节:https://blog.kowalczyk.info/articles/pefileformat.html

在 github 上我找到了一个读取 PE 标头的托管示例:https://gist.github.com/augustoproiete/b51f29f74f5f5b2c59c39e47a8afc3a3

EDIT:根据 @martin-s 的评论,github 上的代码并不可靠,他用这个替代方案成功了:

https://github.com/secana/PeNet

所有部件组合在一起应该可以完成这项工作。

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

C# 实现从签名文件中获取 SignedCms 的相关文章

  • 向进度条添加百分比文本 C#

    我有一个方法可以显示进程栏何时正在执行以及何时成功完成 我工作得很好 但我想添加一个百分比 如果完成 则显示 100 如果卡在某个地方 则显示更少 我在网上做了一些研究 但我无法适应我正在寻找的解决方案 这是我的代码 private voi
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • 如何在c++中读取pcap文件来获取数据包信息?

    我想用 C 编写一个程序来读取 pcap 文件并获取数据包的信息 例如 len sourc ip flags 等 现在我找到了如下代码 我认为它会帮助我获取信息 但是我有一些疑问 首先我想知道应该将哪个库添加到我的程序中 然后什么是 pca
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 在一个平台上,对于所有数据类型,所有数据指针的大小是否相同? [复制]

    这个问题在这里已经有答案了 Are char int long 甚至long long 大小相同 在给定平台上 不能保证它们的大小相同 尽管在我有使用经验的平台上它们通常是相同的 C 2011 在线草稿 http www open std
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 为什么 gcc 抱怨“错误:模板参数 '0' 的类型 'intT' 取决于模板参数”?

    我的编译器是gcc 4 9 0 以下代码无法编译 template
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看
  • 当从finally中抛出异常时,Catch块不会被评估

    出现这个问题的原因是之前在 NET 4 0 中运行的代码在 NET 4 5 中因未处理的异常而失败 部分原因是 try finallys 如果您想了解详细信息 请阅读更多内容微软连接 https connect microsoft com

随机推荐

  • 从 https 中删除 www

    我正在尝试找到一个 htaccess 重写来删除 www 仅来自 https 页面 我发现的每篇文章都删除了所有页面的 www 我需要在 htaccess 中添加什么来执行此操作 https www mydomain com应该https
  • 当行值等于“yes”时连接 Google 表格中的标题值的数组公式

    I saw this问题但无法让它为我工作 因为它已经得到回答 并且从一年前开始 我觉得最好发布一个新问题 我有一个样本表 https docs google com spreadsheets d 1EqNfTWcNFgkv2gdovnH7
  • 返回多个变量以在 Laravel 中查看的最佳方法

    我有一个操作方法 其主体中有多个变量 如下所示 bus Bus all user User all employer employer all 将这些变量对象返回到视图正在做的事情是使用这样的代码 return view create gt
  • 使用 Nodejs 的 SendGrid 模板中的变量替换不起作用

    继USE CASE在 SendGrids github 上确实设法向我发送带有正确模板的电子邮件 但替换显然不起作用 并且在生成的电子邮件中留空 服务器端 const sgmailer require sendgrid mail sgmai
  • 使用 Protractor 设置 Angular 模型

    我正在尝试使用 Protractor 在我的网站上模拟用户故事 用户必须输入使用自动完成功能的输入 在现实生活中 用户必须在输入中键入一些文本 然后使用鼠标或更自然地使用向下箭头键选择正确的命题 问题是我似乎无法用 Protractor 来
  • 什么是 WINAPI_FAMILY_ONECORE_APP?

    我正在 GitHub 上查看 Microsoft 的 OpenSSL 端口 有一个提交引起了我的注意 那就是添加Win10通用平台支持 在提交中 一个名为WINAPI FAMILY ONECORE APP出现 然而 我在搜索时并没有找到太多
  • 如何禁用来自其他域的WebService调用

    我想避免其他人访问我的网络服务 我有一个名为 WebService asmx 的 Web 服务 它托管在 www xyz com 上 我们知道我们可以访问该服务 例如http www xyz com WebService asmx 如何避免
  • 如何强制Dotnet6桌面Winforms应用程序使用appsettings.json而不是Settings.settings?

    如何强制 Dotnet6 桌面 Winforms 应用程序使用 appsettings json 而不是 Settings settings App config 如果我在 Visual Studio 2022 中创建一个新的桌面应用程序以
  • 使用 Apache POI 打开 .xlsx 文件时出现异常

    我一直在开发一个 Android 应用程序 其中我必须打开 xls 和 xlsx 文件才能进一步实现 如果是 xls 一切工作正常 但当我尝试打开 xls x 文件时 它给了我异常 下面是我的代码 请帮我解决这些异常 Override pr
  • 使用PHP数组将数据插入MYSQL

    你好 我正在尝试使用数组在 mysql 中插入数据 有人可以看看我的代码吗 我似乎无法让它工作 这是我的post php POST PHP post id somefunction title POST title body POST bo
  • java -fullversion 中的 b 表示什么?

    当我们使用java 完整版本 我们得到像 java 完整版这样的输出 1 7 0 45 b18 这是什么b18在java完整版中 我仔细阅读了一些 oracle java 文章 其中指出它表示构建版本 那么这个构建版本应该是什么 我还看到一
  • 集合如何对元素类型使用隐式转换?

    在工作的同时这个问题 我提出了以下问题 考虑两个方法定义 def foo T lt Ordered T s Seq T s sorted def foo T
  • 减小 .png 文件的大小是否会对内存中的位图产生影响

    我正在用大量的PNG图片编写游戏 一切都很好 比我添加新活动WebView并出现内存不足的情况 之后我做了一些实验 用刚刚完全填充一些颜色的图像替换游戏 PNG 图像 结果内存短缺问题就消失了 但我想Bitmap在内部单独保存每个像素 因此
  • 如何在代码块中启用 c++17 支持

    在 codeblocks 的 Build 或 Compiler 选项中没有 C 17 选项 只有 C 14 我如何在代码块中启用它 以便编码工具和编译器都支持它 代码 块 is not一个编译器 但有些人美化了源代码编辑器 有时也称自己为I
  • 串行队列上的dispatch_async和dispatch_sync之间的区别?

    我创建了一个像这样的串行队列 dispatch queue t serialQueue dispatch queue create com example name DISPATCH QUEUE SERIAL 有什么区别dispatch a
  • 如何按到给定点的距离对点列表进行排序?

    我有一个项目清单X and Y坐标 现在 有一种方法需要X and Y参数 并应返回根据给定参数从最近到最远排序的坐标列表 基本上 它看起来像这样 class Point x 0 0 y 0 0 List of points points
  • 如何在Python中的列表中获取某个内容之后的项目?

    我正在使用 textblob 来解析英文文本 这是单词列表 Get coffee and water here 我想在名为 list1 的新列表中获取项目 Get 之后的所有单词 我想在名为 list2 的新列表中获取 Get 和 here
  • Facebook FXBML 自昨天起未渲染(IFRAME Canvas)

    从昨天开始 我的应用程序没有渲染 xfbml 标签 名称和图片 我正在 Canvas Iframe 应用程序中使用新的 JavaScript SDK Firebug 在控制台中告诉我以下内容 Get http 0 channel20 fac
  • 基于另一个但具有不同 API 的 Swing 组件创建一个 Swing 组件

    我想基于现有的 Swing JComponent 创建一个新的 Swing JComponent 但使用不同的 API 换句话说 我不想扩展现有组件 因为我不希望它的 API 可供访问 这是一个例子来阐明我的需求 替代品JCheckBox显
  • C# 实现从签名文件中获取 SignedCms

    我正在使用 C CRYPT32 DLL 实现从签名的 c 程序集 dll 中提取 SignedCms 对象 用于签署 dll 的证书已过期 但内部具有有效的证书链 重要的是该证书由我都想提取的三个证书组成 private static re