Basic response recv system implemented

todo ping-pong for alive host. thread's content is  in websocket.rb
todo setting up a separate handler for via ws answer's
This commit is contained in:
Graziano Felline
2012-04-18 12:00:17 +02:00
parent 2198c69aa8
commit 656262c0f4
6 changed files with 298 additions and 247 deletions

View File

@@ -14,118 +14,119 @@
# limitations under the License.
#
module BeEF
module Core
module NetworkStack
module Handlers
# @note DynamicHandler is used reconstruct segmented traffic from the hooked browser
class DynamicReconstruction < BeEF::Core::Router::Router
module Core
module NetworkStack
module Handlers
# @note holds packet queue
PQ = Array.new()
# @note DynamicHandler is used reconstruct segmented traffic from the hooked browser
class DynamicReconstruction < BeEF::Core::Router::Router
# @note obtain dynamic mount points from HttpHookServer
MOUNTS = BeEF::Core::Server.instance.mounts
# @note holds packet queue
PQ = Array.new()
before do
error 404 unless !params.empty?
headers 'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0'
end
# @note obtain dynamic mount points from HttpHookServer
MOUNTS = BeEF::Core::Server.instance.mounts
# Combines packet information and pushes to PQ (packet queue), then checks packets
get '/' do
headers 'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0',
'Content-Type' => 'text/javascript',
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET'
before do
error 404 unless !params.empty?
headers 'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0'
end
PQ << {
:beefhook => params[:bh],
:stream_id => Integer(params[:sid]),
:packet_id => Integer(params[:pid]),
:packet_count => Integer(params[:pc]),
:data => params[:d]
}
# Combines packet information and pushes to PQ (packet queue), then checks packets
get '/' do
headers 'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0',
'Content-Type' => 'text/javascript',
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET'
Thread.new {
check_packets()
}
end
PQ << {
:beefhook => params[:bh],
:stream_id => Integer(params[:sid]),
:packet_id => Integer(params[:pid]),
:packet_count => Integer(params[:pc]),
:data => params[:d]
}
# Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets
def check_packets()
checked = Array.new()
PQ.each do |packet|
if (checked.include?(packet[:beefhook]+':'+String(packet[:stream_id])))
Thread.new {
check_packets()
}
end
# Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets
def check_packets()
checked = Array.new()
PQ.each do |packet|
if (checked.include?(packet[:beefhook]+':'+String(packet[:stream_id])))
next
end
checked << packet[:beefhook]+':'+String(packet[:stream_id])
pc = 0
PQ.each do |p|
end
checked << packet[:beefhook]+':'+String(packet[:stream_id])
pc = 0
PQ.each do |p|
if (packet[:beefhook] == p[:beefhook] and packet[:stream_id] == p[:stream_id])
pc += 1
pc += 1
end
end
if (packet[:packet_count] == pc)
end
if (packet[:packet_count] == pc)
packets = expunge(packet[:beefhook], packet[:stream_id])
data = ''
packets.each_with_index do |sp,i|
if (packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id])
data += sp[:data]
end
packets.each_with_index do |sp, i|
if (packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id])
data += sp[:data]
end
end
b64 = Base64.decode64(data)
b64 = Base64.decode64(data)
begin
res = JSON.parse(b64).first
res['beefhook'] = packet[:beefhook]
res['request'] = request
res['beefsession'] = request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
execute(res)
res = JSON.parse(b64).first
res['beefhook'] = packet[:beefhook]
res['request'] = request
res['beefsession'] = request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
execute(res)
rescue JSON::ParserError => e
print_debug 'Network stack could not decode packet stream.'
print_debug 'Dumping Stream Data [base64]: '+data
print_debug 'Dumping Stream Data: '+b64
print_debug 'Network stack could not decode packet stream.'
print_debug 'Dumping Stream Data [base64]: '+data
print_debug 'Dumping Stream Data: '+b64
end
end
end
end
end
end
# Delete packets that have been reconstructed, return deleted packets
# @param [String] beefhook Beefhook of hooked browser
# @param [Integer] stream_id The stream ID
def expunge(beefhook, stream_id)
packets = PQ.select{ |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
packets.sort_by { |p| p[:packet_id] }
end
# Delete packets that have been reconstructed, return deleted packets
# @param [String] beefhook Beefhook of hooked browser
# @param [Integer] stream_id The stream ID
def expunge(beefhook, stream_id)
packets = PQ.select { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
packets.sort_by { |p| p[:packet_id] }
end
# Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler
# @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction
def execute(data)
handler = get_param(data, 'handler')
if (MOUNTS.has_key?(handler))
if (MOUNTS[handler].class == Array and MOUNTS[handler].length == 2)
# Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler
# @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction
def execute(data)
handler = get_param(data, 'handler')
if (MOUNTS.has_key?(handler))
if (MOUNTS[handler].class == Array and MOUNTS[handler].length == 2)
MOUNTS[handler][0].new(data, MOUNTS[handler][1])
else
else
MOUNTS[handler].new(data)
end
end
end
BeEF::Core::Handlers::Commands
# Assist function for getting parameter from hash
# @param [Hash] query Hash to pull key from
# @param [String] key The key association to return from `query`
# @return Value associated with `key`
def get_param(query, key)
return nil if query[key].nil?
query[key]
end
end
end
# Assist function for getting parameter from hash
# @param [Hash] query Hash to pull key from
# @param [String] key The key association to return from `query`
# @return Value associated with `key`
def get_param(query, key)
return nil if query[key].nil?
query[key]
end
end
end
end
end
end
end

View File

@@ -13,17 +13,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
#@todo STOP POLLING
module BeEF
module Core
module Websocket
require 'singleton'
require 'json'
require 'base64'
class Websocket
# require 'singleton'
#include Singleton
#all hooked browser
include Singleton
@@activeSocket= Hash.new #empty at begin
# @note obtain dynamic mount points from HttpHookServer
MOUNTS = BeEF::Core::Server.instance.mounts
@@activeSocket= Hash.new #empty at begin
def initialize
config = BeEF::Core::Configuration.instance
@@ -43,31 +45,68 @@ module BeEF
while true
#command interpretation
message=ws.receive()
if(/BEEFHOOK=/.match(message))
messageHash= JSON.parse("#{message}")
#@note messageHash[result] is Base64 encoded
if (messageHash["cookie"]!= nil)
print_info("Browser #{ws.origin} says helo! ws is running")
#insert new connection in activesocket
@@activeSocket["#{message.split(/BEEFHOOK=/)[1]}"] = ws
@@activeSocket["#{messageHash["cookie"]}"] = ws
print_debug("In activesocket we have #{@@activeSocket}")
else
#json recv is a cmd response decode and send all to
#we have to call dynamicreconstructor handler camp must be websocket
print_info("We recived that #{messageHash}")
execute(messageHash)
end
end
end
end
}
##Alive check
# Thread.new{
#
# @@activeSocket.each_key{|key , value|
# ping send token and update beefdb whit new timestamp insert a timer
#
# }
#
#
# }
end
#@note used in command.rd return nill if browser is not in list else giveback websocket
#@param [String] browser_id the cookie value
def getsocket (browser_id)
if ( @@activeSocket[browser_id] != nil)
true
if (@@activeSocket[browser_id] != nil)
true
else
false
false
end
end
#@note send a function to hooked and ws browser
def sent (fn ,browser_id )
@@activeSocket[browser_id].send(fn)
#@param [String] fn the module to execute
#@param [String] browser_id the cookie value
def sent (fn, browser_id)
@@activeSocket[browser_id].send(fn)
end
BeEF::Core::Handlers::Commands
#call the handler for websocket cmd response
#@param [Hash] data contains the answer of a command
#@todo ve this stuff in an Handler and resolve the Module friendly name
def execute (data)
command_results=Hash.new
command_results["data"]=Base64.decode64(data["result"])
(print_error "BeEFhook is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(data["bh"])
(print_error "command_id is invalid"; return) if not BeEF::Filters.is_valid_command_id?(data["cid"])
(print_error "command name is empty"; return) if data["handler"].empty?
(print_error "command results are empty"; return) if command_results.empty?
BeEF::Core::Models::Command.save_result(data["bh"], data["cid"], data["handler"], command_results)
end
end
end
end