private static bool ReadPassword() { ConsoleKeyInfo consoleKey = Console.ReadKey(true); while (consoleKey.Key != ConsoleKey.Enter) { if (consoleKey.Key == ConsoleKey.Escape) { return false; } _password.AppendChar(consoleKey.KeyChar); consoleKey = Console.ReadKey(true); } return _password.Length > 0; }
public sealed class CryptedData { /// <summary> /// . /// </summary> public byte[] IV { get; set; } /// <summary> /// . /// </summary> public byte[] EncryptedSource { get; set; } /// <summary> /// . /// </summary> public byte[] ToArray() { using (MemoryStream ms = new MemoryStream()) { Store(ms); return ms.ToArray(); } } /// <summary> /// . /// </summary> /// <param name="output">, .</param> public void Store(Stream output) { Validate(this); if (!output.CanWrite) { throw new ArgumentException(" ", "output"); } using (BinaryWriter bw = new BinaryWriter(output)) { bw.Write(IV.Length); bw.Write(IV); bw.Write(EncryptedSource.Length); bw.Write(EncryptedSource); } } /// <summary> /// . /// </summary> /// <param name="input"> .</param> public static CryptedData Create(Stream input) { if (!input.CanRead) { throw new ArgumentException(" ", "input"); } CryptedData data = new CryptedData(); using (BinaryReader reader = new BinaryReader(input)) { int ivLength = reader.ReadInt32(); data.IV = reader.ReadBytes(ivLength); int sourceLength = reader.ReadInt32(); data.EncryptedSource = reader.ReadBytes(sourceLength); } Validate(data); return data; } /// <summary> /// . /// </summary> /// <param name="data">, .</param> private static void Validate(CryptedData data) { if (data.IV == null || data.IV.Length == 0) { throw new ArgumentException("IV "); } if (data.IV.Length > byte.MaxValue) { throw new ArgumentException(" IV " + byte.MaxValue); } if (data.EncryptedSource == null || data.EncryptedSource.Length == 0) { throw new ArgumentException("Souce "); } } }
public static class AesCryptography { /// <summary> /// . /// </summary> /// <returns></returns> internal static byte[] CreateIv() { using (AesManaged aes = new AesManaged()) { aes.GenerateIV(); return aes.IV; } } /// <summary> /// . /// </summary> /// <param name="source">.</param> /// <param name="key"> .</param> /// <param name="iv"> .</param> /// <returns> .</returns> internal static byte[] Encrypt(byte[] source, byte[] key, byte[] iv) { Validate(source, key, iv); using (AesManaged aes = new AesManaged()) { using (ICryptoTransform transform = aes.CreateEncryptor(key, iv)) { using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write)) { cs.Write(source, 0, source.Length); } byte[] encryptedBytes = ms.ToArray(); return encryptedBytes; } } } } /// <summary> /// . /// </summary> /// <param name="source"> .</param> /// <param name="key"> .</param> /// <param name="iv"> .</param> /// <returns> .</returns> internal static byte[] Decrypt(byte[] source, byte[] key, byte[] iv) { Validate(source, key, iv); using (AesManaged aes = new AesManaged()) { using (ICryptoTransform transform = aes.CreateDecryptor(key, iv)) { using (MemoryStream ms = new MemoryStream(source)) { using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read)) { List<byte> bytes = new List<byte>(1024); int b; while ((b = cs.ReadByte()) != -1) { bytes.Add((byte)b); } return bytes.ToArray(); } } } } } /// <summary> /// . /// </summary> /// <param name="source">.</param> /// <param name="key"> .</param> /// <param name="iv"> .</param> private static void Validate(byte[] source, byte[] key, byte[] iv) { if (source == null) { throw new ArgumentNullException("source"); } else if (source.Length == 0) { throw new ArgumentException(" ", "source"); } if (key == null) { throw new ArgumentNullException("key"); } else if (key.Length == 0) { throw new ArgumentException(" ", "key"); } if (key.Length.IsOneOf(16, 24, 32) == false) { throw new ArgumentException(" 128, 192 256 (16, 24, 32 )", "key"); } if (iv == null) { throw new ArgumentNullException("iv"); } else if (iv.Length != 16) { throw new ArgumentException(" 128 (16 )", "iv"); } } public static bool IsOneOf<T>(this T value, params T[] values) { return value.IsOneOf(values as IEnumerable<T>); } public static bool IsOneOf<T>(this T value, IEnumerable<T> values) { if (values == null) { throw new ArgumentNullException("values"); } foreach (T t in values) { if (Equals(t, value)) { return true; } } return false; } }
internal static class CryptographyHelper { /// <summary> /// . /// </summary> /// <param name="source"> .</param> /// <param name="password"> .</param> /// <returns></returns> public static CryptedData Encrypt(byte[] source, SecureString password) { byte[] iv = AesCryptography.CreateIv(); byte[] key = GetKey(password); byte[] encrypted = AesCryptography.Encrypt(source, key, iv); return new CryptedData() { EncryptedSource = encrypted, IV = iv }; } /// <summary> /// . /// </summary> /// <param name="data">, .</param> /// <param name="password"> .</param> /// <returns> .</returns> public static byte[] Decrypt(CryptedData data, SecureString password) { byte[] key = GetKey(password); byte[] decrypted = AesCryptography.Decrypt(data.EncryptedSource, key, data.IV); return decrypted; } /// <summary> /// . /// </summary> /// <param name="key">, .</param> /// <returns></returns> private static byte[] GetKey(SecureString key) { using (InsecureString insecure = new InsecureString(key)) { using (SHA256Managed sha256 = new SHA256Managed()) { byte[] rawKey = new byte[key.Length]; int i = 0; foreach (char c in insecure) { rawKey[i++] = Convert.ToByte(c); } byte[] hashedKey = sha256.ComputeHash(rawKey); Array.Clear(rawKey, 0, rawKey.Length); return hashedKey; } } } }
[CLSCompliant(false)] public sealed class InsecureString : IDisposable, IEnumerable<char> { internal InsecureString(SecureString secureString) { _secureString = secureString; Initialize(); } public string Value { get; private set; } private readonly SecureString _secureString; private GCHandle _gcHandle; #if !DEBUG [DebuggerHidden] #endif private void Initialize() { unsafe { // We are about to create an unencrypted version of our sensitive string and store it in memory. // Don't let anyone (GC) make a copy. // To do this, create a new gc handle so we can "pin" the memory. // The gc handle will be pinned and later, we will put info in this string. _gcHandle = new GCHandle(); // insecurePointer will be temporarily used to access the SecureString IntPtr insecurePointer = IntPtr.Zero; RuntimeHelpers.TryCode code = delegate { // create a new string of appropriate length that is filled with 0's Value = new string((char)0, _secureString.Length); // Even though we are in the ExecuteCodeWithGuaranteedCleanup, processing can be interupted. // We need to make sure nothing happens between when memory is allocated and // when _gcHandle has been assigned the value. Otherwise, we can't cleanup later. // PrepareConstrainedRegions is better than a try/catch. Not even a threadexception will interupt this processing. // A CER is not the same as ExecuteCodeWithGuaranteedCleanup. A CER does not have a cleanup. Action alloc = delegate { _gcHandle = GCHandle.Alloc(Value, GCHandleType.Pinned); }; ExecuteInConstrainedRegion(alloc); // Even though we are in the ExecuteCodeWithGuaranteedCleanup, processing can be interupted. // We need to make sure nothing happens between when memory is allocated and // when insecurePointer has been assigned the value. Otherwise, we can't cleanup later. // PrepareConstrainedRegions is better than a try/catch. Not even a threadexception will interupt this processing. // A CER is not the same as ExecuteCodeWithGuaranteedCleanup. A CER does not have a cleanup. Action toBSTR = delegate { insecurePointer = Marshal.SecureStringToBSTR(_secureString); }; ExecuteInConstrainedRegion(toBSTR); // get a pointer to our new "pinned" string char* value = (char*)_gcHandle.AddrOfPinnedObject(); // get a pointer to the unencrypted string char* charPointer = (char*)insecurePointer; // copy for (int i = 0; i < _secureString.Length; i++) { value[i] = charPointer[i]; } }; RuntimeHelpers.CleanupCode cleanup = delegate { // insecurePointer was temporarily used to access the securestring // set the string to all 0's and then clean it up. this is important. // this prevents sniffers from seeing the sensitive info as it is cleaned up. if (insecurePointer != IntPtr.Zero) { Marshal.ZeroFreeBSTR(insecurePointer); } }; // Better than a try/catch. Not even a threadexception will bypass the cleanup code RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, cleanup, null); } } #if !DEBUG [DebuggerHidden] #endif public void Dispose() { unsafe { // we have created an insecurestring if (_gcHandle.IsAllocated) { // get the address of our gchandle and set all chars to 0's char* insecurePointer = (char*)_gcHandle.AddrOfPinnedObject(); for (int i = 0; i < _secureString.Length; i++) { insecurePointer[i] = (char)0; } #if DEBUG string disposed = "¡DISPOSED¡"; disposed = disposed.Substring(0, Math.Min(disposed.Length, _secureString.Length)); for (int i = 0; i < disposed.Length; ++i) { insecurePointer[i] = disposed[i]; } #endif _gcHandle.Free(); } } } public IEnumerator<char> GetEnumerator() { if (_gcHandle.IsAllocated) { return Value.GetEnumerator(); } else { return new List<char>().GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static void ExecuteInConstrainedRegion(Action action) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { action(); } } }
/// <summary> /// . /// </summary> private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args) { string[] fileParts = args.Name.Split(",".ToCharArray()); string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileParts[0] + ".edll"); string symbolsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileParts[0] + ".epdb"); byte[] assemblyBytes = null, symbolsBytes = null; if (File.Exists(assemblyPath)) { assemblyBytes = DecryptFile(assemblyPath); } if (File.Exists(symbolsPath)) { symbolsBytes = DecryptFile(symbolsPath); } return Assembly.Load(assemblyBytes, symbolsBytes); } /// <summary> /// . /// </summary> /// <param name="path"> .</param> /// <returns> .</returns> private static byte[] DecryptFile(string path) { CryptedData data; using (FileStream fs = File.OpenRead(path)) { data = CryptedData.Create(fs); } byte[] bytes = CryptographyHelper.Decrypt(data, _password); return bytes; }
static Program() { AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) => Console.WriteLine(eventArgs.ExceptionObject.ToString()); AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve; _password = new SecureString(); }
private static void RunApplication() { SetConsoleWindowVisibility(false); App app = new App(); MainWindow window = new MainWindow(); app.Run(window); }
[DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
/// <summary> /// . /// </summary> /// <param name="visible"> .</param> private static void SetConsoleWindowVisibility(bool visible) { IntPtr hWnd = FindWindow(null, Console.Title); if (hWnd != IntPtr.Zero) { if (visible) ShowWindow(hWnd, 1); //1 = SW_SHOWNORMAL else ShowWindow(hWnd, 0); //0 = SW_HIDE } }
[STAThread] public static void Main(string[] args) { // try { ArgumentException ex = new ArgumentException("There is not enough data to start application"); throw ex; } catch (ArgumentException ex) { Console.WriteLine(ex.ToString()); Console.WriteLine("Press Esc to exit"); } if (!ReadPassword()) return; RunApplication(); }
/// <summary> /// . /// </summary> private static void EncryptAssemblies() { Wiper wiper = new Wiper(); foreach (string file in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")) { byte[] source = File.ReadAllBytes(file); CryptedData crypted = CryptographyHelper.Encrypt(source, _password); string resultPath = Path.Combine(Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file) + ".edll"); File.WriteAllBytes(resultPath, crypted.ToArray()); // wiper.WipeFile(file, 3); //File.Delete(file); } string currentAssemblyName = Assembly.GetEntryAssembly().GetName().Name; foreach (string file in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.pdb")) { if (Path.GetFileNameWithoutExtension(file) == currentAssemblyName) continue; byte[] source = File.ReadAllBytes(file); CryptedData crypted = CryptographyHelper.Encrypt(source, _password); string resultPath = Path.Combine(Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file) + ".epdb"); File.WriteAllBytes(resultPath, crypted.ToArray()); // wiper.WipeFile(file, 3); } }
internal sealed class Wiper { /// <summary> /// Deletes a file in a secure way by overwriting it with /// random garbage data n times. /// </summary> /// <param name="filename">Full path of the file to be deleted</param> /// <param name="timesToWrite">Specifies the number of times the file should be overwritten</param> public void WipeFile(string filename, int timesToWrite) { if (File.Exists(filename)) { // Set the files attributes to normal in case it's read-only. File.SetAttributes(filename, FileAttributes.Normal); // Calculate the total number of sectors in the file. double sectors = Math.Ceiling(new FileInfo(filename).Length / 512.0); // Create a dummy-buffer the size of a sector. byte[] dummyBuffer = new byte[512]; // Create a cryptographic Random Number Generator. // This is what I use to create the garbage data. using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { // Open a FileStream to the file. FileStream inputStream = new FileStream(filename, FileMode.Open); for (int currentPass = 0; currentPass < timesToWrite; currentPass++) { // Go to the beginning of the stream inputStream.Position = 0; // Loop all sectors for (int sectorsWritten = 0; sectorsWritten < sectors; sectorsWritten++) { // Fill the dummy-buffer with random data rng.GetBytes(dummyBuffer); // Write it to the stream inputStream.Write(dummyBuffer, 0, dummyBuffer.Length); } } // Truncate the file to 0 bytes. // This will hide the original file-length if you try to recover the file. inputStream.SetLength(0); // Close the stream. inputStream.Close(); // As an extra precaution I change the dates of the file so the // original dates are hidden if you try to recover the file. DateTime dt = new DateTime(2037, 1, 1, 0, 0, 0); File.SetCreationTime(filename, dt); File.SetLastAccessTime(filename, dt); File.SetLastWriteTime(filename, dt); File.SetCreationTimeUtc(filename, dt); File.SetLastAccessTimeUtc(filename, dt); File.SetLastWriteTimeUtc(filename, dt); // Finally, delete the file File.Delete(filename); } } } }
Source: https://habr.com/ru/post/244031/
All Articles