I have a program that decrypts a zip file, extracts it to a secret location, and then runs a program in the extracted folder. I would like to ensure that no external program can copy the extract folder to another location (the secret folder is deleted upon program completion).
I have already eliminated Windows Explorer by making my decryption program a "always on top" program that deletes the secret folder if it is killed (by use of another hidden program that the decryption program starts). My concern is that another program could watch the process list, discover the folder location and perform the copy.
Is there a way to prevent programmatic copying of a directory, or if not, of a file?
Look at Directory.CreateDirectory(string,DirectorySecurity)
You'll need to create a DirectorySecurity object that encapsulates the desired permission set. The easiest way is to create a model directory owned by the process' userid with the desired permission sets (e.g., "Only I can traverse this directory or see or even open anything in it."). Once you've done that, use the DirectorySecurity constructor overload DirectorySecurity(String, AccessControlSections) to instantiate a DirectorySecurity object with identical permissions.
Another approach, of course, would be to create the same sort of "model directory" as above and create your "secret" working directory as a subdirectory of that, inheriting the parent's permission set.
As far as securely deleting the contents on disk, look at the question "Shredding files in .NET"
If the information is that sensitive, you should probably be decrypting it into memory rather than disk. But you should be aware that that's not secure either. The recent data breach Target's POS systems suffered was due to custom-designed malware harvesting plain-text credit card and other PCI/sensitive data from process memory.
Well for that purpose you need to set share mode. Not sure about C# solution, but as far as I know in C# you are able to use Win32, so you need to open files in that folder using CreateFile and set dwShareMode to zero.
Also if you want to delete all the stuff after program terminates, you can use FILE_FLAG_DELETE_ON_CLOSE flag.
So as I mentioned, not sure if it is easy to do this using C#, but you can always trust C++, it lets do the stuff in lower level.
The file system is always public, when run from a user context.
You could always attempt to extract the 'folder' to a binary stream - and create a raw, binary file on the file system, that would have no obvious meaning - e.g. make your own temporary "file system"
Short answer: you can't.
Do note that hiding a window / displaying a window always on top are very weak protections, it's really easy to change that from another process.
Also do note that you always can suspend processes instead of terminating them, so it's also easy to prevent any logic such as "if you're killed, then I do XXX" to execute
Best thing you could do is create a user account and restrict rights to read your files/directory to only this account. Of course, admin will still have access to it.
Related
I'm trying to create software that will add a computer to an Active Directory domain. One criteria I need to meet is the machine must be added to the proper OU. In order to do this I have a set list of site locations with addresses (this is how we determine OU). This list is currently in the form of an ACCDB file, and I want to include this within the application as the Access list will not be changed.
Everything I see wants the DB file to be connected to in a different location such as server or on the local machine. My preference is to use the DB file as a reference or something inside the program's .exe file itself. I may be missing something horribly obvious, but it's been messing with me for a couple days so I'm reaching out for help.
To clarify, this software MUST be self contained (no installer). It must also be able to determine the proper OU to join to the domain (no access to shares until the PC joins the domain). It must also be user-friendly enough to avoid mistakes, meaning I want to avoid copying distributing multiple files that must go to a correct location. This is why I want to embed the ACCDB file into the application for on the fly use.
Things get much easier because this is static data. You don't have to worry about persisting this data, reclaiming changes into your program, or users accidentally deleting something, etc. You will be able to just use an embedded resource in your application. In the link, follow the examples using the image file. Text file examples will corrupt your database.
However, there is still a trick to doing this. The problem is the Access engine included with Windows will not be able to open the database as a resource, and so you will need to save this file to the local hard drive. The good news is its not as bad as it seems, because your program can do this as needed, and make sure it's right, rather than asking the user to put a file in a specific place.
As for where to put the file when you extract it... the safest and best place is the Application Data folder. You can easily get the path for this folder by checking the results of this call:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
This will give you a path where standard privilege users do have write access, no matter which user.
In summary:
Embed the ACCDB as a resource.
When your program runs, get the Application Data path using the Environment object.
Open a FileStream for writing to a file based on the path from #2
Open the embedded resource as a Stream object in C#
Copy the stream from #4 to the stream from #3. Make sure to use a mechanism intended for binary data, rather than text.
Close/Dispose your streams, so no locks remain on the file. This is as simple as putting using blocks in the right places.
Open a normal Access connection to the file you just made, using any of the thousands of tutorials or examples available on the web as a guide.
In this way, you only need to distribute the final .exe file, and users won't need any special permissions to use the database. You don't have to worry if a user deletes your file; it's still embedded in the application, which will recreate it if needed every time it starts up.
The downside is a clever user may be able to manipulate the database to end up in an undesirable OU. If you need to worry about this, you should consider having the program check a web service, rather than using embedded data. Anything you embed can ultimately be altered by an end user. A web service is also nice because you can update your mapping data as your organization evolves, without needing to rebuild or redistribute the program.
There are several threads on SO that describe how to check which application creates a file with tools like Sysinternals process monitor. Is something like this possible programmatically from .net?
Background: My program has to remote-control a proprietary third party application using its automation interface, and one of the functions I need from this application has a bug where it creates a bunch of temporary files in %TEMP% that are called tmpXXXX.tmp (the same as .net's Path.GetTempFileName() does) but does not delete them. This causes the C drive to become full over time, eventually failing the application. I already filed a bug to the manufacturer, but we need a temporary workaround for the time being, so I thought of putting a FileSystemWatcher on %TEMP% that watches tmp*.tmp, collects these files, and after the operation on the third-party application finishes, deletes them. But this is risky as another application might also write files with the same file name pattern to %TEMP% so I only want to delete those created by NastyBuggyThirdPartyApplication.exe.
Is this anyhow possible?
This kind of things is possible, but maybe a bit tricky.
To know who created the file, look at the user that owns it. Therefore you might need to create a specific user, and that application will run under this specific user. In order to do that, you need to create a small application that will start your buggy app by impersonating another user, so anything done within the app will be under this user so as file creating...
I don't know how to monitor and get triggered when a file is created, but nothing can prevent you from setting a timer that wakes up every five or ten minutes, then checks if any file in the directory is owned by the application user and closed, so it deletes it.
Maybe if they react fast for this bug fixing, you won't need your app very long time. So another solution, if possible might just to change the Temp folder into another drive, which has lots of space...
One solution is that you use a FileWatcher to automatically delete all the files but before deleting you should check if the file is not currently locked or used by other process, for example the Sysinternal Suite has a tool called handle.exe that can do this. Use it from the command line:
handle.exe -a
You can invoke this from a c# program (there might be some performance issues though)
So what you would do is when a file is created you verify if it is in use or locked (for example u can use the code provided in Is there a way to check if a file is in use?) and then delete it.
Most of the time when an app is using a temp file it will lock it to prevent just what you fear, that you might delete files from other processes.
As far as I can tell there is no sure way to identify which process created a specific file.
Okay, so I am creating a c# winforms application.
I want to write/read from binary data file. But, I want to put that file in a folder somewhere and I do not want anyone to be able to delete or edit the file. I only want the program that uses the file to be able to access it.
Is this possible? I looked into MSDN's structure on file security and as I researched it I saw people complain that if you limit the file to a user then that person can just override the privileges and make it editable.
Also, I thought about how this would actually work considering in essence I would like a process to edit the file only and that process could have varying process ID's if it is opened and closed over time, seems tough.
Any thoughts?
Even though this will not satisfy all your requirements you can try IsolatedStorage (System.IO.IsolatedStorage Namespace).
How to write and read file in IsolatedStorage
The System.IO.IsolatedStorage namespace contains types that allow the
creation and use of isolated stores. With these stores, you can read
and write data that less trusted code cannot access and prevent the
exposure of sensitive information that can be saved elsewhere on the
file system. Data is stored in compartments that are isolated by the
current user and by the assembly in which the code exists.
Additionally, data can be isolated by domain. Roaming profiles can be
used in conjunction with isolated storage so isolated stores will
travel with the user's profile. The IsolatedStorageScope enumeration
indicates different types of isolation. For more information about
when to use isolated storage
You can prevent file access while your program is running if you open it exclusively.
However, when the program is not running, the file is no longer protected. So someone would just need to kill the program in order to access the file.
In order to protect the file while your program is not running, you'd need to set up a user account and assign it a password which is only known to the program. Then set the permissions of the file so that only your user can access the file.
However, any administrator can take over the ownership of the file, so even permission protection is useless.
Finally, someone can even take the hard disk out of the PC and read the raw data.
You might also think about whether you want to protect the file or the file content. If the file content is sensitive, think about encryption.
It really depends on your needs, which option to choose.
If you have control over the target filesystem prior to install then setup some file permissions and go from there. The user accessing the folder will need read permissions at minimum.
Run the app under a security group and assign persmissions to the folder and files with that security group. Revoke access for others and make it readonly
Windows 10 version 1709 introduced Controlled Folder Access. This allows you to whitelist applications that can modify certain folders. You cannot restrict Read access.
well, I have the same issue and I did some research on this subject and I found that secure your information in a accesspoint database or any other Microsoft data base with password and only one specific app that have the password will have the permission to do read/write to these information.
I am by no means a programmer but currently am wondering if an application creates a temp file that windows names. For example the file it creates is tmp001, is there a way i can take that name tmp001 and ask windows to give me the next temp file it would create before it creates it.
Thanks,
Mike
There is no direct means to get to know the next temporary filename to be created.
For example, programmers use the System.IO.Path.GetTempFileName method, but one can add application-specific prefixes or suffixes in order to make it easier for the application to find its newly created files.
One can even choose to save this temporary file elsewhere than the system Temp folder.
You would need to define a "temp file" much more explicitly in order to answer this question with a "Yes". The problem is that a "temp file" is just something not meant to be kept. It could exist anywhere on the system and be created by a user, application, or service. This would make it nearly (or actually) impossible to answer your question with a "Yes".
If you constrain the definition of a temp file to just the files in the official temp folder (or a subfolder), you still have a problem if you're trying to catch names not generated by windows. Any app could produce a particularly named temp file in that folder, without Windows caring.
If you further constrain the definition to be only those files named by Windows, you might be able to get somewhere. But, does that really meet your needs?
After all of that, maybe it would be better to describe the problem you're trying to solve. There may be a much better (workable) solution that would address the issue.
Typically applications use the Win32 API GetTempFileName to get the temporary directory.
The process of how the temp file is generated is described there.
I'm not sure why you want this info, but perhaps you could for example register for directory changes via a Win32 API like ReadDirectoryChangesW or by using a mini filter driver.
This kind of code just cannot work reliably on a multi-tasking operating system. Another thread in another process might pre-empt yours and claim the file name you are hoping to create.
This is otherwise easy enough to work around, just name your own files instead of relying on Windows doing it for you. Do so in the AppData folder so you'll minimize the risk of another process messing it up.
Is there a reliable method to check if an application is run from somewhere beneath program files?
If the user installs the application to program files on local machine, we need to put writable files somewhere else to avoid virtualization on Vista and Win7. When installed to a network disk, though, we want to keep these files with the installation for shared access among users.
Today we do an string comparison between startup path and CSIDL_PROGRAM_FILES, but something tells me this is a very unreliable method.
Any smart solution out there?
Is there a 'IsRunningFromProtectedFolder( )'-api that I do not know about?
Are there any other folders giving the same problems as program files do?
This is not a terribly good idea, as a user can install it wherever they want to, and then the check might fail. Instead have a checkbox when the user installs the app, deciding if it is installed locally or on a server.
As you I also found problems dealing with UAC folder virtualization.I suggest a workaround, it seems that it should work.
It comes from the assumption that elevated processes always use original copies and not the virtualized ones (CMIIW). Also I assume that you setup processed was executed elevated
The idea is to create a "general" process (non-elevated, legacy), that your main installer should run. This process will create a file name in the user chosen folder with a name and contents that both your programs know (for example, test73819704.bin). If the folder virtualized, this file should appear in the user VirtualStore and SHOULD NOT in the original one (from the point of view and privileges of the installer).
So for chosen C:\Program_Files_But_Not_Necessarily and Process-1 (elevated)
Process-1 ensures there's no file C:\Program_Files_But_Not_Necessarily\test73819704.bin
It launches Process-2 with no elevation
Process-2 creates C:\Program_Files_But_Not_Necessarily\test73819704.bin and checks whether it really exists. If exists it would return with a good return code, otherwise with a "failed" one.
Process-1 waits for Process-2 and analize the result. If good, checks for C:\Program_Files_But_Not_Necessarily\test73819704.bin, if it exists, go for "Bingo! No virtualization occured", if doesn't exist, "Bad, let's find some other storage place". If the code from the Process-2 is "failed" one, show the user some error message.
Unfortunately I could not test it right now, but I guess it should work and there's a logic behind this, with Process-2 you just emulate the behavior of your main program )
We allow our users to install anywhere...
If the user has taken the default, and is installed in Program Files, we make the assumption that we need to write to Documents and Settings/Users. Otherwise, we write our data to a folder under the directory the software is in. This of course can still cause problems, and the install does indeed allow people to choose a different data location if they choose to not go for the default.
On top of that, it's a simple ini file change and a copy to move the data.
On start up we detect if we are in the Program Files directory by comparing the value we obtain from SHGetFolderPath(CSIDL_PROGRAM_FILES) with the start of the path the executable is in.