Skip to content

Conversation

@s0rtega
Copy link

@s0rtega s0rtega commented Jan 5, 2021

Description

I have added some functions / delegates for wtsapi32 (WTSOpenServerA, WTSEnumerateSessionsA, WTSDisconnectSession, WTSConnectSession) and ntdll (RtlMoveMemory, NtQueryValueKey). Hopefully I got the structure and the style properly, but all feedback is more than welcome because I would like to keep adding content.

Any better approach when importing functions? (e.g., wtsapi32 - https://github.com/s0rtega/DInvoke/blob/90a6d54dbe9b58af2e6ca4eab3e2a275456b7685/DInvoke/DInvoke/DynamicInvoke/Win32.cs#L93)

Test cases

NtQueryValueKey / RtlMoveMemory

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;

namespace dinvoke_pr
{
    class Program
    {
        static object[] parseInformation(byte[] information)
        {
            byte[] titleIndexArr = new byte[4];
            byte[] typeArr = new byte[4];
            byte[] nameLenArr = new byte[4];
            Array.Copy(information, 0, titleIndexArr, 0, 4);
            Array.Copy(information, 4, typeArr, 0, 4);
            Array.Copy(information, 8, nameLenArr, 0, 4);

            int titleIndex = BitConverter.ToInt32(titleIndexArr, 0);
            int type = BitConverter.ToInt32(typeArr, 0);
            int nameLen = BitConverter.ToInt32(nameLenArr, 0);

            byte[] nameArr = new byte[nameLen];
            Array.Copy(information, 12, nameArr, 0, nameLen);
            string name = Encoding.Unicode.GetString(nameArr);

            Object[] result =
            {
                titleIndex,
                type,
                nameLen,
                name
            };

            return result;
        }

        static void Main(string[] args)
        {
            String sid = WindowsIdentity.GetCurrent().User.ToString();
            string hive = @"\Registry\User\" + sid;
            String regKey = hive + @"\Environment";
            IntPtr keyHandle = IntPtr.Zero;

            DInvoke.Data.Native.OBJECT_ATTRIBUTES oa = new DInvoke.Data.Native.OBJECT_ATTRIBUTES();
            DInvoke.Data.Native.UNICODE_STRING UC_RegKey = new DInvoke.Data.Native.UNICODE_STRING();
            DInvoke.DynamicInvoke.Native.RtlInitUnicodeString(ref UC_RegKey, regKey);

            IntPtr oaObjectName = Marshal.AllocHGlobal(Marshal.SizeOf(UC_RegKey));
            Marshal.StructureToPtr(UC_RegKey, oaObjectName, true);
            oa.Length = Marshal.SizeOf(oa);
            oa.Attributes = (uint)DInvoke.Data.Native.OBJ_ATTRIBUTES.CASE_INSENSITIVE;
            oa.ObjectName = oaObjectName;
            oa.SecurityDescriptor = IntPtr.Zero;
            oa.SecurityQualityOfService = IntPtr.Zero;
            DInvoke.Data.Native.NTSTATUS retValue = new DInvoke.Data.Native.NTSTATUS();

            retValue = DInvoke.DynamicInvoke.Native.NtOpenKey(ref keyHandle, DInvoke.Data.Native.REG_ACCESS_MASK.KEY_ALL_ACCESS, ref oa);

            string keyValueName = "Path";

            DInvoke.Data.Native.UNICODE_STRING UC_RegKeyValueName = new DInvoke.Data.Native.UNICODE_STRING();
            DInvoke.DynamicInvoke.Native.RtlInitUnicodeString(ref UC_RegKeyValueName, keyValueName);

            int regSize = 2048;
            IntPtr regBufferPointer = Marshal.AllocHGlobal(regSize);
            int nLength = 0;

            retValue = DInvoke.DynamicInvoke.Native.NtQueryValueKey(keyHandle, UC_RegKeyValueName, DInvoke.Data.Native.KEY_INFORMATION_CLASS.KeyPartialInformation,
                                                                       ref regBufferPointer, regSize, ref nLength);

            if (retValue != DInvoke.Data.Native.NTSTATUS.ObjectNameNotFound)
            {
                byte[] baTemp = new byte[nLength];
                DInvoke.DynamicInvoke.Native.RtlMoveMemory(baTemp, regBufferPointer, nLength);
                object[] hkeyRegBasicInfo = parseInformation(baTemp);

                Console.WriteLine((string)hkeyRegBasicInfo[3]);
            }
        }
    }
}

WTS*

using System;
using System.Runtime.InteropServices;

namespace dinvoke_pr
{
    class Program
    {
        static void Main(string[] args)
        {
            int target_session = 3;
            string serverName = "localhost";
            IntPtr hServer = DInvoke.DynamicInvoke.Win32.WTSOpenServerA(serverName);
            
            IntPtr pSessions = IntPtr.Zero;
            int dwSessionCount = 0;
            int activeSession = 0;

            bool res = DInvoke.DynamicInvoke.Win32.WTSEnumerateSessionsA(IntPtr.Zero, 0,1, ref pSessions, ref dwSessionCount);

            IntPtr current = pSessions;
            for (int i = 0; i < dwSessionCount; ++i)
            {
                DInvoke.Data.Win32.wtsapi32.WTS_SESSION_INFO session_info = (DInvoke.Data.Win32.wtsapi32.WTS_SESSION_INFO)Marshal.PtrToStructure(current, 
                                                                                    typeof(DInvoke.Data.Win32.wtsapi32.WTS_SESSION_INFO));
                if (session_info.State == DInvoke.Data.Win32.wtsapi32.WTS_CONNECTSTATE_CLASS.WTSActive)
                    activeSession = session_info.SessionId;
                // Only available in .net +4.0
                current += Marshal.SizeOf(typeof(DInvoke.Data.Win32.wtsapi32.WTS_SESSION_INFO));
            }

            // requires SYSTEM
            res = DInvoke.DynamicInvoke.Win32.WTSDisconnectSession(IntPtr.Zero, target_session, false);
            res = DInvoke.DynamicInvoke.Win32.WTSConnectSession(target_session, activeSession, "", false);
        }
    }
}

@TheWover TheWover changed the base branch from main to dev September 15, 2021 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants