首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用P/Invoke (System.AccessViolationException)的内存分配

使用P/Invoke (System.AccessViolationException)的内存分配
EN

Stack Overflow用户
提问于 2022-07-22 23:01:34
回答 1查看 79关注 0票数 1

我试图通过使用C#代码将内存地址解析为权限,将以下X64位编译为X64位。

代码语言:javascript
运行
复制
namespace ConsoleApp2
{
public class Program
{

    //Open Process Token Starts Here

    public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
    public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
    public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
    public const UInt32 TOKEN_DUPLICATE = 0x0002;
    public const UInt32 TOKEN_IMPERSONATE = 0x0004;
    public const UInt32 TOKEN_QUERY = 0x0008;
    public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
    public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
    public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
    public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
    public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
    public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
    public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
                TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
                TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
                TOKEN_ADJUST_SESSIONID);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, ref IntPtr TokenHandle);

    //Open Prcoess Token Ends Here
    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public uint LowPart;
        public uint HighPart;
    }
    public struct TOKEN_PRIVILEGES
    {
        public int PrivilegeCount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        public LUID_AND_ATTRIBUTES[] Privileges;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID_AND_ATTRIBUTES
    {
        public LUID Luid;
        public UInt32 Attributes;
    }
    //Token Privileges



    //GetTokenInformation Starts Here


    enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        TokenIsAppContainer,
        TokenCapabilities,
        TokenAppContainerSid,
        TokenAppContainerNumber,
        TokenUserClaimAttributes,
        TokenDeviceClaimAttributes,
        TokenRestrictedUserClaimAttributes,
        TokenRestrictedDeviceClaimAttributes,
        TokenDeviceGroups,
        TokenRestrictedDeviceGroups,
        TokenSecurityAttributes,
        TokenIsRestricted,
        TokenProcessTrustLevel,
        TokenPrivateNameSpace,
        TokenSingletonAttributes,
        TokenBnoIsolation,
        TokenChildProcessFlags,
        TokenIsLessPrivilegedAppContainer,
        TokenIsSandboxed,
        TokenIsAppSilo,
        MaxTokenInfoClass
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, long TokenInformationLength, ref long ReturnLength);

    //GetTokenInformation Ends Here

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool LookupPrivilegeName(
   string lpSystemName,
   IntPtr lpLuid,
   [param: MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpName,
   ref long cchName);

    public static void Main()
    {
        IntPtr hwnd = Process.GetCurrentProcess().Handle;
        IntPtr TokenHandle = IntPtr.Zero;
        OpenProcessToken(hwnd, TOKEN_READ, ref TokenHandle);

        long ReturnLength = 0;
        GetTokenInformation(TokenHandle, TOKEN_INFORMATION_CLASS.TokenPrivileges, IntPtr.Zero, 0, ref ReturnLength);

        IntPtr elevationptr = Marshal.AllocHGlobal(64);
        long TokenInformationLength = 64;
        GetTokenInformation(TokenHandle, TOKEN_INFORMATION_CLASS.TokenPrivileges, elevationptr, TokenInformationLength, ref TokenInformationLength);
        TOKEN_PRIVILEGES tp = (TOKEN_PRIVILEGES)Marshal.PtrToStructure(elevationptr, typeof(TOKEN_PRIVILEGES));

        IntPtr startingptr = new IntPtr(elevationptr.ToInt64() + sizeof(uint));

        for (int i = 0; i < tp.PrivilegeCount; i++)
        {
            IntPtr tempptr = new IntPtr(startingptr.ToInt64() + i * Marshal.SizeOf(typeof(LUID_AND_ATTRIBUTES)));
            LUID_AND_ATTRIBUTES laa = (LUID_AND_ATTRIBUTES)Marshal.PtrToStructure(tempptr, typeof(LUID_AND_ATTRIBUTES));
            IntPtr luidptr = Marshal.AllocHGlobal(Marshal.SizeOf(laa.Luid));
            Marshal.StructureToPtr(laa.Luid, luidptr, true);
            StringBuilder sb = new StringBuilder(50);
            long cchname = 50;
            // Console.WriteLine("[1]LUIDPTR: {0}", luidptr);
            LookupPrivilegeName(null, luidptr, sb, ref cchname);
            //Console.WriteLine("[2]cchname: {0}", cchname);
            Console.WriteLine(sb);
            Marshal.FreeHGlobal(luidptr);
         
        }
        Console.Read();
    }

}

}

虽然"tp.PrivilegeCount“是5,但是程序在第三循环中崩溃。

通过使用断点进行调试,发现LookupPrivilegeName试图访问"luidptr“内存地址,但由于以下错误而被阻塞-

代码语言:javascript
运行
复制
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

这显然是内存分配问题,但我不知道我遗漏了什么。

编辑:--我已经更新了程序在X64 arch上工作的代码,但是一旦尝试,它就会崩溃/打印所有特权/不打印任何内容。

EN

回答 1

Stack Overflow用户

发布于 2022-07-24 04:55:30

您需要为SizeParamIndex声明StringBuilder。您可以将lpLuid作为in参数传递。

  • cchName应该是ref int
  • 使用SafeProcessHandle表示OpenProcessToken
  • 明显缺乏错误处理。你在任何地方都需要usingtry finally,也需要把Marshal.GetLastWin32Error()扔到需要的地方。
  • 您正在泄漏大量的HGlobal内存,您需要释放它。
  • 使用64代替ReturnLength
  • 整个TOKEN_PRIVILEGES结构是浪费时间的,因为它是动态大小的。由于您正在手动编组它,您还可以使用ReadInt32
  • 使用PtrToStructure的泛型形式。
代码语言:javascript
运行
复制
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out SafeProcessHandle TokenHandle);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool LookupPrivilegeName(
   [MarshalAs(UnmanagedType.LPTStr)] string lpSystemName,
   in LUID lpLuid,
   [Out, MarshalAs(UnmanagedType.LPTStr, SizeParamIndex = 3)] StringBuilder lpName,
   ref int cchName);

以下是更新的代码:

代码语言:javascript
运行
复制
public static void Main()
{
    IntPtr hwnd = Process.GetCurrentProcess().Handle;
    SafeProcessHandle TokenHandle;
    OpenProcessToken(hwnd, TOKEN_READ, out TokenHandle);
    if(TokenHandle.IsInvalid)
        throw new Win32Exception(Marshal.GetLastWin32Error());
    using(TokenHandle)
    {
        if(!GetTokenInformation(TokenHandle, TOKEN_INFORMATION_CLASS.TokenPrivileges, IntPtr.Zero, 0, out var ReturnLength))
            throw new Win32Exception(Marshal.GetLastWin32Error());

        IntPtr elevationptr = IntPtr.Zero;
        try
        {
            elevationptr = Marshal.AllocHGlobal(ReturnLength);
            if(!GetTokenInformation(TokenHandle, TOKEN_INFORMATION_CLASS.TokenPrivileges, elevationptr, ReturnLength, out var ReturnLength))
                throw new Win32Exception(Marshal.GetLastWin32Error());

            var startingptr = new IntPtr(elevationptr.ToInt64() + sizeof(uint));
            var count = Marshal.ReadInt32(elevationptr);

            for (int i = 0; i < count; i++)
            {
                var tempptr = new IntPtr(startingptr.ToInt64() + i * Marshal.SizeOf(typeof(LUID_AND_ATTRIBUTES)));
                var laa = Marshal.PtrToStructure<LUID_AND_ATTRIBUTES>(tempptr);
                var sb = new StringBuilder(50);
                int cchname = sb.Length;
                // Console.WriteLine("[1]LUIDPTR: {0}", luidptr);
                if(!LookupPrivilegeName(null, in luidptr, sb, ref cchname))
                    throw new Win32Exception(Marshal.GetLastWin32Error());

                //Console.WriteLine("[2]cchname: {0}", cchname);
                Console.WriteLine(sb);
            }
        }
        finally
        {
            Marshal.FreeHGlobal(elevationptr);
        }
    }
    Console.Read();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73086803

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档