Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wtsapi32 and NtQueryValueKey functions #18

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

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