none
SeCreateGlobalPrivilege to a none session0 process. RRS feed

  • Question

  • I would like to know how I can programmatically set SeCreateGlobalPrivilege to a none session0 process that's trying to open a MemoryMappedFile with Global\ prefix, which will be used to share some data between 2 processes, one running with session0 (Windows Service) and other being a process that is started by invoking CreateProcessAsUser upon a user logging on to the system. The access token passed to CreateProcessAsUser function is duplicated from the process of "explorer" whose sessionId matches the result of WTSGetActiveConsoleSessionId(). I have this Owin middleware which runs under session0 that returns contents of MemoryMappedFile allocated by a user process that continuously monitors a specific local file which is mapped to an url that is used to access the data from outside using HTTP.

    I'm running this in Windows 7 environment.

    Is SeCreateGlobalPrivilege something that can be set to a process programmatically? 

    Thank you.

    Wednesday, February 26, 2014 12:58 PM

Answers

All replies

  • Hi Hanishi,

    I am trying to involve someone familiar with this issue to come into this thread. Thank you for your understanding.

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, February 27, 2014 1:37 AM
    Moderator
  • I've answered that survey and now it's your time to answer my question. 

    Thanks for your attention and I really need to solve this

    I can't have the Windows Service process open the MemoryMappedFile as it would create some arbitrary place that is unknown to that none sesison0 process

    The following is the code snippet that I'm trying to make it work under this specific circumstance described above. It only works if both of the aforementioned processes run with the same sessionId, regardless of whether there is a Global prefix or not. 

    public class FileView
        {
            private readonly AutoResetEvent _run = new AutoResetEvent(false);
            private readonly AutoResetEvent _update = new AutoResetEvent(false);
            
            private ILog logger = LogManager.GetLogger("weldR");
            private bool IsDisposed { get; set; }
    
            private byte[] Data { get; set; }
    
            private string MapName { get; set; }
    
            private string MutexName { get; set; }
    
            private MemoryMappedFileSecurity Security { get; set; }
    
            public FileView(string url)
            {
                if (url.StartsWith("/"))
                {
                    url = url.Substring(1);
                }
                MapName = string.Format("Global\\{0}",String.Concat("pipe://", url));
                MutexName = string.Format("Global\\{0}", url.GetHashCode().ToString("x"));
                Security = new MemoryMappedFileSecurity();
                Security.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>("everyone", 
                    MemoryMappedFileRights.FullControl, System.Security.AccessControl.AccessControlType.Allow));
    
                Task.Factory.StartNew(Run);
            }
    
            void Run()
            {
                while (!IsDisposed)
                {
                    if(Data != null)
                    {
                        Process process = Process.GetCurrentProcess();
                        using (new PrivilegeEnabler(process, Privilege.CreateGlobal))
                        {
                            var mutex = new Mutex(true, MutexName);
    
                            using (var mmf = MemoryMappedFile.CreateNew(MapName, Data.Length + 8,
                                MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, Security, HandleInheritability.Inheritable))
                            {
                                using (var viewAccessor = mmf.CreateViewAccessor())
                                {
                                    try
                                    {
                                        var size = Data.Length.Bytes();
                                        viewAccessor.WriteArray(0, size, 0, size.Length);
                                        viewAccessor.WriteArray(size.Length + 1, Data, 0, Data.Length);
                                    }
                                    catch (Exception e)
                                    {
                                        logger.ErrorFormat(e.ToString());
                                    }
                                }
                                mutex.ReleaseMutex();
    
                                _update.Set();
    
                                _run.WaitOne();
    
                                mutex.WaitOne();
                            }     
                        }
                    }
                    else
                    {
                        _run.WaitOne();
                    }
                }
            }
    
            public void Update(byte[] data)
            { 
                Data = data;
                _run.Set();
                _update.WaitOne();
            }
    
            public void Dispose()
            { 
                IsDisposed = true;
                _run.Set();
                _update.Set();
            }
        }

    And here is the code that tries to retrieve the contents of the file from the allocated memory space.

    private static Action<OwinRequest, OwinResponse> Serve(string path)
            {
                return (request, response) =>
                    {
    
                        //var pipename = String.Concat("pipe://", path);
                       // var pipemutex = path.GetHashCode().ToString("x");
    
                        var pipename = string.Format("Global\\{0}", String.Concat("pipe://", path));
                        var pipemutex = string.Format("Global\\{0}", path.GetHashCode().ToString("x"));
    
                        using (var mmf = MemoryMappedFile.OpenExisting(pipename))
                        {
                            using (var mutex = Mutex.OpenExisting(pipemutex))
                            {
                                try
                                {
                                    mutex.WaitOne();
                                    using (var accessor = mmf.CreateViewAccessor())
                                    {
                                        var offset = 0;
                                        var fileLength = new byte[4];
                                        accessor.ReadArray(offset, fileLength, 0, fileLength.Length);
                                        offset += fileLength.Length;
                                        var size = fileLength.Int32();
                                        var buff = new byte[size];
                                        accessor.ReadArray(offset, buff, 0, buff.Length);
                                       
                                        var lastWriteTimeUtc = new DateTime();
                                        var etag = string.Concat("\"", lastWriteTimeUtc.Ticks.ToString("x"), "\"");
                                        var lastModified = lastWriteTimeUtc.ToString("R");
                                        if ("HEAD".Equals(request.Method, StringComparison.OrdinalIgnoreCase))
                                            return;
    
                                        //if (CacheHelpers.ReturnNotModified(etag, lastWriteTimeUtc, context))
                                        //{
                                        //    mutex.ReleaseMutex();
                                        //    return TaskHelpers.Completed();
                                        //}
                                        response.AddHeader("ETag", etag);
                                        response.AddHeader("Last-Modified", lastModified);
                                        response.AddHeader("Content-Type", Mime.MimeTypeFromExtension(path, "text/plain"));
                                        response.AddHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture));
    
                                        response.Body.Write(buff, 0, buff.Length);
                                    }
                                }
                                finally
                                {
                                    mutex.ReleaseMutex();
                                }
                            }
                        }
                    };
            }

    I get the following Exception

    2014-02-27 11:21:18,677 [1704|22|DEBUG] weldR: System.IO.FileNotFoundException: 指定されたファイルが見つかりません。
       場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenCore(String mapName, HandleInheritability inheritability, Int32 desiredAccessRights, Boolean createOrOpen)
       場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(String mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability)
       場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(String mapName)
       場所 weldR.Owin.File.MemoryMappedStatic.<>c__DisplayClass8.<Serve>b__7(OwinRequest request, OwinResponse response)
       場所 weldR.Owin.File.MemoryMappedStatic.<Invoke>d__0.MoveNext()




    Thursday, February 27, 2014 2:43 AM
  • This seems impossible. I'm just guessing however, I see other blog posts and forum entries that suggest Opening a MemoryMappedFile with Global\ prefix is only allowed by a process with admin privilege.
    Monday, March 3, 2014 2:29 PM
  • If you find a way to get this privilege by code, you found an elevation of privilege vulnerability. Windows security is designed to prevent what you are asking.

    Ask the user to run your process using a user token with the privilege. E.g. run as admin.



    Visual C++ MVP


    Monday, March 3, 2014 7:21 PM