首页 > 编程问答 >Python CDLL 无法加载两次

Python CDLL 无法加载两次

时间:2024-07-30 06:16:11浏览次数:8  
标签:python

我正在尝试用 python 创建一个密码管理器,但遇到了一个问题,一旦加载了一种类型的 dll,我就无法加载不同的 dll,在这个示例中,我加载了一个 dll,并尝试解密加密的密码数据,它工作正常,直到我加载另一个不同的 nss3.dll 文件,此时它给我一个错误:

“过程入口点 HeapAlloc 无法位于动态链接库 C:\Program Files\Waterfox\nss3.dll 中”

我仅在加载多个 nss3.dll 文件后出现此错误,例如:

def DecryptFirefoxBased(Type,EncryptedPassword):
    EncryptedPassword = base64.b64decode(EncryptedPassword)
    nss3 = ctypes.CDLL(Paths[Type][1])
    nss_init = nss3.NSS_Init
    nss_init.argtypes = [ctypes.c_char_p]
    nss_init.restype = ctypes.c_int
    nss_init(ProfileDirectory.encode())
    pk11_sdr_decrypt = nss3.PK11SDR_Decrypt
    pk11_sdr_decrypt.argtypes = [ctypes.POINTER(SecItem), ctypes.POINTER(SecItem), ctypes.c_int]
    pk11_sdr_decrypt.restype = ctypes.c_int
    EncryptedItem = SecItem()
    EncryptedItem.data = ctypes.create_string_buffer(EncryptedPassword)
    EncryptedItem.len = len(EncryptedPassword)
    DecryptedItem = SecItem()
    decrypted_buffer = ctypes.create_string_buffer(len(EncryptedPassword))
    DecryptedItem.data = ctypes.cast(decrypted_buffer, ctypes.POINTER(ctypes.c_char))
    DecryptedItem.len = len(EncryptedPassword)
    ret = pk11_sdr_decrypt(ctypes.byref(EncryptedItem), ctypes.byref(DecryptedItem), 0)
    if ret != 0:
        input("PK11SDR_Decrypt failed")
    return ctypes.string_at(DecryptedItem.data, DecryptedItem.len).decode()

Paths[Type][1] = "C:\Users\me\Program Files\nss3.dll"

在参考中上面的内容被多次调用,每次加载不同的 dll,在它破坏的第二个不同的 nss3.dll 库上,这实际上是我能提供的所有信息,如果有人知道我为什么会收到此错误,请帮助我或提示为什么会发生这种情况,因为它真的开始激怒我。


你遇到的问题是,当你多次加载 nss3.dll 时,实际上并没有加载多个副本。Windows DLL 加载机制会确保每个 DLL 只加载一次。当你尝试加载已经加载的 DLL 时,Windows 只是返回了对已加载 DLL 的引用。

问题在于,当 ctypes.CDLL 加载 DLL 时,它会解析 DLL 中的所有函数指针。当你加载第二个 nss3.dll 时, ctypes.CDLL 会覆盖第一个 nss3.dll 中解析的函数指针,导致函数指针指向错误的地址。这就是你看到“过程入口点 HeapAlloc 无法位于动态链接库...中”错误的原因。

解决这个问题的方法是,为每个 nss3.dll 文件创建一个独立的加载器。你可以使用 ctypes.WinDLL 来实现这一点。 ctypes.WinDLL 不会解析所有函数指针,而是只在需要时才解析。这样,每个 nss3.dll 文件都会有自己的函数指针集,避免了冲突。

以下是修改后的代码:

import ctypes
import base64

def DecryptFirefoxBased(Type, EncryptedPassword):
    EncryptedPassword = base64.b64decode(EncryptedPassword)
    # 使用 WinDLL 加载 DLL
    nss3 = ctypes.WinDLL(Paths[Type][1])

    # 使用 GetProcAddress 获取函数指针
    nss_init = ctypes.WinDLL(Paths[Type][1]).NSS_Init
    nss_init.argtypes = [ctypes.c_char_p]
    nss_init.restype = ctypes.c_int
    nss_init(ProfileDirectory.encode())

    pk11_sdr_decrypt = ctypes.WinDLL(Paths[Type][1]).PK11SDR_Decrypt
    pk11_sdr_decrypt.argtypes = [ctypes.POINTER(SecItem), ctypes.POINTER(SecItem), ctypes.c_int]
    pk11_sdr_decrypt.restype = ctypes.c_int

    EncryptedItem = SecItem()
    EncryptedItem.data = ctypes.create_string_buffer(EncryptedPassword)
    EncryptedItem.len = len(EncryptedPassword)

    DecryptedItem = SecItem()
    decrypted_buffer = ctypes.create_string_buffer(len(EncryptedPassword))
    DecryptedItem.data = ctypes.cast(decrypted_buffer, ctypes.POINTER(ctypes.c_char))
    DecryptedItem.len = len(EncryptedPassword)

    ret = pk11_sdr_decrypt(ctypes.byref(EncryptedItem), ctypes.byref(DecryptedItem), 0)
    if ret != 0:
        input("PK11SDR_Decrypt failed")

    return ctypes.string_at(DecryptedItem.data, DecryptedItem.len).decode()

请注意,这段代码假设 SecItem 已经定义。

通过使用 ctypes.WinDLL ,你可以避免多次加载 DLL 时函数指针冲突的问题,从而解决你的问题。

标签:python
From: 78809165

相关文章

  • 你能将 HTTPS 功能添加到 python Flask Web 服务器吗?
    我正在尝试构建一个Web界面来模拟网络设备上的静态接口,该网络设备使用摘要式身份验证和HTTPS。我想出了如何将摘要式身份验证集成到Web服务器中,但我似乎无法找到如何使用FLASK获取https,如果您可以向我展示如何实现,请评论我需要使用下面的代码做什么来实现这一点。from......
  • Python:比较 csv 文件并打印相似之处
    我需要比较两个csv文件并打印出它们的相似之处。第一个文件有名称和浓度,第二个文件就像只有名称的“最佳”列表,我需要绘制相似性图表。例如,这就是我的列表的样子:file1-old_file.csvname_id,conc_test1,conc_test2name1,####,####name2,###......
  • Python 类交叉引用
    我用Python创建了一个数独游戏。我有一个:单元格类-“保存”数字可能性单元格组-保存单元格类实例我使用这些组在数独中运行行、列和正方形功能。每个单元格包含所有组,他属于classCell:def__init__(groups):self.groups=groupscla......
  • 如何修复我的 Python Azure Function DevOps Pipeline 上的“找到 1 个函数(自定义)加载
    我正在尝试使用AzureDevOps构建管道将PythonAzureFunction部署到Azure门户。由于某种原因,代码被部署到服务器,但我在尝试访问端点时收到404错误。我收到一个错误,显示1functionsfound(Custom)0functionsloaded,以及在服务器上显示ModuleNotFound......
  • 使用 kivy 从 python 脚本的 buildozer 构建 android apk 时出错
    我想从使用kivy包构建的Python脚本构建apk为此,我使用googlecollab.这里是main.py脚本:importyoutube_dlfromkivy.appimportAppfromkivy.uix.boxlayoutimportBoxLayoutfromkivy.uix.buttonimportButtonfromkivy.uix.tex......
  • 自动解码并检索 S/MIME 加密电子邮件的正文 (python)
    我如何:用python代码连接我的邮件收件箱以自动获取未读电子邮件的加密内容;解码S/MIME加密电子邮件(我有密钥);检索电子邮件正文纯文本;检查正文(或主题)是否与某个关键字(现在为“test”)匹配,并在匹配时打印一些内容;在树莓派上使用此代码,无需手动......
  • Python 3 写入 DBF(带有 Memo 的 dBase IV)
    我需要在Python3中写入带有备注字段的dBaseIVdbf文件,但找不到合适的模块来执行此操作。我尝试过的包:Simpledbf-只读dbf-不支持dBaseIVdbfpy-不支持Python3dbfpy3-不支持dBaseIVYDbf-不支持备注字段pyshp-无法仅使用dbf文件......
  • Robin-Stocks Python 中的 order_buy_fractional_by_price 问题
    我在Robin-StocksPython包中的order_buy_fractional_by_price函数中遇到问题。在正常市场交易时间内下达以美元为基础的买入订单时,该订单被错误地设置为限价订单。对我来说看起来有问题的代码似乎是导致此问题的原因。我尝试在包管理器中本地修改或删除有问题的代码,但遇......
  • 在python中使用turtle绘制图案(带点)
    我正在尝试使用python中的海龟制作一幅赫斯特画(点图案)。我设法实现了它。Hirst_painting_dot_pattern但是我的for循环没有按照我预期的方式工作。它省略了最后一次迭代。在下面的代码中,我的for循环没有生成最后一个点。因此,我在循环末尾添加了一行来制作最后......
  • 使用 Python 进行 QuantLib Vanilla 掉期定价 - 错误
    我真的需要帮助...我有一个使用QuantLib构建自己的VanillaSwapPricer的项目。我想根据ois掉期的市场价格进行计算以进行贴现,并根据Euribor6M掉期+FRA进行预测固定。总而言之,我的目标是尽可能接近彭博社对标准Euribor6M掉期的定价(贴现ois)-fwdEuribor6M)。......