Unfortunately, that is not entirely possible in C# and neither in C/C++ for that matter even if you are writing a kernel mode driver.
Quote from the Bleachbit documentation:
Shredding an individual file properly assumes its location can be completely known, but basically it can only be known in one ideal case.The ideal case has three characteristics:
- The file size has never shrunk because of editing. Imagine starting with a 3MB spreadsheet, editing it down to 1MB (using the spreadsheet application), and asking the cleaner application to delete the 1MB version: the cleaner has no way of knowing where the missing 2MB was allocated on the physical hard drive. (Remember: file systems often don't store files continuously, so you can't assume the missing part was directly after the known part.)
- The file never moved. Imagine the spreadsheet software saves the document by writing a new copy to a temporary file, deleting the old copy, and renaming the temporary file to the original name. In this case, the cleaner application has no way of knowing where any of the old spreadsheet was located.
- The file system overwrites files to the same place. This is a good assumption. On Windows NTFS and on Linux the most common ext3 configuration (which is the default on Ubuntu 9.10 and other Linux distributions) overwrite files in the same place, but transparent disk compression, encryption, and sparse files may not overwrite files in place.
Further: When an area of a modern hard drive is damaged, it automatically remaps the bad sector to a spare. These operations are at the discretion of the drive's firmware and neither the operating system nor applications are aware of the move, so wiping the drive ignores the damaged area.
Having said that, it is possible (albeit not easy) to figure out which sectors of the drive a file currently occupies. This requires however that your application (at least partially) understands the filesystem used and how that filesystem stores files on the underlying medium.
Finally, the question remains what additional security you would gain by identifying all the sectors your file occupies and filling them with 0s vs. just doing
using(var fs = new System.IO.FileStream(@"m:\delme.zip",
FileMode.Open,
FileAccess.Write,
FileShare.None))
{
var zeros = new byte[fs.Length];
fs.Write(zeros, 0, zeros.Length);
}