【问题标题】:Best way to implement plugin framework - are DLLs the only way (C/C++ project)?实现插件框架的最佳方式 - DLL 是唯一的方式(C/C++ 项目)吗?
【发布时间】:2010-05-10 12:12:39
【问题描述】:

简介:

我目前正在使用 C/C++ 开发文档分类器软件,我将使用朴素贝叶斯模型进行分类。但是我希望用户使用他们想要的任何算法(或者我将来想要的),因此我将架构中的算法部分分离为一个插件,该插件将附加到主应用程序@应用程序启动。因此,任何用户都可以将自己的算法编写为插件并将其与我的应用程序一起使用。

问题陈述:

我打算开发这个的方式是将用户想要使用的每个算法都制作成一个 DLL 文件并放入一个特定的目录中。一开始,我的应用程序将搜索该目录中的所有 DLL 并加载它们。

我的问题:

(1) 如果恶意代码被制作成 DLL(并且具有插件框架要求的相同功能)并放入我的插件目录怎么办?在这种情况下,我的应用程序会认为它是一个插件并选择它并调用它的函数,因此恶意代码很容易让我的整个应用程序崩溃(在最坏的情况下可能使我的应用程序成为恶意代码启动器!!!) .

(2) 使用 DLL 是实现插件设计模式的唯一方法吗? (不仅是因为害怕恶意插件,而且出于好奇,这是一个普遍的问题:))

(3) 我觉得很多软件都是用插件模型写的,是为了扩展性,如果是这样,他们如何防御这种攻击?

(4) 总的来说,您如何看待我决定使用插件模型来实现可扩展性(您认为我应该考虑其他替代方案吗?)

谢谢

-微内核:)

【问题讨论】:

  • 您的应用程序的主体是什么语言,C 还是 C++?您希望使用 C 或 C++ 编写扩展,还是两者兼而有之?
  • 除了 UI 部分,一切都在 C 中。所以,我希望扩展在 C 中。抱歉,我之前应该提到过。谢谢你:)

标签: c architecture dll plugins design-decisions


【解决方案1】:
  1. 不用担心恶意插件。如果有人设法将恶意 DLL 潜入该文件夹,他们可能也有权直接执行内容。

  2. 作为 DLL 的替代方案,您可以连接 Python 或 Lua 等脚本语言,并允许使用脚本插件。但也许在这种情况下你需要编译代码的速度?

    对于嵌入Python,请参阅here。这个过程不是很困难。您可以静态链接到解释器,因此用户无需在其系统上安装 Python。但是,任何非内置模块都需要随您的应用程序一起提供。

    但是,如果语言对您来说并不重要,那么嵌入 Lua 可能更容易,因为它是专门为该任务设计的。请参阅其手册中的this section

  3. 见 1。他们没有。

  4. 使用插件模型听起来是个不错的解决方案,但在这一点上,缺乏可扩展性确实是一个问题。如果事实证明确实需要它,那么对当前模型进行硬编码并稍后添加插件接口可能会更容易。它很容易添加,但一旦人们开始使用它就很难删除。

【讨论】:

  • 感谢您的回答 :) 您能否为我提供一些指导,让我开始将脚本语言与我的应用程序集成。 (如果我将 Python 与我的应用程序集成,那么 Python VM 不会成为我应用程序的依赖项吗?在大多数 Windows PC 中,用户不会拥有 Python !!!)或者是否有任何通用解释器可以配置我的目的并与我的应用程序一起编译?
  • Python 作为一种扩展语言非常棒,但如果您担心有大量的外部依赖项,请查看 Lua。它是专门作为扩展语言构建的,你可以在一小时内让它在你的应用程序中运行,而且它很小且独立。
  • @Microkernel:用一些额外的指针编辑了我的答案。
【解决方案2】:

恶意代码并不是 DLL 的唯一问题。即使是善意的 DLL 也可能包含可能导致整个应用程序崩溃或逐渐泄漏内存的错误。

以高级语言加载模块在一定程度上降低了风险。例如,如果你想了解嵌入 Python,documentation is here

另一种方法是在单独的进程中启动插件。它确实需要您付出更多的努力来实施,但它更安全。谷歌的Chrome浏览器采用的是分进程方式,他们有a document describing the architecture

基本思想是为插件编写者提供一个库,其中包含与主应用程序通信的所有逻辑。这样,插件作者就有了他们使用的 API,就像他们在编写 DLL 一样。维基百科有一个很好的list of ways for inter-process communication (IPC)

【讨论】:

  • “在单独的进程中启动插件”,看起来 gr8 的想法。感谢提及。
【解决方案3】:

1) 如果您的插件文件夹中有恶意 dll,您可能已经被入侵了。

2) 不,您可以从文件中动态加载汇编代码,但这只是在重新发明轮子,只需使用 DLL。

3) Firefox 扩展不会,即使它的 javascript 插件也不会。我所知道的其他一切都使用来自动态库的本机代码,因此无法保证安全。然后 Chrome 有 NaCL,它对二进制代码进行广泛的分析,如果不能 100% 确定它没有违反边界,则拒绝它,尽管我确信随着时间的推移它们会有越来越多的漏洞.

4) 插件很好,只需将它们限制为可信任的人。或者,您可以使用 LUA、Python、Java 等安全语言,并将文件加载到该语言中,但仅限于不会损害您的程序或环境的 API 子集。

【讨论】:

  • On 2) 操作系统可能会将程序数据标记为不可执行,从而阻止您将任意代码加载到程序空间中。我赞成只使用 DLL 的动议。
  • 嗯,您可以使用 VirtualProtect 将堆中的代码标记为可执行文件,这是大多数人为避免 DEP 或 NX 出现问题而采取的做法。但是,是的,DLL 很好。
【解决方案4】:

(1) 您能否使用操作系统安全设施来防止未经授权访问从其中搜索或加载 DLL 的文件夹?这应该是您的第一种方法。

否则:运行威胁分析 - 风险是什么,已知的攻击媒介是什么等。

(2) 不一定。如果您想要编译的插件,这是最直接的 - 这主要是性能问题,对操作系统功能的访问等。如前所述,请考虑脚本语言。

(3) 通常通过写“防止恶意代码执行,限制对插件文件夹的访问”。

(4) 有相当多的额外成本 - 即使使用您还不熟悉的插件框架。它增加了以下成本:

  • 核心应用程序(插件功能)
  • 插件(更高的隔离度)
  • 安装
  • 调试 + 诊断(仅在某些插件组合中出现的错误)
  • 管理(用户必须知道并管理插件)

只有当

  • 安装/更新主软件比更新插件复杂得多
  • 个别组件需要单独更新(例如,用户可以组合不同版本的插件)
  • 其他人为您的主应用程序开发插件

(将代码移动到 DLL 中还有其他好处,但它们与插件本身无关)

【讨论】:

  • 感谢您的回答 :) 您能否为我提供一些指导,让我开始将脚本语言与我的应用程序集成。 (如果我将 Python 与我的应用程序集成,那么这不会使 Python VM 作为我的应用程序的依赖项吗?在大多数 Windows PC 中,用户不会拥有 Python !!!)。或者是否有任何通用解释器可以用我的应用程序配置和编译?
  • 设置 Matt Curtis 对 Thomas 回复的评论。我也会这么说:)
【解决方案5】:

如果恶意代码被制作成 DLL 会怎样

通常,如果您不信任 dll,则无法以一种或另一种方式加载它。

这对于几乎任何其他语言来说都是正确的,即使它是被解释的。

Java 和某些语言非常努力地限制用户可以执行的操作,这仅是因为它们在虚拟机中运行。

所以没有。 DLL 加载的插件只能来自受信任的来源。

使用 DLL 是实现插件设计模式的唯一方法吗?

您也可以在代码中嵌入一些解​​释器,例如 GIMP 允许编写插件 在python中。

但请注意,这会慢得多,因为任何解释语言的性质。

【讨论】:

    【解决方案6】:

    我们有一个非常相似的产品,它使用模块来扩展功能。

    我们做两件事:

    1. 我们使用 BPL 文件,这些文件实际上是 DLL。这是来自 Borland/Codegear/Embarcadero 在 C++ Builder 中的一项特定技术。我们利用一些 RTTI 类型的特性发布了一个类似于 main (argv[]) 的简单 API,因此可以将任意数量的参数压入堆栈并由 DLL 弹出。

    2. 我们还将 PERL 嵌入到我们的应用程序中,以处理本质上更具业务逻辑的事物。

    我们的软件是会计/ERP 套件。

    【讨论】:

      【解决方案7】:

      查看现有的插件架构,看看是否有任何可以重用的东西。 http://git.dronelabs.com/ethos/about/ 是我在谷歌搜索 glib + 插件时遇到的一个链接。 glib 本身可能更容易开发插件架构。 Gstreamer 使用 glib 并且有一个非常好的插件架构,可能会给你一些想法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多