I have a small application that displays the contents of a log file, somewhat transmogrified for readability. As the log file gets rewritten occasionally and Windows file system semantics prohibit deletion of open files, I create a hardlink to the file.
Obviously, this needs to happen on the same file system as the original file -- at present, I create the harddisk in the same directory, which I believe can be reasonably assumed to fulfill this requirement; the result is that a temporary file shows up in the directory listing where the user just clicked to open the file, which is ugly.
Is there a way to create a hardlink so that it does not show up (the customer where the program is used has several junctions in their directory tree, so it cannot be assumed that a specific directory is on the same filesystem), or is there a better method to read a file that another process may want to delete and rewrite (e.g. by catching their access and closing the file before letting the other process's access go through), so the program can be used on archived (readonly) log files without modification?
No
It won't help if you could. Sharing spans links.
Use the solution posed by Hans Passant as a comment.
Related
I have a GUI (lxn/walk) app patcher that downloads a file via ftp, streams it to a temporary file and extracts the contents to update the local files. The remove file command is deferred.
This works unless the user exits the program while the file is downloading, then the file isn’t deleted.
I tried to fix this by doing a graceful exit by catching the signal and removing the file there. But unfortunately it throws an error that the file can’t be deleted because it is being used by another program. Which makes sense because the another program is actually itself still writing to the temporary file.
Now I’m stuck and don’t know what to do to make sure that the temporary file is automatically gone once the patcher is not running. How do I do that correctly?
The file could also be created as a normal file, not just a temp file. I would just like to ask too, where in windows is best to write a temporary file?
Now I’m stuck and don’t know what to do to make sure that the temporary file is automatically gone once the patcher is not running. How do I do that correctly?
There are no guaranteed ways to accomplish this as many things beyond the control of the application can cause it to exit. A power failure or kernel panic due to some hardware issue can crash the machine or force it to be restarted.
A strategy that is in common use is to implement a check on program startup for the status of the previous run. Some applications create a lock file at start and remove it on graceful exit. If this lock file exists when the program is restarted, this means the previous run did not result in a clean exit, and the application can take any corrective action. The exact action to be taken depends on the nature of the application, some refuse to start, others give warnings to users.
I would just like to ask too, where in windows is best to write a temporary file?
Each OS has its own location for temporary files. If you eliminate the dir argument to TempFile, it will create it in the appropriate location, as mentioned in the documentation:
TempFile creates a new temporary file in the directory dir, opens the
file for reading and writing, and returns the resulting *os.File. The
filename is generated by taking pattern and adding a random string to
the end. If pattern includes a "*", the random string replaces the
last "*". If dir is the empty string, TempFile uses the default
directory for temporary files (see os.TempDir). Multiple programs
calling TempFile simultaneously will not choose the same file. The
caller can use f.Name() to find the pathname of the file. It is the
caller's responsibility to remove the file when no longer needed.
From os.TempDir we see the following:
On Unix systems, it returns $TMPDIR if non-empty, else /tmp. On
Windows, it uses GetTempPath, returning the first non-empty value
from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory. On
Plan 9, it returns /tmp.
The directory is neither guaranteed to exist nor have accessible
permissions.
For the purposes of a security test involving Windows servers, I would like to attempt uploading a Symbolic link to a Windows web application. However, based on the information officially available, it is unclear whether Windows hard links (Which I suppose are the same as NTFS junctions) exist as a file that can be copied from the hard disk the same way it does on Linux. It's vague, but I get the sense that NTFS junctions are some other kind of file system artifacts which is different than "regular" files - I can't find the documentation to confirm or deny this. I.E NTFS I want to know if NTFS supports the direct manipulation of the symlink record such that I could move the symlink to a different computer.
I am aware that Windows softlink files (.lnk) are not limited in this way, but they do not suit the purposes of the test.
My Aim is to copy a symlink off of a virtual machine, and then upload it to the server which I am testing.
Is this possible? (I am under the impression it is not.) From what I have seen absolutely every program on Windows would regard the hardlink as the destination file. Is there a way around this, perhaps by using a special editor to temporarily corrupt the file? If the symlink exists as a normal file on the file system can the symlink be altered so it can moved to a non-Windows OS for further use?
Let me know if this would be a better question for server fault. Since this is not directly about security, and is more of mundane technical problem in the service of a security exercise, I don't think it would fit on Stack Exchange security.
It's hard to provide a very direct answer. I work on a backup/repair/imaging project, and I copy whole disk images to a server via a web service - so, it's possible to do what you want, but there's a lot to consider.
Hardlinks
It is generally assumed that hardlinks cannot be distinguished from each other, however, there is a subtle difference between linked files and their "original" file. That difference is that queries to the $MFT (using USN-related arguments on the winapi function DeviceIOControl) will only return one of the files. This may be considered the original file. You can then call the winapi function NtQueryInformationFile to enumerate the hard links.
Symlinks and junctions are different animals...
You can know that a folder is a junction or a symlink, by getting the attributes from it. There's a ReparsePoint flag in the attributes if it's a junction or a symlink. BTW - the difference between junctions and symlinks is that the junction is a redirect to another location on the same volume, while a symlink is a redirect to an off-volume location. The redirect target is always another folder either way.
What's interesting is that both symlinks and junctions look and act like folders, while they are really files containing redirect information. When you open 'em, NTFS will normally look at the redirect, and open the redirect target. NTFS checks the permissions at the redirect target, so as an attack, this might not be a robust strategy.
When opening a junction/symlink, you can add a flag FILE_FLAG_OPEN_REPARSE_POINT. When you do this, NTFS does not perform the redirect, but opens the content, which is actually redirect information, and assuming you know the format of that information, it is possible to reconstruct the junction/symlink at the server. Note that the redirect may point to a location that may not exist, or may exist only temporarily. This is expected as some network resources may not always be available.
So, in short, it's possible to copy a junction or a symlink...while copying a hard link nominally means copying the file...with the foregoing subtleties in mind. You can create a hard link manually, too, as long as the target file exists.
With hardlinks, there's one interesting kink in the NTFS security picture. If a user has access to a file, and you create a hardlink to that file in a folder the user doesn't have access to, the user can still open that file using the path to the hard link. This is because the link and the original file are both pointing to the same file (and security info) on disk. Permissions changed on any of the links affect all the links. Without knowing this, you can inadvertently wreak havoc on a file system :-)
I know this is a bit helter-skelter, so let me summarize this way:
NTFS directory entries can be folders or files. Hardlinks are directory entries that all point to one file. Symlinks and junctions are really files that act like folders for most practical purposes (until you know how to get at the redirect info as described above).
AFAIR, NTFS (directory) junctions are actually symbolic links. The juctnion is implemented as a special file attribute called repars point that contains the link target.
Hardlinks, on the other hand, are implemented as direct references to the base MFT record of the target file and are stored as regular entries inside directory tree. You actually cannot distinguish a hardlink from the "original" file (every file and directory actually has at least one hardlink since it is contained somewhere within the directory tree).
If you wish to copy a symbolic link itself, you need to know that it is a symbolic link and extract the information about its target. File operations (except deletion and, probably, renamng) are redirected to the link target. So, you can, in general, copy a symbolic link by creating its exact copy in the destination area.
The actual question is, whether the interface you are using to perform the copy operation allows you to create symbolic links on the target.
http://code.google.com/p/guava-libraries/issues/detail?id=365 discusses the potential race-conditions that may occur while deleting a directory recursively.
According to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7148952 this can be implemented in a race-free manner under Linux using openat(). Is there an equivalent mechanism under Windows?
A key difference between Windows filesystem behavior and linux filesystem behavior is locking and reference counting.
In Windows if a process has a file open, then that file and the path leading to that file are protected.
So, if somebody has "C:\a\b\c\d\file.txt" open, then nobody is allowed to rename or delete any part of the path "C:\a\b\c\d\file.txt".
The linux model is much different, any part of that path can be changed and even the file can be deleted. The process holding the handle to "file.txt" still has a reference, and the file wouldn't be removed from the filesystem until all handles are closed.
The Win32 API doesn't expose a direct way to hold a handle to a directory (though, there are APIs for this - see the "Zw" functions, FindFirstFile may I'm not sure, the backup APIs, etc) - but your process "current directory" does hold a handle for that directory.
Thus, you can get "openat" behavior by changing your working directory and then opening the file directly. Better would be to use something like ZwCreateFile() to open a handle to the directory - since the "current dir" is process global.
Search Stackoverflow and Microsoft.com for ZwCreateFile information.
Is it possible to lock a directory in Windows so as to ensure that no other process is reading or modifying files inside the directory for the duration of the lock, while at the same time allowing the process with the lock to modify and move files and directory itself freely?
This is not a real answer, but as a workaround:
Move the directory to a subdirectory specific to your application, which is on the same volume.
Advantages:
Prevents users and other programs from modifying the file at the old location, as the files will no longer be there
Importantly, will fail if a process already has a file open within that directory, thus ensuring that the "acquired" lock is indeed "exclusive"
Disadvantages:
It's a hack
The software will need to be adapted to work with the directory at a different path than where it was initially
Users and programs attempting to access the files will encounter unusual behavior or errors ("Path not found" instead of "Access denied")
Does not protect against programs that may poke into your application-specific subdirectory
Will leave the directory "locked" (moved to a location the user probably can't find) if your program crashes while the "lock" is "held"
I need to be able edit the content of index.dat file programmatically (C:\Documents and Settings\Username\Cookies\index.dat). More precisely I need to modify it in order that index.dat for one user can be used for a different user name. Is there any documentation out there for this kind of binary file?
Pasco (http://www.foundstone.com/us/resources/proddesc/pasco.htm) is a free index.dat parser that comes with the source code.
Docs will be hard to come by - Microsoft has never publicly documented the structure of the the structure of this file. That said, you can find docs on the web such as the one mentioned above.
However, note that IE keeps close tabs on this file. The file is locked while IE is running (meaning, you can open/read it in some modes but not in others) and you can certainly not write to it.
One method that might still work is to boot-up in safe mode and then assign yourself administrator rights and then see if you can find the files to delete them.
The method I now use is to create a batch file to rename the subfolder below the folder containing the index.bat files and to then only copy the folders back to the original location that don't contain these files but the resultant batch files needs to be run from a separate windows account that has full administrator permissions.
The freeware code editor PSPad will allow you to view and to edit the contents of all of the index.dat files on your computer in hexadecimal form. This is done by replacing all of the digits in the first eight columns with zeros. This removes all of the information contained in the files.
It's a tedious process, requiring holding down the "0" (zero numeric key) as all of the edits are made, but anyone then accessing any of the index.dat files will get no information.
IE must be closed when doing this or you may receive an error message when attempting to save the modified file(s).