Blizzhackers

Return of the Jedi

* Login   * Register    * FAQ    * Search

Join us on IRC: #bh@irc.synirc.net (or Mibbit Web IRC)


MuleFactory


It is currently Wed Jun 19, 2013 4:57 am


All times are UTC [ DST ]





Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: C# Windows Server 2008 -- StartProcess not working well.
PostPosted: Fri Apr 01, 2011 11:06 pm 
 
User
User
User avatar

Joined: Wed Mar 07, 2007 10:37 am
Location: San Luis Obispo, CA
Hi All (e.g. probably lord2800! ;) )

So, I have this code. It's really, really fucking simple. All it does is sit in a DLL and open up basic programs when asked to do so. For instance, opening up telnet. Or ping.

It works perfectly great in Win 7, Vista, XP. It does not work in Windows Server 2008 and I have no idea why.

The heavy work comes in when I need to bypass Session 0 Isolation -- this is an issue for all later OSes including Win 7, Vista and Windows Server 2008. It appears there is more to it for 2008, though.

Anyway, some code:

using System;
using System.Reflection;
using System.Diagnostics;
using Microsoft.Win32;

using log4net;

namespace ExternalProgram
{
    public class Access
    {
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        String applicationName = String.Empty;
        bool result;

        public Access()
        {
            Logger.Debug("I am now in Access Constructor");
        }

        public void Telnet(string address)
        {
            Logger.Debug("I am now in Telnet");
            applicationName = "telnet.exe " + address;
            Logger.Debug(String.Format("Application Name: {0} ", applicationName));

            ApplicationLoader.PROCESS_INFORMATION procInfo;
            result = ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
            Logger.Debug(String.Format("Result of StartProcessAndBypassUAC: {0} ", result.ToString()));
        }

        public void Ping(string address)
        {
            Logger.Debug("I am now in Ping");
            //Process.Start("ping.exe", address + " -t");

            applicationName = "ping.exe " + address + " -t";
            Logger.Debug(String.Format("Application Name: {0} ", applicationName));

            ApplicationLoader.PROCESS_INFORMATION procInfo;
            result = ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
            Logger.Debug(String.Format("Result of StartProcessAndBypassUAC: {0} ", result.ToString()));
        }

        public void Putty(string address)
        {
            applicationName = "putty.exe " + address;

            ApplicationLoader.PROCESS_INFORMATION procInfo;
            ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
        }

        public void RemoteDesktop(string address)
        {
            applicationName = "mstsc.exe " + "/v " + address;

            ApplicationLoader.PROCESS_INFORMATION procInfo;
            ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
        }

        public void Browse(string address)
        {
            applicationName = GetDefaultBrowser() + " " + address;

            ApplicationLoader.PROCESS_INFORMATION procInfo;
            ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
        }

        private string GetDefaultBrowser()
        {
            string browser = string.Empty;
            RegistryKey key = null;

            try
            {
                key = Registry.ClassesRoot.OpenSubKey(@"HTTP\shell\open\command", false);

                //trim off quotes
                browser = key.GetValue(null).ToString().ToLower().Replace("\"", "");
                if (!browser.EndsWith("exe"))
                {
                    //get rid of everything after the ".exe"
                    browser = browser.Substring(0, browser.LastIndexOf(".exe") + 4);
                }
            }
            finally
            {
                if (key != null) key.Close();
            }
            return browser;
        }
    }
}



using System;
using System.Security;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
using log4net;

namespace ExternalProgram
{
    /// <summary>
    /// Class that allows running applications with full admin rights. In
    /// addition the application launched will bypass the Vista UAC prompt.
    /// </summary>
    public class ApplicationLoader
    {
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        #region Structures

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public int cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }

        #endregion

        #region Enumerations

        enum TOKEN_TYPE : int
        {
            TokenPrimary = 1,
            TokenImpersonation = 2
        }

        enum SECURITY_IMPERSONATION_LEVEL : int
        {
            SecurityAnonymous = 0,
            SecurityIdentification = 1,
            SecurityImpersonation = 2,
            SecurityDelegation = 3,
        }

        #endregion

        #region Constants

        public const int TOKEN_DUPLICATE = 0x0002;
        public const uint MAXIMUM_ALLOWED = 0x2000000;
        public const int CREATE_NEW_CONSOLE = 0x00000010;

        public const int IDLE_PRIORITY_CLASS = 0x40;
        public const int NORMAL_PRIORITY_CLASS = 0x20;
        public const int HIGH_PRIORITY_CLASS = 0x80;
        public const int REALTIME_PRIORITY_CLASS = 0x100;

        #endregion

        #region Win32 API Imports

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CloseHandle(IntPtr hSnapshot);

        [DllImport("kernel32.dll")]
        static extern uint WTSGetActiveConsoleSessionId();

        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
            String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("kernel32.dll")]
        static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);

        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
        public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
            int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);

        #endregion

        /// <summary>
        /// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
        /// </summary>
        /// <param name="applicationName">The name of the application to launch</param>
        /// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
        /// <returns></returns>
        public static bool StartProcessAndBypassUAC(String applicationName, out PROCESS_INFORMATION procInfo)
        {
            Logger.Debug("I am now in StarProcessAndBypassUAC");
            uint winlogonPid = 0;
            IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
            procInfo = new PROCESS_INFORMATION();
            Logger.Debug("Successfully created procInfo");

            // obtain the currently active session id; every logged on user in the system has a unique session id
            uint dwSessionId = WTSGetActiveConsoleSessionId();
            Logger.Debug(String.Format("dwSessionId: {0}", dwSessionId));

            // obtain the process id of the winlogon process that is running within the currently active session
            Process[] processes = Process.GetProcessesByName("winlogon");
            foreach (Process p in processes)
            {
                if ((uint)p.SessionId == dwSessionId)
                {
                    winlogonPid = (uint)p.Id;
                }
            }

            Logger.Debug(String.Format("winlogonPid: {0} (0 means not found)", winlogonPid));

            // obtain a handle to the winlogon process
            hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
            Logger.Debug("Successfully opened a handle to the winlogon process");

            // obtain a handle to the access token of the winlogon process
            if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
            {
                Logger.Debug("FAILED TO OPEN a handle to the access token of the winlogon process");
                CloseHandle(hProcess);
                return false;
            }

            Logger.Debug(String.Format("hPToken: {0}", hPToken.ToString()));

            // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
            // I would prefer to not have to use a security attribute variable and to just
            // simply pass null and inherit (by default) the security attributes
            // of the existing token. However, in C# structures are value types and therefore
            // cannot be assigned the null value.
            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
            sa.Length = Marshal.SizeOf(sa);

            // copy the access token of the winlogon process; the newly created token will be a primary token
            if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
            {
                Logger.Debug("FAILED TO COPY ACCESS TOKEN");
                CloseHandle(hProcess);
                CloseHandle(hPToken);
                return false;
            }

            // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
            // the window station has a desktop that is invisible and the process is incapable of receiving
            // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
            // interaction with the new process.
            STARTUPINFO si = new STARTUPINFO();
            si.cb = (int)Marshal.SizeOf(si);
            si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop

            // flags that specify the priority and creation method of the process
            int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

            Logger.Debug("Okay, I am now about to try and create my process as user");

            // create a new process in the current user's logon session
            bool result = CreateProcessAsUser(hUserTokenDup,        // client's access token
                                            null,                   // file to execute
                                            applicationName,        // command line
                                            ref sa,                 // pointer to process SECURITY_ATTRIBUTES
                                            ref sa,                 // pointer to thread SECURITY_ATTRIBUTES
                                            false,                  // handles are not inheritable
                                            dwCreationFlags,        // creation flags
                                            IntPtr.Zero,            // pointer to new environment block
                                            null,                   // name of current directory
                                            ref si,                 // pointer to STARTUPINFO structure
                                            out procInfo            // receives information about new process
                                            );

            // invalidate the handles
            CloseHandle(hProcess);
            CloseHandle(hPToken);
            CloseHandle(hUserTokenDup);

            return result; // return the result
        }

    }
}



Here's what a successful run looks like on my machine:

2011-04-01 13:08:07,944 DEBUG 19 ExternalProgram.Access - I am now in Access Constructor
2011-04-01 13:08:07,945 DEBUG 19 ExternalProgram.Access - I am now in Telnet
2011-04-01 13:08:07,945 DEBUG 19 ExternalProgram.Access - Application Name: telnet.exe localhost
2011-04-01 13:08:07,947 DEBUG 19 ExternalProgram.ApplicationLoader - I am now in StarProcessAndBypassUAC
2011-04-01 13:08:07,947 DEBUG 19 ExternalProgram.ApplicationLoader - Successfully created procInfo
2011-04-01 13:08:07,955 DEBUG 19 ExternalProgram.ApplicationLoader - dwSessionId: 1
2011-04-01 13:08:07,983 DEBUG 19 ExternalProgram.ApplicationLoader - winlogonPid: 728 (0 means not found)
2011-04-01 13:08:07,984 DEBUG 19 ExternalProgram.ApplicationLoader - Successfully opened a handle to the winlogon process
2011-04-01 13:08:07,984 DEBUG 19 ExternalProgram.ApplicationLoader - hPToken: 2748
2011-04-01 13:08:07,985 DEBUG 19 ExternalProgram.ApplicationLoader - Okay, I am now about to try and create my process as user
2011-04-01 13:08:08,073 DEBUG 19 ExternalProgram.Access - Result of StartProcessAndBypassUAC: True

I see the exact same logs being generated on Windows Server 2008 -- the process IS being started properly -- I can see it using resource mon, but before it is shown to the user it closes itself and I have no idea why.

Any suggestions would be appreciated.

The heavy work code was found here: http://www.codeproject.com/KB/vista-sec ... taUAC.aspx

_________________
Image

Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron