Example #1
0
        public static ReparsePoint ChangeReparsePointTarget(string reparsePointPath, string newReparsePointTarget)
        {
            reparsePointPath      = reparsePointPath.GetFullPath();
            newReparsePointTarget = newReparsePointTarget.GetFullPath();
            var oldReparsePointTarget = GetActualPath(reparsePointPath).GetFullPath();

            if (newReparsePointTarget.Equals(oldReparsePointTarget, StringComparison.CurrentCultureIgnoreCase))
            {
                return(Open(reparsePointPath));
            }

            if (!IsReparsePoint(reparsePointPath))
            {
                throw new IOException("Path is not a reparse point.");
            }

            if (Directory.Exists(reparsePointPath))
            {
                if (!Directory.Exists(newReparsePointTarget))
                {
                    throw new IOException("Reparse point is a directory, but no directory exists for new reparse point target.");
                }
            }
            else if (File.Exists(reparsePointPath))
            {
                if (!File.Exists(newReparsePointTarget))
                {
                    throw new IOException("Reparse point is a file, but no file exists for new reparse point target.");
                }
            }
            else
            {
                throw new IOException("Reparse Point is not a file or directory ?");
            }

            var reparsePoint = Open(reparsePointPath);
            var isSymlink    = reparsePoint._reparseDataData.ReparseTag == IoReparseTag.Symlink;

            if (reparsePoint._reparseDataData.ReparseTag != IoReparseTag.MountPoint && reparsePoint._reparseDataData.ReparseTag != IoReparseTag.Symlink)
            {
                throw new IOException("ChangeReparsePointTarget only works on junctions and symlink reparse points.");
            }

            // dark magic kung-fu to get privilige to create symlink.
            var    state     = IntPtr.Zero;
            UInt32 privilege = 35;

            if (isSymlink)
            {
                Ntdll.RtlAcquirePrivilege(ref privilege, 1, 0, ref state);
            }

            using (var handle = GetReparsePointHandle(reparsePointPath, NativeFileAccess.GenericWrite)) {
                var substituteName = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + newReparsePointTarget);
                var printName      = Encoding.Unicode.GetBytes(newReparsePointTarget);
                var extraOffset    = isSymlink ? 4 : 0;

                reparsePoint._reparseDataData.SubstituteNameOffset = 0;
                reparsePoint._reparseDataData.SubstituteNameLength = (ushort)substituteName.Length;
                reparsePoint._reparseDataData.PrintNameOffset      = (ushort)(substituteName.Length + 2);
                reparsePoint._reparseDataData.PrintNameLength      = (ushort)printName.Length;
                reparsePoint._reparseDataData.PathBuffer           = new byte[0x3ff0];

                reparsePoint._reparseDataData.ReparseDataLength =
                    (ushort)(reparsePoint._reparseDataData.PrintNameLength + reparsePoint._reparseDataData.PrintNameOffset + 10 + extraOffset);

                Array.Copy(substituteName, 0, reparsePoint._reparseDataData.PathBuffer, extraOffset, substituteName.Length);
                Array.Copy(printName, 0, reparsePoint._reparseDataData.PathBuffer, reparsePoint._reparseDataData.PrintNameOffset + extraOffset, printName.Length);

                var inBufferSize = Marshal.SizeOf(reparsePoint._reparseDataData);
                var inBuffer     = Marshal.AllocHGlobal(inBufferSize);

                try {
                    Marshal.StructureToPtr(reparsePoint._reparseDataData, inBuffer, false);

                    int bytesReturned;
                    var result = Kernel32.DeviceIoControl(handle, ControlCodes.SetReparsePoint, inBuffer, reparsePoint._reparseDataData.ReparseDataLength + 8,
                                                          IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                    {
                        throw new IOException("Unable to modify reparse point.", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
                    }
                    return(Open(reparsePointPath));
                } finally {
                    if (isSymlink)
                    {
                        try {
                            if (state != IntPtr.Zero)
                            {
                                Ntdll.RtlReleasePrivilege(state);
                            }
                        } catch {
                            // sometimes this doesn't work so well
                        }
                    }
                    Marshal.FreeHGlobal(inBuffer);
                }
            }
        }
Example #2
0
        private static bool DoRehash(int processId)
        {
            SizeT written  = 0;
            uint  threadId = 0;

            // Find target
            var processHandle = Kernel32.OpenProcess(0x000F0000 | 0x00100000 | 0xFFFF /* PROCESS_ALL_ACCESS */, false, processId);

            if (processHandle.IsInvalid)
            {
                return(false);
            }

            // Create some space in target memory space
            var processType = GetProcessProcessorType(processHandle);

            if (!_reHashDlls.ContainsKey(processType))
            {
                Logger.Error("Rehash: Unable to get rehash DLL for {0}", processType);
                return(false);
            }

            var pathInAscii = _reHashDlls[processType];
            var length      = (uint)pathInAscii.Length;

            // before we actually allocate any memory in the target process,
            // let's make sure we get out module/fn pointers ok.
            var moduleHandle = Kernel32.GetModuleHandle("kernel32");

            if (moduleHandle.IsInvalid)
            {
                Logger.Error("Rehash: Can't get Kernel32 Module Handle");
                // failed to get Module Handle to Kernel32? Whoa.
                return(false);
            }

            var fnLoadLibrary = Kernel32.GetProcAddress(moduleHandle, "LoadLibraryA");

            if (fnLoadLibrary == IntPtr.Zero)
            {
                // Failed to get LoadLibraryA ptr.
                Logger.Error("Rehash: Can't get LoadLibraryA Handle");
                return(false);
            }

            var remoteMemory = Kernel32.VirtualAllocEx(processHandle, IntPtr.Zero, length, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ExecuteReadWrite);

            if (remoteMemory == IntPtr.Zero)
            {
                // Target alloc mem error
                Logger.Error("Rehash: Can't allocate memory in process pid:{0}", processId);
                return(false);
            }

            // Write library name into target memory space
            if (!Kernel32.WriteProcessMemory(processHandle, remoteMemory, pathInAscii, length, ref written) || written == 0)
            {
                // Target write mem error.
                // cleanup what we allocated?
                // var err = Marshal.GetLastWin32Error();
                Logger.Error("Rehash: Can't write memory in process pid:{0}", processId);
                Kernel32.VirtualFreeEx(processHandle, remoteMemory, length, AllocationType.Release);
                return(false);
            }

            // flush the instruction cache, to make sure that the processor will see the changes.
            // Note: In the matrix, this can cause "deja vu"
            Kernel32.FlushInstructionCache(processHandle, IntPtr.Zero, 0);

            // tell the remote process to load our DLL (which does the actual rehash!)
            if (WindowsVersionInfo.IsVistaOrBeyond)
            {
                if (0 != Ntdll.RtlCreateUserThread(processHandle, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, fnLoadLibrary, remoteMemory, out threadId, IntPtr.Zero))
                {
                    Logger.Error("Rehash: Can't create remote thread (via RtlCreateUserThread) in pid:{0}", processId);
                    return(false);
                }
            }
            else
            {
                if (
                    Kernel32.CreateRemoteThread(processHandle, IntPtr.Zero, 0, fnLoadLibrary, remoteMemory, CreateRemoteThreadFlags.None, out threadId).
                    IsInvalid)
                {
                    Logger.Error("Rehash: Can't create remote thread in pid:{0}", processId);
                    return(false);
                }
            }
            //Logger.Warning("Rehash: Success with pid:{0}", processId);
            return(true);
        }
Example #3
0
        public static ReparsePoint CreateSymlink(string symlinkPath, string linkTarget)
        {
            symlinkPath = symlinkPath.GetFullPath();
            linkTarget  = linkTarget.GetFullPath();

            if (Directory.Exists(symlinkPath) || File.Exists(symlinkPath))
            {
                throw new IOException("Symlink path already exists.");
            }

            if (Directory.Exists(linkTarget))
            {
                Directory.CreateDirectory(symlinkPath);
            }
            else if (File.Exists(linkTarget))
            {
                File.Create(symlinkPath).Close();
            }
            else
            {
                throw new IOException("Target path does not exist or is not a directory.");
            }

            // dark magic kung-fu to get privilige to create symlink.
            var    state     = IntPtr.Zero;
            UInt32 privilege = 35;

            Ntdll.RtlAcquirePrivilege(ref privilege, 1, 0, ref state);

            using (var handle = GetReparsePointHandle(symlinkPath, NativeFileAccess.GenericWrite)) {
                var substituteName = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + linkTarget);
                var printName      = Encoding.Unicode.GetBytes(linkTarget);
                var extraOffset    = 4;

                var reparseDataBuffer = new ReparseData {
                    ReparseTag           = IoReparseTag.Symlink,
                    SubstituteNameOffset = 0,
                    SubstituteNameLength = (ushort)substituteName.Length,
                    PrintNameOffset      = (ushort)(substituteName.Length + 2),
                    PrintNameLength      = (ushort)printName.Length,
                    PathBuffer           = new byte[0x3ff0],
                };

                reparseDataBuffer.ReparseDataLength = (ushort)(reparseDataBuffer.PrintNameLength + reparseDataBuffer.PrintNameOffset + 10 + extraOffset);

                Array.Copy(substituteName, 0, reparseDataBuffer.PathBuffer, extraOffset, substituteName.Length);
                Array.Copy(printName, 0, reparseDataBuffer.PathBuffer, reparseDataBuffer.PrintNameOffset + extraOffset, printName.Length);

                var inBufferSize = Marshal.SizeOf(reparseDataBuffer);
                var inBuffer     = Marshal.AllocHGlobal(inBufferSize);

                try {
                    Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);

                    int bytesReturned;
                    var result = Kernel32.DeviceIoControl(handle, ControlCodes.SetReparsePoint, inBuffer, reparseDataBuffer.ReparseDataLength + 8, IntPtr.Zero,
                                                          0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                    {
                        if (Directory.Exists(symlinkPath))
                        {
                            Directory.Delete(symlinkPath);
                        }
                        else if (File.Exists(symlinkPath))
                        {
                            File.Delete(symlinkPath);
                        }

                        throw new IOException("Unable to create symlink.", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
                    }
                    return(Open(symlinkPath));
                } finally {
                    Marshal.FreeHGlobal(inBuffer);
                    try {
                        if (state != IntPtr.Zero)
                        {
                            Ntdll.RtlReleasePrivilege(state);
                        }
                    } catch {
                        // sometimes this doesn't work so well
                    }
                }
            }
        }