How do i change the hosts file in a windows program? - c#

How would a program in C++/ C / C# program change the C:\Windows\System32\drivers\etc\hosts file content in windows?
I know this sounds like phishing, honestly not.

Hosts file has a very simple format where each line may contain "ip host" records
All you need is regular file appending :
using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers/etc/hosts")))
{
w.WriteLine("123.123.123.123 FQDN");
}
Beware that by default you'll need elevated privileges to write to the hosts file...
In order to revert back, better take a backup of the file and restore it once you are done.

First, you should request for administrative permission from the user. You can do this through your Program class in your application. The below code will request the user for administrative access, the user then has the option to allow or deny it. If they deny it, this example does not run the application.
Once your application is run in administrative mode, its plain text with simple formatting. You do not even need all the Microsoft comments included in the file, and simple string parsing will do just fine. The comments by MSFT in the HOSTS file are all the documentation you really need as far as the HOSTS file itself goes.
namespace Setup {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Setup.Forms;
using System.Security.Principal;
using System.Diagnostics;
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool administrativeMode = principal.IsInRole(WindowsBuiltInRole.Administrator);
if (!administrativeMode) {
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.FileName = Application.ExecutablePath;
try {
Process.Start(startInfo);
}
catch {
return;
}
return;
}
Application.Run(new ShellForm());
}
}
}

The file is usually located at C:\Windows\System32\drivers\etc\hosts. Rather than hard coding the C:\Windows part though, you should use Environment.GetEnvironmentVariable("SystemRoot") to safely determine the system root directory.
Otherwise you can write to it like any other file, assuming you have the proper permissions.

The hosts file is just plain text. The format is each line contains the IP and the hostname that IP should resolve to, separated by whitespace. # denotes a comment.
Example:
# This is a comment-
127.0.0.1 mysuperhost.com
The file is located here: C:\Windows\system32\drivers\etc\hosts. You will (with good reason), need administrator privileges to write to it.

The most accurate way of finding the HOSTS file location is to read the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DataBasePath registry key, and appending hosts to the end.
This will always point to the correct location for the current machine configuration and works for all Windows NT based platforms since Windows NT 4.0.

As a guy who struggled with this problem, easy way out, copy the hosts file to temp folder, modify it and copy it back with overwrite. Running the application as admin, will be the best.

Related

Killing process as admin via another process

I'm trying to kill some processes by their names (specific names that I already know) In C#. I find them and kill them with Process.Kill(), but sometimes on some processes i get 'access denied'. I assume it is because I'm not running them as an admin.
I created a batch that does the same, and if I run it as an admin it kills them all, otherwise not.
I can run the batch as an admin via the c# code, i.e:
var psi = new ProcessStartInfo();
psi.Verb = "runas"; //This suppose to run the command as administrator
//Then run a process with this psi
My question is, is this really a way to solve the access problem? Is there a better way? If I run my C# code as an admin, does Process.Kill() suppose to have the same result as doing it with the batch file?
What you are talking about are Elevated rights.
You need the programm that finds the programms and sends out the kills to always run Elevated. The most reliable way to do that, is to add this requirement to the Programm Manifest. It is something the UAC will read to help you.
The second most reliable way is to check if you got the rights. And if not, have the programm try to (re)start itself elevated. I did write some sample code for this a while back:
using System;
using System.Diagnostics;
using System.IO;
namespace RunAsAdmin
{
class Program
{
static void Main(string[] args)
{
/*Note: Running a batch file (.bat) or similar script file as admin
Requires starting the interpreter as admin and handing it the file as Parameter
See documentation of Interpreting Programm for details */
//Just getting the Absolute Path for Notepad
string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
string FullPath = Path.Combine(windir, #"system32\notepad.exe");
//The real work part
//This is the programm to run
ProcessStartInfo startInfo = new ProcessStartInfo(FullPath);
//This tells it should run Elevated
startInfo.Verb = "runas";
//And that gives the order
//From here on it should be 100% identical to the Run Dialog (Windows+R), except for the part with the Elevation
System.Diagnostics.Process.Start(startInfo);
}
}
}
Note that regardless how you try to elevate, Eleveation can fail in very rare OS settings.

Accessing Files from UNC Network Path in C# Application

I have a desktop application in which the user is able to specify the input and output directories.Things work fine for local directories;but people have started complaining about network locations accessed using UNC Naming Conventions.
If the user pastes the UNC Path,the code checks if the Directory exists using the following method
if(Directory.Exists(selecteddir)
{
// all good
}
This method returns false for some network locations situated on other machines.I have tested using default local machine UNC Path \\?\C:\my_dir and the code works fine.
The application runs with administrative rights .
Im new to accessing network locations in C# Code.Is there any specific way to do this? If the user has already performed windows based authentication for the UNC Shares,wont these shares be accessible by the c# application?
Please advice on how to go forward.
Update:
I have also tried using directory info
DirectoryInfo info1 = new DirectoryInfo(#textbox.Text);
if (info1.Exists)
{
return true;
}
I have faced this situation many times. In the end, I believe that there is some issue with Directory.Exist method and I leave it.
Now, I am using DirectoryInfo class to check that like this.
DirectoryInfo info = new DirectoryInfo(#"Your Path");
if (info.Exists)
{
}
It is working fine for now. So there are other reasons too but it works for me. And of course, it does not resolve the impersonation issue.

Can you make a C# program which can not access to any local file system other than the folder it is installed?

Let me ask whether you can make a C# program which can not access to any local file system other than the folder/sub folders it is installed? And how if the answer is yes.
For details if it is necessary and possible, users are supposed to accept the program runs under a special user account which is restricted the file access only to the folder it is installed and to sub folders.
Thank you very much in advance.
Edit : Let me add context. I want users do not change their accounts. And as a programmer I do not have complete control over the program for some reasons.
Can you make a C# program which cannot access any part of the local file system other than the directory in which it is installed?
No, because every C# program will need to at the very least have access to the .NET runtime libraries, which are in the Windows install directory.
My suggestion to you is that you look into isolated storage. The .NET code access security system enables you to set a policy which states that certain programs only get to access the .NET runtime, the installed location of the code, and a special "isolated storage" directory that can be used for the application to store per-user data.
The answer is yes, but how you do this is complicated.
First, you need a user account with extremely limited permissions. It must be able to access files and run programs within the installation directory of the program, and that's pretty much it. You can create such a user with the installer program, using tools in the System.DirectoryServices namespace. Here's an example of creating a user:
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
private void CreateUser(string userName, string password)
{
DirectorySearcher dseSearcher = new DirectorySearcher();
string rootDSE = dseSearcher.SearchRoot.Path;
string userDSE = rootDSE.Insert(7, "OU=Users,");
DirectoryEntry userDE = new DirectoryEntry(userDSE);
DirectoryEntry user = userDE.Children.Add("CN=" + userID, "user");
staff.Properties["samAccountName"].Value = userID;
staff.Properties["UserPrincipalName"].Value = userName +
#"#domain";
staff.CommitChanges();
staff.Properties["userAccountControl"].Value =
ActiveDs.ADS_USER_FLAG.ADS_UF_NORMAL_ACCOUNT |
ActiveDs.ADS_USER_FLAG.ADS_UF_DONT_EXPIRE_PASSWD;
staff.CommitChanges();
staff.Invoke("SetPassword", new Object[] { password });
}
Now, once that's happened, you need to make sure your program normally runs in the context of that user account. You can do that by specifying the user account to run the program with in a ProcessStartInfo object, used by a "bootstrapper" program that is what you create shortcuts for. You can then also ensure the program is running in the context of that user account using Environment.CurrentUser, and abort execution of the program if it is being run by any more permissive account.
If you just want to restrict the program to a particular account, you can look up the user's credentials, and exit the program if it's not the right one.
http://msdn.microsoft.com/en-us/library/csyx45b8.aspx
http://msdn.microsoft.com/en-us/library/sfs49sw0.aspx

Writing to a file I get unauthorized access error.How can I do it?

Despite numerous post on the web I cannot find an answer to my problem.
I am writing an application that writes csv files to folders.Users should be able to pick a directory.
I am developing in windows 7 using vs2010 running my app in Admin Mode.Regardless of all this I still get the "Unauthorized access exception" when I do
var path=#"c:\" or c:\MyFolder
StringBuilder sb=new StringBuilder();
sb.AppendLine("Test");
var myFile=sb.ToString();
using (var writer=new StreamWriter(path))
{
writer.Write(myFile);
}
Am I missing something?
I have feeling that in window7 you can only write to designated folders.Is this what's happening?
any suggestions?
EDITED
I have created few folders under "C:\MyFolder\"
I am not using any credentials eg windows impersonation etc..
It does write if it writes to the bin\debug\ of my class library. but not to any designated folder.
Is your code snippet the real code causing the problem?
On the face of it, you are trying to stream the text "Test" into a directory on the file system, not trying to write a file. (path is just assigned to #"C:\"). I'm not surprised that you get an UnauthorizedAccessException.
Assign the full path of the file you want to write into your path variable, and I imagine you'll succeed.
Try running your app with "Run as Administrator". The comments above will probably also steer you in the right direction. You should definitely pick a directory that your windows users has access to edit.

Is there an way to programmatically read a file from a TrueCrypt disk into memory?

I need to load a file from an umounted TrueCrypt disk into memory. Is there any way to do this programmatically? Does TrueCrypt offer an API?
The way I believe is best for attempting this would be to mount the volume (prompting the user for a password, of course), open the file, and then unmount the volume. Is there a way to do this all automatically?
I am on Windows Vista. I have C#, Python, and Perl readily available.
Can you not use the true crypt command line from say System.Diagnostics.Process?
using System;
using System.Diagnostics;
namespace Test {
class TrueCrypeStart
{
static void Main(string[] args)
{
string password = getPassword(...);
Process tc= new Process();
tc.StartInfo.FileName = "TrueCrypt.exe";
tc.StartInfo.Arguments = string.Format("/v \"{0}\" /p \"{1}\" /q", ...mount info ..., password); // for quiet!
tc.Start();
}
}
}
TrueResize includes an open-source C# TrueCrypt library that will allow you to read the encrypted volume (without having to mount it), an additional library includes NTFS support.

Categories