Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.0k views
in Technique[技术] by (71.8m points)

c# - Write to file and execute it atomically

Let's say I have contents of an executable (or a bat script, doesn't matter) in memory and want to run it as a new process. That is easy.

File.WriteAllBytes(filePath, contents);
// gap
Process.Start(filePath)

But I want to make sure that the executed file is not tampered by any other process. And there is a gap between file creation and execution. It gives a chance to tamper the file with the right tools.

So, instead of File.WriteAllBytes, I went with opening a FileStream FileShare.Read and keeping it open until the execution has finished.

using(var fileStream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
{
    Process.Start(filePath)
}

But this doesn't work. Process.Start fails with:

System.ComponentModel.Win32Exception (32): The process cannot access the file because it is being used by another process.

This question and its answer explains why I think. In a nutshell, Process.Start will attempt to open the file with FileShare.Read and fail because the open FileStream already has Write Access, hence failing the FileShare.Read attempt of the process.

Is there a way to do this cleanly?

A workaround I can think of is to save the file, close it, open a new FileStream with FileShare.Read and FileAccess.Read, make sure the content is still the same before executing it. But that's not pretty.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you are describing is a classic case of Time of check to time of use vulnerability.

Any solution that involves checking something and then executing it, and where those two operations are not atomic, will still leave you vulnerable. For example:

make sure the content is still the same before executing it. But that's not pretty

There's still a (smaller) gap (timing window) between the "make sure the content is still the same" and "executing it".

In 2004, an impossibility result was published,showing that there was no portable, deterministic technique for avoiding TOCT-TOU race conditions

- https://web.cecs.pdx.edu/~markem/CS333/handouts/tocttou.pdf

You can do a couple of things to mitigate it:

  • Don't use files! You say you have some code in memory that you need to execute: can you execute it yourself in the same process?

  • Reduce the window of time.

  • Make the file name random and hard to predict for other processes.

  • Run your program as a separate user where there's less likelyhood an attacker (or malicious program) is running, and restrict the file read/write to the new user only.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...