googleprojectzero / sandbox-attacksurface-analysis-tools

Set of tools to analyze Windows sandboxes for exposed attack surface.
Apache License 2.0
2.07k stars 433 forks source link

Getting Access Denied when calling NtFile.Open on a named pipe #67

Closed g3rzi closed 1 year ago

g3rzi commented 1 year ago

Hi James,

I am creating the following dummy named pipe without Dacl in Powershell:

function CreateDummyPipeForTesting {
  $pipeSecurity = New-Object System.IO.Pipes.PipeSecurity
  $pipeSecurity.SetAccessRuleProtection($true, $true)
  $pipeServer = New-Object System.IO.Pipes.NamedPipeServerStream("myPipe", [System.IO.Pipes.PipeDirection]::InOut, -1, [System.IO.Pipes.PipeTransmissionMode]::Byte, [System.IO.Pipes.PipeOptions]::None, 4096, 4096, $pipeSecurity)
  Write-Output "Waiting for client connection..."
  $pipeServer.WaitForConnection()
  Write-Output "Client connected."
  $reader = New-Object System.IO.StreamReader($pipeServer)
  $writer = New-Object System.IO.StreamWriter($pipeServer)
  while ($true) {
    $message = $reader.ReadLine()
    Write-Output "Received message: $message"
    $writer.WriteLine("Hello from the server!")
    $writer.Flush()
  }
}

CreateDummyPipeForTesting

When I run the PowerShell GetNtFile, everything works fine:

PS C:\Users\eviatar> $b = Get-NtFile("\Device\NamedPipe\myPipe")
PS C:\Users\eviatar> $b.SecurityDescriptor | fl

Dacl                 : {}
Sacl                 :

But when I am trying to use the C# parallel function (NtFile.Open()) like that:

public static NtNamedPipeFileBase GetNamedPipeObjectClient2()
{
    NtNamedPipeFileBase namedPipeFileObject = null;

    string i_NamedPipe = @"\Device\NamedPipe\myPipe";
    //i_NamedPipe = @"\Device\NamedPipe\InitShutdown";
    FileShareMode ShareMode = FileShareMode.Read | FileShareMode.Write;
    FileOpenOptions Options = FileOpenOptions.SynchronousIoNonAlert;
    FileAccessRights Access = FileAccessRights.GenericRead | FileAccessRights.GenericWrite | FileAccessRights.Synchronize;

    using (ObjectAttributes obj_attributes = new ObjectAttributes(i_NamedPipe))
    {
        try
        {
            namedPipeFileObject = (NtNamedPipeFileBase)NtFile.Open(obj_attributes, Access, ShareMode, Options);
            // namedPipeFileObject = NtFile.CreateNamedPipe(obj_attributes, Access, ShareMode, Options, FileDisposition.Open, NamedPipeType.Bytestream,
           // NamedPipeReadMode.ByteStream, NamedPipeCompletionMode.CompleteOperation, 0, 0, 0, NtWaitTimeout.FromMilliseconds(0));

        }
        catch (Exception e)
        {
            // 
        }

    };

    return namedPipeFileObject;
}

I am getting an exception:

{"(0xC0000022) - {Access Denied}
A process has requested access to an object, but has not been granted those access rights."}

I also tried to run it with admin permissions with no success.
I used Get-NtFile with standard permissions (not admin) and it worked, and I used the same user with the C# function, so I am not sure why it doesn't work.
Maybe my FileAccessRights is wrong?
I tried to follow the source code but didn't see the use of the default permissions:
https://github.com/googleprojectzero/sandbox-attacksurface-analysis-tools/blob/c02ed8ba04324e54a0a188ab9877ee6aa372dfac/NtObjectManager/Cmdlets/Object/NewNtFileCmdlet.cs#L98-L120

g3rzi commented 1 year ago

We were able to find the problem.
I debugged the project and changed the CreateObject to public so I can debug it.
I called it like that:

 NtObjectManager.Cmdlets.Object.GetNtFileCmdlet a = new NtObjectManager.Cmdlets.Object.GetNtFileCmdlet();
using (ObjectAttributes obj_attributes = new ObjectAttributes(@"\Device\NamedPipe\myPipe"))
{
    a.CreateObject(obj_attributes);
}

I saw the default values:
image

After I changed them to:

 Access = FileAccessRights.MaximumAllowed;
ShareMode = FileShareMode.None;
Options = FileOpenOptions.None;

It works fine :)