如何使用硬件 ID 提取器修复 Ntdll.dll APPCRASH?

问题描述 投票:0回答:1

我正在使用来自 https://www.soft.tahionic.com/download-hdd_id/index.html 的硬件 ID 提取器库(用 Delphi 编写),目的是生成唯一的系统指纹。

这个库非常好,与我在市场上看到的任何其他库不同,但它的主要问题是它在与 .NET 应用程序一起运行时不稳定,这意味着它有时可以工作,有时则可以用于一些函数调用主应用程序崩溃,或者大多数时候应用程序在调用 dll 函数时立即崩溃。

正如该库的开发人员指出的(在我收到的最后一封支持电子邮件中),错误出在 ntdll.dll 上,正如我亲眼所见: enter image description here

以下是我创建的演示项目的链接,其目的是测试 dll 函数(因此,为了确保没有其他干扰,演示应用程序会执行此操作,并且仅执行此操作 - 它调用 dll 函数)。 http://www.mediafire.com/download/1jws7zh9218v88a/HardwareIdExtractDllTest.zip 该存档包含带有源代码的 Visual Studio 2013 项目和一个已编译的演示应用程序,如下所示: enter image description here

可以在此处找到 dll 包含的函数列表: https://www.soft.tahionic.com/download-hdd_id/hardware%20id%20programming%20source%20code/exported%20functions%20for%20non-Delphi.html

如果有人有知识并且愿意测试演示项目/应用程序以针对该问题进行测试或个人意见,然后与我分享可能的解决方案,我将不胜感激。

如果您认为可以采取任何措施,请告诉我是否可以采取任何措施来进一步帮助解决此问题。

编辑:这就是我声明 dll 函数的方式

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern bool EnterKey(int key);

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern bool IsCPUIDAvailable();

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern int GetCPUCount();

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern byte CoreNumber2CoreMask(byte cpuCore);

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetCPUID")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetCPUID(byte cpuCore);

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetCpuIdNow")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetCpuIdNow(); 

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetIDESerialNumber")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetIDESerialNumber(byte driveNumber);
c# pinvoke
1个回答
3
投票

失败的函数是返回

string
的函数。这样的 p/invoke 将返回值编组为指向以 null 结尾的字符数组的指针,然后对非托管代码返回的原始指针调用
CoTaskMemFree

字符串未在 COM 堆上分配的概率接近 1,因此错误可能出现在 C# p/invoke 声明中。 ntdll 中出现访问冲突是很有可能的。

因此,要取得进展,您需要修复 p/invoke 调用。我无法告诉您如何执行此操作,因为您没有显示非托管函数声明。或者,更重要的是,内存是如何分配的。


文档有一些线索

procedure ReleaseMemory (P: PAnsiChar); stdcall;
我认为这告诉我们 DLL 返回的字符串必须由 DLL 通过调用此函数来释放。大概是因为它们是由 DLL 的堆分配器分配的。

因此,使用

IntPtr

 作为返回文本的函数的返回类型。调用 
Marshal.PtrToStringAnsi
 转换为 C# 字符串。然后将指针传递给
ReleaseMemory

例如:

[DllImport(DllPath, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr GetCPUID(ushort CoreMask); [DllImport(DllPath, CallingConvention = CallingConvention.StdCall)] private static extern void ReleaseMemory(IntPtr P); .... IntPtr ptr = GetCPUID(CoreMask); string cpuid = Marshal.PtrToStringAnsi(ptr); ReleaseMemory(ptr);
    
© www.soinside.com 2019 - 2024. All rights reserved.