【问题标题】:Marshal Unmanaged Unicode String in COM Task Allocator Memory to SecureString将 COM 任务分配器内存中的非托管 Unicode 字符串编组到 SecureString
【发布时间】:2017-09-05 19:57:41
【问题描述】:

我正在使用对 advapi32.dll 的 API 调用来管理 Windows 保存的凭据,以便自动化某些可以使用保存的凭据的 Windows 应用程序,这工作正常。

我正在尝试更新我的代码以在整个过程中使用SecureString 作为密码,因为我不需要在任何时候与密码中包含的文本进行交互,因此如果我的应用程序从不以明文形式保存密码,它应该会更安全文本。

我能够将 SecureString 编组到 COM 任务分配器内存以传递给 API 调用:

var unmanagedPassword = Marshal.SecureStringToCoTaskMemUnicode(userCredential.Password);

但是,当将该信息读回应用程序时,如果不将字符串复制到托管内存中,无论是作为字符串还是字节数组,我都找不到将这种非托管字符串编组回 SecureString 的方法.

有没有我忽略的安全方法?

【问题讨论】:

  • 投反对票的人是否愿意解释这个问题是一个“为什么它不起作用”而没有预期结果的问题?我在问如何做一些我找不到方法的事情。我想我已经清楚地说明了我需要什么。从非托管内存创建新的 SecureString。
  • 这是一个奇怪的疏忽。我想最简单的方法(没有非托管代码)是在Marshal.ReadInt16() 的循环中调用.AppendChar()(假设是Unicode 字符串)。还有一个不安全的构造函数,它带有一个char* 和一个长度。请注意,非托管内存应该清零并释放,否则使用SecureString 并没有多大意义,而所有数据仍以纯文本形式浮动。
  • 感谢@JeroenMostert,成功了!

标签: c# unmarshalling securestring unmanaged-memory


【解决方案1】:

非常感谢 Jeroen Mostert 的 cmets 导致了这个解决方案,它应该尽可能安全。

正如 Jeroen 所描述的,每个字符都被读取为 short,并一次附加到一个新的 SecureString

任务分配器内存中的非托管字符串以空值结尾,因此读取字符直到获得0。非托管二进制字符串以长度为前缀,因此需要对下面的代码稍作修改。

    var outString = new SecureString();
    outString.AppendChar('p');
    outString.AppendChar('a');
    outString.AppendChar('s');
    outString.AppendChar('s');
    outString.AppendChar('w');
    outString.AppendChar('o');
    outString.AppendChar('r');
    outString.AppendChar('d');
    var ptr = Marshal.SecureStringToCoTaskMemUnicode(outString);

    var inString = new SecureString();
    var i = 0;
    short c;

    while ((c = Marshal.ReadInt16(ptr, i)) != 0)
    {
        inString.AppendChar((char)c);
        i += 2;
    }

    Marshal.ZeroFreeCoTaskMemUnicode(ptr);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多