安全字符串如何编组为非托管代码?

发布于 2024-08-06 08:08:36 字数 211 浏览 7 评论 0原文

是什么引发了这个问题: 我正在尝试更改运行 Windows 服务的帐户。我决定使用 win32 api 而不是 WMI,并开始研究 ChangeServiceConfig。

我认为我可以简单地在非托管方法签名中使用 SecureString 类型,并且它可以正常工作。嗯,不完全是。这让我想知道,有谁知道 SecureString 类(默认情况下)编组为非托管代码的本机(win32)类型吗?

What prompted this question:
I'm trying to change the account under which a windows service runs. I decided to use the win32 api rather than WMI and started looking at ChangeServiceConfig.

I thought I could simply use the SecureString type in the unmanaged method signature and it would work fine. Hmmm, not quite. This made me wonder, does anyone know what native (win32) type the SecureString class is marshalled as (by default) to unmanaged code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

栀子花开つ 2024-08-13 08:08:36

我从未得到标题中问题的答案,所以我仍然不知道 SecureString 已编组为非托管代码。

然而,我确实通过使用其他一些答案中的建议来使我的代码正常工作。我提供了下面的代码。

internal static class NativeService
{
    ...
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ChangeServiceConfig(IntPtr hService, uint nServiceType, uint nStartType, uint nErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, string lpServiceStartName, IntPtr lpPassword, string lpDisplayName);
    ...
    public const uint SERVICE_NO_CHANGE = 0xffffffff;
}

internal class ClassThatConfiguresService
{
    ...
    public void ConfigureStartupAccount(IntPtr service, string userName, SecureString password)
    {
        passwordPointer = Marshal.SecureStringToGlobalAllocUnicode(password);
        try
        {
            if(!NativeService.ChangeServiceConfig(service, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, userName, passwordPointer, null))
                throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(passwordPointer);
        }
    }
    ...
}

我没有使用 Marshal.SecureStringToBSTR,而是使用了 Marshal.SecureStringToGlobalAllocUnicode,因为这是非托管函数所期望的,但除此之外,它还是一种享受。

希望其他人发现这很有用。
凯普。

I never got an answer to the question in the title, so I still don't know SecureString is marshalled to unmanaged code.

I did, however, get my code working by using the suggestions in some of the other answers. I have provided the code below.

internal static class NativeService
{
    ...
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ChangeServiceConfig(IntPtr hService, uint nServiceType, uint nStartType, uint nErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, string lpServiceStartName, IntPtr lpPassword, string lpDisplayName);
    ...
    public const uint SERVICE_NO_CHANGE = 0xffffffff;
}

internal class ClassThatConfiguresService
{
    ...
    public void ConfigureStartupAccount(IntPtr service, string userName, SecureString password)
    {
        passwordPointer = Marshal.SecureStringToGlobalAllocUnicode(password);
        try
        {
            if(!NativeService.ChangeServiceConfig(service, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, userName, passwordPointer, null))
                throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(passwordPointer);
        }
    }
    ...
}

Instead of Marshal.SecureStringToBSTR I used Marshal.SecureStringToGlobalAllocUnicode because thats's what the unmanaged function expects, but other than that it works a treat.

Hopefully someone else finds this useful.
Kep.

终弃我 2024-08-13 08:08:36

看起来您可以使用 InteropServices 命名空间中的辅助函数来帮助您完成此操作:

请注意,SecureString 没有成员
检查、比较或转换
SecureString 的值。缺席
此类成员的数量有助于保护
实例的偶然值
或恶意曝光。使用适当的
的成员
System.Runtime.InteropServices..::.Marshal
类,例如 SecureStringToBSTR
方法,操纵 a 的值
SecureString 对象。

您可以使用 SecureStringToBSTR 进行转换将字符串传递给 BSTR,然后将其传递给适当的函数以供使用。

It looks as though you can use the helper functions in the InteropServices namespace to assist you with this:

Note that SecureString has no members
that inspect, compare, or convert the
value of a SecureString. The absence
of such members helps protect the
value of the instance from accidental
or malicious exposure. Use appropriate
members of the
System.Runtime.InteropServices..::.Marshal
class, such as the SecureStringToBSTR
method, to manipulate the value of a
SecureString object.

You can use SecureStringToBSTR to convert the string to a BSTR, then pass it to an appropriate function for use.

天涯离梦残月幽梦 2024-08-13 08:08:36

SecureString 是一种 非 blittable 类型。所以 - 不存在 1:1 win32 类型。

请记住,我根本不是 COM 专家。

SecureString is a non-blittable type. So - there isn't a 1:1 win32 type.

Keep in mind that i'm not a COM expert at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文