Beispiel #1
0
        public static void CopyLockedFile(ProcessFileHandle fileHandle, string copyTo = "")
        {
            // Copies a locked file to a random temp file or the location specified
            //  -Opens the process with DuplicateHandle permissions
            //  -Duplicates the file handle supplied
            //  -Uses CreateFileMapping() on the duplicated handle
            //  -Uses MapViewOfFile() to map the entire file into memory
            //  -Writes the mapped data to the new temp file

            // open the target process with "duplicate handle" permissions
            IntPtr processHandle        = Kernel32.OpenProcess(ProcessAccessFlags.DuplicateHandle, true, (uint)fileHandle.ProcessID);
            IntPtr currentProcessHandle = Kernel32.GetCurrentProcess();

            IntPtr duplicatedHandle = new IntPtr();

            // duplicate the specific file handle opened by the process locking it
            bool success = Kernel32.DuplicateHandle(processHandle, new IntPtr(fileHandle.FileHandleID), currentProcessHandle, out duplicatedHandle, 0, false, DuplicateOptions.DUPLICATE_SAME_ACCESS);

            if (success)
            {
                long fileSize = 0; // size of the file we're copying out
                Kernel32.GetFileSizeEx(duplicatedHandle, out fileSize);

                // create a file mapping with the duplicated handle
                IntPtr mappedPtr = Kernel32.CreateFileMapping(duplicatedHandle, IntPtr.Zero, FileMapProtection.PageReadonly, 0, 0, null);

                // map the entire file into memory
                IntPtr mappedViewPtr = Kernel32.MapViewOfFile(mappedPtr, FileMapAccess.FileMapRead, 0, 0, 0);

                // generate a temporary file name if a target isn't specified
                if (String.IsNullOrEmpty(copyTo))
                {
                    copyTo = Path.GetTempFileName();
                }
                Console.WriteLine($"[*] Copying to: {copyTo}");

                // create the temporary file to copy to
                //  GENERIC_READ = 0x80000000
                //  GENERIC_WRITE = 0x40000000
                //  FILE_SHARE_READ = 0x00000001
                //  FILE_SHARE_WRITE = 0x00000002
                //  CREATE_ALWAYS = 0x00000002
                IntPtr tempFilePtr = Kernel32.CreateFile(copyTo, 0x80000000 | 0x40000000, 0x00000001 | 0x00000002, (IntPtr)null, 0x00000002, 0, (IntPtr)null);
                // write out the memory mapped file to the new temp file
                uint written = 0;
                Kernel32.WriteFile(tempFilePtr, mappedViewPtr, (uint)fileSize, out written, (IntPtr)null);

                Console.WriteLine($"[*] Copied {written} bytes from \"{fileHandle.FileName}\" to \"{copyTo}\"");

                // cleanup
                Kernel32.UnmapViewOfFile(mappedViewPtr);
                Kernel32.CloseHandle(tempFilePtr);
                Kernel32.CloseHandle(duplicatedHandle);
            }

            Kernel32.CloseHandle(processHandle);
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            var parsed = ArgumentParser.Parse(args);

            string[] candidateProcesses = null;
            bool     copyFile           = false;
            string   copyDestination    = "";

            if (parsed.ParsedOk == false)
            {
                Usage();
                return;
            }

            if (
                parsed.Arguments.ContainsKey("/h") ||
                parsed.Arguments.ContainsKey("/H") ||
                parsed.Arguments.ContainsKey("/?") ||
                parsed.Arguments.ContainsKey("/help") ||
                parsed.Arguments.ContainsKey("/HELP") ||
                parsed.Arguments.ContainsKey("-h") ||
                parsed.Arguments.ContainsKey("-H") ||
                parsed.Arguments.ContainsKey("-?") ||
                parsed.Arguments.ContainsKey("-help") ||
                parsed.Arguments.ContainsKey("-HELP"))
            {
                Usage();
                return;
            }

            var targetFile = args.Length != 0 ? args[0] : "";

            if (String.IsNullOrEmpty(targetFile))
            {
                Usage();
                return;
            }

            if (parsed.Arguments.ContainsKey("/process"))
            {
                candidateProcesses = parsed.Arguments["/process"].Split(',');
            }

            if (parsed.Arguments.ContainsKey("/copy"))
            {
                copyFile        = true;
                copyDestination = parsed.Arguments["/copy"];
            }

            if (targetFile == "all")
            {
                Console.WriteLine($"ProcessName,ProcessID,FileHandleID,FileName");

                List <ProcessFileHandle> handles = GetAllFileHandles();

                foreach (ProcessFileHandle handle in handles)
                {
                    Console.WriteLine($"{handle.ProcessName},{handle.ProcessID},{handle.FileHandleID},{handle.FileName}");
                }
            }
            else
            {
                Console.WriteLine($"\r\n[*] Searching processes for an open handle to \"{targetFile}\"");

                ProcessFileHandle foundHandle = FindFileHandle(targetFile, candidateProcesses);

                if (foundHandle.ProcessID != 0)
                {
                    Console.WriteLine($"[+] Process \"{foundHandle.ProcessName}\" ({foundHandle.ProcessID}) has a file handle (ID {foundHandle.FileHandleID}) to \"{foundHandle.FileName}\"");

                    if (copyFile)
                    {
                        CopyLockedFile(foundHandle, copyDestination);
                    }
                }
                else
                {
                    Console.WriteLine($"[X] Handle not found for \"{targetFile}\"");
                }
            }
        }