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 的相关文章

  • VLC 媒体播放器有 C# 界面吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以使用 C 控制台应用程序中的包装器从 VLC 播放中当前播放的文件中读取曲目统计信息 时间 标
  • EntityHydrate 任务失败

    我最近安装了 Visual Studio 11 Beta 和 Visual Studio 2010 之后 我无法在 Visual Studio 2010 中构建依赖于 PostSharp 的项目 因此我卸载了 Visual Studio 1
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • Boost ASIO 串行写入十六进制值

    我正在使用 ubuntu 通过串行端口与设备进行通信 所有消息都必须是十六进制值 我已经在 Windows 环境中使用白蚁测试了通信设置 并得到了我期望的响应 但在使用 Boost asio 时我无法得到任何响应 以下是我设置串口的方法 b
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • 为什么这个 makefile 在“make clean”上执行目标

    这是我当前的 makefile CXX g CXXFLAGS Wall O3 LDFLAGS TARGET testcpp SRCS main cpp object cpp foo cpp OBJS SRCS cpp o DEPS SRCS
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 来自嵌入图像的 BitmapSource

    我的目标是在 WPF 窗口上重写 OnRender 方法中绘制图像 someImage png 它是嵌入资源 protected override void OnRender System Windows Media DrawingCont
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来
  • ASP.NET Core 中间件与过滤器

    在阅读了 ASP NET Core 中间件之后 我对何时应该使用过滤器以及何时应该使用中间件感到困惑 因为它们似乎实现了相同的目标 什么时候应该使用中间件而不是过滤器 9频道有一个关于此的视频 ASP NET 怪物 91 中间件与过滤器 h
  • 当Model和ViewModel一模一样的时候怎么办?

    我想知道什么是最佳实践 我被告知要始终创建 ViewModel 并且永远不要使用核心模型类将数据传递到视图 这就说得通了 让我把事情分开 但什么是Model 和ViewModel一模一样 我应该重新创建另一个类还是只是使用它 我觉得我应该重
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • 调用 .ToArray() 时出现 ArgumentException

    我有一个经常被清除的列表 代码完全是这样的 VisitorAgent toPersist List
  • 如何在C#中控制datagridview光标移动

    我希望 datagridview 光标向右移动到下一列 而不是在向单元格输入数据后移动到下一行 我试图通过 dataGridView1 KeyDown 事件捕获键来控制光标 但这并不能阻止光标在将数据输入到单元格后移动到下一行 提前感谢你的
  • 在 C# 的 WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据

    我需要服务分块传输使用编码数据API控制器 因为我无权访问HttpContext or the Http请求 我有点不知道在哪里写入响应以及在哪里刷新它 设置如下 public class MyController ApiControlle
  • 从后面的代码添加外部 css 文件

    我有一个 CSS 文件 例如 SomeStyle css 我是否可以将此样式表文档从其代码隐藏应用到 aspx 页面 您可以将文字控件添加到标头控件中 Page Header Controls Add new System Web UI L
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有

随机推荐

  • 从 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