/// <summary> /// Provides a record-by-record processing functionality for the cmdlet. /// </summary> protected override void ProcessRecord() { Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] bytes = mycrypt.GetBytes(this.Message, Cryptkeeper.Action.Encrypt); AlternateDataStream.Write(this.Path.FullName, this.Stream, bytes); this.WriteObject("Message saved."); }
/// <summary> /// Provides a record-by-record processing functionality for the cmdlet. /// </summary> protected override void ProcessRecord() { byte[] bytes = AlternateDataStream.Read(this.Path.FullName, this.Stream); if (bytes == null) { this.WriteObject("No message."); return; } Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] cleartext = mycrypt.GetBytes(bytes, Cryptkeeper.Action.Decrypt); string text = System.Text.Encoding.Unicode.GetString(cleartext); this.WriteObject(text); }
/// <summary> /// Read a message using the Least Significant Bit Steganographic method. /// </summary> /// <param name="path">The bitmap file to write to.</param> /// <param name="startingPosition">The starting byte address.</param> /// <param name="mathset">The set to use to determine where to update the least significant bits.</param> /// <param name="passphrase">The passphrase for encrypting and decrypting the message text.</param> /// <returns>Returns the message in Unicode characters.</returns> public static string SteganographyRead(string path, uint startingPosition, ChannelTools.MathematicalSet mathset, SecureString passphrase) { // Read the value in as bytes and convert to Unicode string byte[] cipherBytes = SteganographyReadBytes(path, startingPosition, mathset); // Decrypt the message Cryptkeeper crypt = new Cryptkeeper(passphrase); byte[] messageBytes = crypt.GetBytes(cipherBytes, Cryptkeeper.Action.Decrypt); string finaltext = new string(Encoding.Unicode.GetChars(messageBytes)); // Find the stop character: 0xFFFF or 65,535 int endof = finaltext.IndexOf(Convert.ToChar(ushort.MaxValue)); // No final character? Return an empty string if (endof == -1) return string.Empty; // Return the string from the start to the stop character return finaltext.Substring(0, endof).TrimStart(); }
/// <summary> /// Provides a record-by-record processing functionality for the cmdlet. /// </summary> protected override void ProcessRecord() { //// Encode and encrypt the message with spoofed entropy Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] cipherbytes = mycrypt.GetBytes(this.Message, Cryptkeeper.Action.Encrypt); int length = cipherbytes.Length; if (this.TargetEntropy > 0) length = length * 3; byte[] bytes = ShannonEntropy.Spoof(cipherbytes, this.TargetEntropy, length); //// Create a Memory Mapped File without an actual file string mappedName = string.Concat("Global\\", this.Mutex); string mutexName = string.Concat("Global\\{0}", this.Mutex, "-mutex"); MemoryMappedFile map; try { map = MemoryMappedFile.CreateOrOpen(mappedName, bytes.Length, MemoryMappedFileAccess.ReadWrite); } catch (Exception ex) { this.WriteWarning(ex.Message); return; } // Define an access rules such that all processes on the OS can access it var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); var securitySettings = new MutexSecurity(); securitySettings.AddAccessRule(allowEveryoneRule); // Grab the mutex and set the access rules Mutex mutex = new Mutex(false, mutexName); mutex.SetAccessControl(securitySettings); mutex.WaitOne(); // Write the bytes BinaryWriter writer = new BinaryWriter(map.CreateViewStream(0, bytes.Length, MemoryMappedFileAccess.ReadWrite)); writer.Write(bytes); writer.Close(); mutex.ReleaseMutex(); Console.WriteLine("Please check for the message now. Once you continue, the message will be scheduled for garbage collection."); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); Console.WriteLine(); mutex.Dispose(); }
/// <summary> /// The handler for HTTP GET requests. /// </summary> /// <param name="processor">The HTTP processor.</param> public void HttpGetHandler(HttpProcessor processor) { processor.WriteSuccess(); Cryptkeeper myCrypt = new Cryptkeeper(this.passphrase); DerivedValue derived = new DerivedValue(this.passphrase); string result = derived.GetString(3, 10); // No result? No handshake. Done. if (processor.RequestURL.IndexOf(result) == -1) return; // Parse out the host name and fetch the next page. string hostname = string.Empty; string absolutePath = processor.RequestURL; string[] values = absolutePath.Split(new string[] { result }, StringSplitOptions.RemoveEmptyEntries); absolutePath = values[0].Trim(); string hostBase64 = values[1].Trim(); byte[] hostBytes = System.Convert.FromBase64String(hostBase64); hostname = Encoding.ASCII.GetString(hostBytes); Uri link = new Uri(string.Concat("http://", hostname, absolutePath)); try { WebClient web = new WebClient(); byte[] page = web.DownloadData(link); web.Dispose(); WebPageSteganography stegopage = new WebPageSteganography(page, this.passphrase); string message = string.Empty; if (this.MessageQueue.Count > 0) { message = (string)this.MessageQueue.Dequeue(); } stegopage.WriteValue(message); page = stegopage.GetBytes(); processor.StreamOutput.Write(page); processor.StreamOutput.Flush(); processor.WriteSuccess(); } catch (Exception ex) { processor.StreamOutput.Write("<html><p>Ping! Something odd happened while retrieving ... " + link.ToString() + "</p><p>" + ex.ToString() + "</p></html>"); } }
/// <summary> /// Send incognito message via DNS and, if successful, return the value encoded in Base64. /// </summary> /// <param name="message">The Unicode character string to send over the covert channel.</param> /// <returns>String.Empty if the message fails, otherwise, the encrypted message encoded in Base64.</returns> private string SendCovertMessage(string message) { // Execute the covert channel this.messageId++; ushort fragmentId = 0; // Ensure the line is at least 16 Byte (128 bit) for encryption do { message += " "; } while (message.Length < 16); Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] messageBytes = mycrypt.GetBytes(message, Cryptkeeper.Action.Encrypt); // Setup the DNS calls array, count, and index int hostIndex = 0; int hostCount = (int)Math.Ceiling((decimal)messageBytes.Length / (decimal)this.messagelist.MaximumByteLength); string[] hosts = new string[hostCount]; for (int i = 0; i < messageBytes.Length; i += this.messagelist.MaximumByteLength) { ushort length = (ushort)Math.Min(this.messagelist.MaximumByteLength, messageBytes.Length - i); byte[] msg = BitConverter.GetBytes(this.messageId); byte[] frag = BitConverter.GetBytes(fragmentId); byte[] len = BitConverter.GetBytes(length); byte[] blendme = new byte[6]; blendme[0] = msg[0]; blendme[1] = msg[1]; blendme[2] = frag[0]; blendme[3] = frag[1]; blendme[4] = len[0]; blendme[5] = len[1]; byte[] tmp = new byte[length]; Array.Copy(messageBytes, i, tmp, 0, length); BitArray mine = BinaryTools.BlendBits(tmp, blendme, 5); string fragment = SimWitty.Library.Core.Encoding.Base32.ToBase32String(mine); hosts[hostIndex] = string.Concat( "www.", fragment, ".com."); hostIndex++; fragmentId++; } // Randomize the fragmments ArrayTools.Scramble(hosts); // Send the fragments as DNS hosts using Nslookup for (int i = 0; i < hosts.Length; i++) { this.ExecuteNslookup(hosts[i], this.RemoteAddress); } return System.Convert.ToBase64String(messageBytes); }
/// <summary> /// Provides a record-by-record processing functionality for the cmdlet. /// </summary> protected override void ProcessRecord() { //// Open a Memory Mapped File without an actual file string memoryMappedName = string.Concat("Global\\", this.Mutex); // mappedName string memoryMutexName = string.Concat("Global\\{0}", this.Mutex, "-mutex"); // mutexName MemoryMappedFile map; try { map = MemoryMappedFile.OpenExisting(memoryMappedName); } catch (Exception ex) { this.WriteWarning(ex.Message); return; } // Open a existing mutex and prepare to receive Mutex mutex = System.Threading.Mutex.OpenExisting(memoryMutexName); mutex.WaitOne(); // Read the memory map and release the mutex BinaryReader reader = new BinaryReader(map.CreateViewStream()); byte[] receiveBytes = new byte[reader.BaseStream.Length]; reader.Read(receiveBytes, 0, (int)reader.BaseStream.Length); reader.Close(); mutex.ReleaseMutex(); // Remove spoofing, decrypt, decode, and display the message Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] cipherbytes = ShannonEntropy.Despoof(receiveBytes); byte[] clearbytes = mycrypt.GetBytes(cipherbytes, Cryptkeeper.Action.Decrypt); string message = System.Text.Encoding.Unicode.GetString(clearbytes); this.WriteObject(message); }
/// <summary> /// Write a message using the Least Significant Bit Steganographic method. /// </summary> /// <param name="path">The bitmap file to write to.</param> /// <param name="startingPosition">The starting byte address.</param> /// <param name="message">The message in Unicode characters.</param> /// <param name="mathset">The set to use to determine where to update the least significant bits.</param> /// <param name="passphrase">The passphrase for encrypting and decrypting the message text.</param> public static void SteganographyWrite(string path, uint startingPosition, string message, ChannelTools.MathematicalSet mathset, SecureString passphrase) { // Append the stop character: 0xFFFF or 65,535 message += Convert.ToChar(ushort.MaxValue); // Encrypt the message Cryptkeeper crypt = new Cryptkeeper(passphrase); byte[] cipherBytes = crypt.GetBytes(message, Cryptkeeper.Action.Encrypt); // Write the encoded and encrypted message SteganographyWrite(path, startingPosition, cipherBytes, mathset); }
/// <summary> /// Send incognito message via ping and, if successful, return the value encoded in Base16. /// </summary> /// <param name="message">The Unicode character string to send over the covert channel.</param> /// <returns>String.Empty if the message fails, otherwise, the message encoded in Base16.</returns> private string SendCovertMessage(string message) { // Encode the message byte[] bytes = ChannelTools.EncodeString(message.Trim()); // Encrypt the message Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] messageBytes = mycrypt.GetBytes(bytes, Cryptkeeper.Action.Encrypt); // Get two bytes that represent the length of the messageBytes array byte[] lengthBytes = BitConverter.GetBytes(Convert.ToUInt16(messageBytes.Length)); // Create the ping bytes (length + encrypted message) byte[] pingBytes = new byte[messageBytes.Length + 2]; Array.Copy(lengthBytes, 0, pingBytes, 0, 2); Array.Copy(messageBytes, 0, pingBytes, 2, messageBytes.Length); // Double-check ushort length = BitConverter.ToUInt16(new byte[] { pingBytes[0], pingBytes[1] }, 0); byte[] checkBytes = mycrypt.GetBytes(messageBytes, Cryptkeeper.Action.Decrypt); string checkText = ChannelTools.DecodeString(checkBytes); if (message != checkText) return string.Empty; // Send the message in a ping try { Ping p = new Ping(); p.Send(this.RemoteAddress, 1000, pingBytes); } catch (Exception ex) { this.WriteWarning(ex.ToString()); return string.Empty; } // Return the message encoded in Base64. return SimWitty.Library.Core.Encoding.Base16.ToBase16String(checkBytes); }
/// <summary> /// Write -- encode, encrypt, and hide the steganographic message. /// </summary> /// <param name="value">The text value to write into the page.</param> public void WriteValue(string value) { Cryptkeeper myCrypt = new Cryptkeeper(this.passphrase); byte[] cipherBytes = myCrypt.GetBytes(value, Cryptkeeper.Action.Encrypt); byte[] cleartext = myCrypt.GetBytes(cipherBytes, Cryptkeeper.Action.Decrypt); byte[] lengthBytes = BitConverter.GetBytes((uint)cipherBytes.Length); byte[] buffer = new byte[lengthBytes.Length + cipherBytes.Length]; Array.Copy(lengthBytes, 0, buffer, 0, lengthBytes.Length); Array.Copy(cipherBytes, 0, buffer, lengthBytes.Length, cipherBytes.Length); this.EmbedBytesInPage(buffer); // If this is a file info, write the bytes down to the file while preserving the file dates if (this.isFileInfo) { // Write the bytes to the file and then reset last access time. DateTime created = this.webPageFile.CreationTime; DateTime modified = this.webPageFile.LastWriteTime; DateTime accessed = this.webPageFile.LastAccessTime; BinaryWriter writeFile = new BinaryWriter(File.Open(this.webPageFile.FullName, FileMode.Create)); writeFile.Write(this.GetBytes()); writeFile.Close(); this.webPageFile.CreationTime = created; this.webPageFile.LastWriteTime = modified; this.webPageFile.LastAccessTime = accessed; } }
/// <summary> /// Read -- decrypt, decode, and display the steganographic message. /// </summary> /// <returns>Returns the clear text message.</returns> public string ReadValue() { // Always use GetBytes because GetBytes does error handling byte[] buffer = this.GetBytes(); // Extract the first four bytes as an unsigned integer specifying length byte[] lengthBytes = new byte[4]; lengthBytes[0] = buffer[this.Positions[0]]; lengthBytes[1] = buffer[this.Positions[1]]; lengthBytes[2] = buffer[this.Positions[2]]; lengthBytes[3] = buffer[this.Positions[3]]; uint length = BitConverter.ToUInt32(lengthBytes, 0); // If the length is 0, there is no message, and we return an empty string if (length == 0) return string.Empty; // Extract the encrypted bytes byte[] cipherBytes = new byte[length]; for (int i = 0; i < cipherBytes.Length; i++) { // It should not happen, but just in case, prevent an index out of range exception if (i >= buffer.Length) break; // We start at length bytes and increment the position index from that point uint position = this.Positions[lengthBytes.Length + i]; byte stegoByte = buffer[position]; cipherBytes[i] = stegoByte; } // Decrypt and return Cryptkeeper myCrypt = new Cryptkeeper(this.passphrase); byte[] cleartext = myCrypt.GetBytes(cipherBytes, Cryptkeeper.Action.Decrypt); string value = Encoding.Unicode.GetString(cleartext); return value; }
/// <summary> /// Initializes a new instance of the <see cref="IncogStream" /> class. /// </summary> /// <param name="stream">The stream to write to and read from.</param> /// <param name="passphrase">The secure string used to encrypt messages written to the stream and decrypt messages read from the stream.</param> /// <param name="entropy">The approximate Shannon Entropy value (between 1.00 and 7.80) to spoof.</param> public IncogStream(Stream stream, SecureString passphrase, double entropy) { this.innerStream = stream; this.mycrypt = new Cryptkeeper(passphrase); if (entropy > 0) this.targetEntropy = entropy; }
/// <summary> /// Initializes a new instance of the <see cref="IncogStream" /> class. /// </summary> /// <param name="stream">The stream to write to and read from.</param> /// <param name="passphrase">The secure string used to encrypt messages written to the stream and decrypt messages read from the stream.</param> public IncogStream(Stream stream, SecureString passphrase) { this.innerStream = stream; this.mycrypt = new Cryptkeeper(passphrase); this.targetEntropy = 0; }
/// <summary> /// Decrypts the fragments values of this instance into a clear text message string using the passphrase. /// </summary> /// <param name="passphrase">Decryption key</param> /// <returns>Decrypted message string</returns> public string GetDecryptedMessage(System.Security.SecureString passphrase) { if (!this.Complete) return string.Empty; Cryptkeeper mycrypt = new Cryptkeeper(passphrase); string cleartext = mycrypt.Decrypt(this.GetBytes()); return cleartext; }
/// <summary> /// Receive incognito message via ping and, if successful, put the value on the pipeline. /// </summary> /// <param name="rawPacket">The raw bytes that were captured.</param> private void ReceiveCovertMessage(byte[] rawPacket) { try { int length = rawPacket.Length; IPv4Packet packet = new IPv4Packet(rawPacket, length); if (packet.SourceAddress.Equals(this.RemoteAddress) && packet.ProtocolType == Protocol.ICMP) { ushort len = BitConverter.ToUInt16(new byte[] { packet.Data[8], packet.Data[9] }, 0); byte[] messageBytes = new byte[len]; Array.Copy(packet.Data, 10, messageBytes, 0, len); this.WriteVerbose(SimWitty.Library.Core.Encoding.Base16.ToBase16String(messageBytes)); Cryptkeeper mycrypt = new Cryptkeeper(this.Passphrase); byte[] checkedBytes = mycrypt.GetBytes(messageBytes, Cryptkeeper.Action.Decrypt); string message = ChannelTools.DecodeString(checkedBytes); if (message.Trim().ToLower() == "exit") { this.packetCapturing = false; return; } if (this.Interactive) { Console.WriteLine("{0} > {1}", packet.SourceAddress.ToString(), message); } else { this.WriteObject(message); } } } catch (ObjectDisposedException) { } catch (Exception ex) { this.WriteWarning(ex.ToString()); } }