Added new IPEC admin_ui tab. This includes the new Wterm-based interactive shell to communicate with the BeEF_bind shellcode.

This commit is contained in:
antisnatchor
2012-10-22 16:09:34 +11:00
parent 79bf6f4a9f
commit aa1efd1c73
5 changed files with 811 additions and 4 deletions

View File

@@ -28,7 +28,12 @@
<%= script_tag 'ui/panel/tabs/ZombieTabRider.js' %>
<%= script_tag 'ui/panel/tabs/ZombieTabXssRays.js' %>
<%= script_tag 'ui/panel/PanelViewer.js' %>
<%= script_tag 'wterm/wterm.jquery.js' %>
<%= stylesheet_tag 'wterm.css' %>
<script type="text/javascript" language="JavaScript">var $jwterm = jQuery.noConflict();</script>
<%= script_tag 'ui/panel/tabs/ZombieTabIpec.js' %>
<%= script_tag 'ui/panel/PanelViewer.js' %>
<%= script_tag 'ui/panel/DataGrid.js' %>
<%= script_tag 'ui/panel/MainPanel.js' %>
<%= script_tag 'ui/panel/ZombieTab.js' %>

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
/* Basic Terminal CSS */
.wterm_terminal { background: #000; color: #fff; font-size: 1em; font-family: monospace; padding: 3px; width: 100%; height: 100%; display: block; overflow-x: none; overflow-y: auto; }
/* TODO: Input Box Width is faulty */
.wterm_terminal input { background: transparent; border: 0; color: #fff; width: 100%; font-size: 1em; font-family: monospace; outline: none; }
.wterm_terminal div:first { margin-bottom: 1em; }
.wterm_terminal .wterm_prompt { float: left; clear: left; }
.wterm_terminal form { float: left; margin: 0px; width: 75%; }
/* Themes */
.wterm_theme_green_on_black { background: #000; color: #0f0; }
.wterm_theme_green_on_black input { background: transparent; border: 0; color: #0f0; }

View File

@@ -20,8 +20,10 @@ ZombieTab = function(zombie) {
commands_tab = new ZombieTab_Commands(zombie);
requester_tab = new ZombieTab_Requester(zombie);
xssrays_tab = new ZombieTab_XssRaysTab(zombie);
ZombieTab.superclass.constructor.call(this, {
ipec_tab = new ZombieTab_IpecTab(zombie);
ZombieTab.superclass.constructor.call(this, {
id:"current-browser",
activeTab: 0,
loadMask: {msg:'Loading browser...'},
@@ -32,7 +34,7 @@ ZombieTab = function(zombie) {
forceFit: true,
type: 'fit'
},
items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab]
items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab, ipec_tab]
});
};

View File

@@ -0,0 +1,357 @@
//
// 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.
//
/*
* The Ipec Tab panel for the selected zombie.
*/
ZombieTab_IpecTab = function(zombie) {
var commands_statusbar = new Beef_StatusBar('ipec-bbar-zombie-'+zombie.session);
var req_pagesize = 30;
var ipec_config_panel = new Ext.Panel({
id: 'ipec-config-zombie-'+zombie.session,
title: 'Scan Config',
layout: 'fit',
autoscroll: true
});
function get_rest_token(){
var token = "";
var url = "/ui/modules/getRestfulApiToken.json";
$jwterm.ajax({
contentType: 'application/json',
dataType: 'json',
type: 'GET',
url: url,
async: false,
processData: false,
success: function(data){
token = data.token;
console.log(token);
},
error: function(){
console.log("Error getting RESTful API token");
}
});
return token;
}
function get_module_id(name, token){
var id = "";
var url = "/api/modules/search/" + name + "?token=" + token;
$jwterm.ajax({
contentType: 'application/json',
dataType: 'json',
type: 'GET',
url: url,
async: false,
processData: false,
success: function(data){
id = data.id;
},
error: function(){
console.log("Error getting module id.");
}
});
return id;
}
function escape_html(str) {
str = str.toString();
str = str.replace(/</g, '&lt;');
str = str.replace(/>/g, '&gt;');
// str = str.replace(/\u0022/g, '&quot;');
str = str.replace(/\u0027/g, '&#39;');
str = str.replace(/\"\"/g, '');
str = str.replace(/\\r/g, '');
str = str.replace(/\\n/g, '<br>');
str = str.replace(/\\\\/g, '\\');
str = str.replace(/\\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;');
// str = str.replace(/\\/g, '&#92;');
return str;
}
function initTerminal(zombie){
String.prototype.reverse = function() {
return this.split('').reverse().join('');
};
$jwterm( document ).ready( function() {
$jwterm('#wterm').wterm( { WIDTH: '100%', HEIGHT: '100%', WELCOME_MESSAGE: 'Welcome to BeEF Bind interactive shell. To Begin Using type \'help\'' });
});
var target_ip = "";
var target_port = "";
var command_directory = {
'eval': function( tokens ) {
tokens.shift();
var expression = tokens.join( ' ' );
var result = '';
try {
result = eval( expression );
} catch( e ) {
result = 'Error: ' + e.message;
}
return result;
},
'date': function( tokens ) {
var now = new Date();
return now.getDate() + '-' +
now.getMonth() + '-' +
( 1900 + now.getYear() )
},
'cap': function( tokens ) {
tokens.shift();
return tokens.join( ' ' ).toUpperCase();
},
'go': function( tokens ) {
var url = tokens[1];
document.location.href = url;
},
'target': function(tokens){
target_ip = tokens[1];
target_port = tokens[2];
return "Target is now " + tokens[1] + ":" + tokens[2];
},
'exec': function(tokens){
if(target_ip.length == 0 || target_port.length == 0)
return "Error: target ip or port not set."
tokens.shift(); //remove the first element (exec)
var cmd = tokens.join(' '); //needed in case of commands with options
cmd = cmd.replace(/\\/g, '\\\\'); //needed to prevent JS errors (\ need to be escaped)
var token = get_rest_token();
var mod_id = get_module_id("BeEF_bind_shell", token);
var uri = "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token;
var result = null;
$jwterm.ajax({
contentType: 'application/json',
data: JSON.stringify({"rhost":target_ip, "rport":target_port, "path":"/", "cmd":cmd}),
dataType: 'json',
type: 'POST',
url: uri,
async: false,
processData: false,
success: function(data){
console.log("data: " + data.command_id);
result = "Command [" + data.command_id + "] sent successfully";
},
error: function(){
console.log("Error sending command");
return "Error sending command";
}
});
return result;
},
'get': function(tokens){
var command_id = tokens[1];
if(command_id != null){
var token = get_rest_token();
var mod_id = get_module_id("BeEF_bind_shell", token);
var uri_results = "/api/modules/" + zombie.session + "/" + mod_id + "/"
+ command_id + "?token=" + token;
var results = "";
$jwterm.ajax({
contentType: 'application/json',
dataType: 'json',
type: 'GET',
url: uri_results,
async: false,
processData: false,
success: function(data){
$jwterm.each(data, function(i){
console.log("result [" + i +"]: " + $jwterm.parseJSON(data[i].data).data);
results += $jwterm.parseJSON(data[i].data).data;
});
},
error: function(){
console.log("Error sending command");
return "Error sending command";
}
});
results = escape_html(results);
if(results.charAt(0) == '"' && results.charAt(results.length-1) == '"')
results = results.slice(1,results.length-1);
return results;
}
},
'strrev': {
PS1: 'strrev $',
EXIT_HOOK: function() {
return 'exit interface commands';
},
START_HOOK: function() {
return 'exit interface commands';
},
DISPATCH: function( tokens ) {
return tokens.join('').reverse();
}
}
};
for( var j in command_directory ) {
$jwterm.register_command( j, command_directory[j] );
}
$jwterm.register_command( 'help', function() {
return 'target - Usage: target &lt;IP&gt; &lt;port&gt; - Send commands to the specified IP:port<br>' +
'exec - Usage exec &lt;command&gt; &lt;command options&gt; - Exec a command, returns the command id.<br>' +
'get - Usage get &lt;command id&gt; - Retrieve command results given a specified command id.<br>'
});
};
var ipec_terminal_panel = new Ext.Panel({
id: 'ipec-terminal-zombie-'+zombie.session,
title: 'Terminal',
layout: 'fit',
padding: '1 1 1 1',
autoScroll: true,
html: "<style>body { background: #000; font-size: 1em;}</style><div id='wterm'></div>",
listeners: {
afterrender : function(){
initTerminal(zombie);
}
}
});
var ipec_logs_store = new Ext.ux.data.PagingJsonStore({
storeId: 'ipec-logs-store-zombie-' + zombie.session,
url: '/ui/ipec/zombie.json',
remoteSort: false,
autoDestroy: true,
autoLoad: false,
root: 'logs',
fields: ['id', 'vector_method', 'vector_name', 'vector_poc'],
sortInfo: {field: 'id', direction: 'DESC'},
baseParams: {
nonce: Ext.get("nonce").dom.value,
zombie_session: zombie.session
}
});
var ipec_logs_bbar = new Ext.PagingToolbar({
pageSize: req_pagesize,
store: ipec_logs_store,
displayInfo: true,
displayMsg: 'Displaying history {0} - {1} of {2}',
emptyMsg: 'No history to display'
});
var ipec_logs_grid = new Ext.grid.GridPanel({
id: 'ipec-logs-grid-zombie-' + zombie.session,
store: ipec_logs_store,
bbar: ipec_logs_bbar,
border: false,
loadMask: {msg:'Loading History...'},
viewConfig: {
forceFit:true
},
view: new Ext.grid.GridView({
forceFit: true,
emptyText: "No History",
enableRowBody:true
}),
columns: [
{header: 'Id', width: 10, sortable: true, dataIndex: 'id', hidden:true},
{header: 'Vector Method', width: 30, sortable: true, dataIndex: 'vector_method', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
{header: 'Vector Name', width: 40, sortable: true, dataIndex: 'vector_name', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
{header: 'Vector PoC', sortable: true, dataIndex: 'vector_poc', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}
],
listeners: {
afterrender: function(datagrid) {
datagrid.store.reload({params:{start:0,limit:req_pagesize, sort: "date", dir:"DESC"}});
}
}
});
var ipec_logs_panel = new Ext.Panel({
id: 'ipec-logs-panel-zombie-'+zombie.session,
title: 'Logs',
items:[ipec_logs_grid],
layout: 'fit',
listeners: {
activate: function(ipec_logs_panel) {
ipec_logs_panel.items.items[0].store.reload();
}
}
});
function genScanSettingsPanel(zombie, bar, value) {
panel = Ext.getCmp('ipec-config-zombie-'+zombie.session);
panel.setTitle('Prompt');
panel.add(ipec_terminal_panel);
// panel.add(form);
}
ZombieTab_IpecTab.superclass.constructor.call(this, {
id: 'ipec-log-tab-'+zombie.session,
title: 'Ipec',
activeTab: 0,
viewConfig: {
forceFit: true,
type: 'fit',
autoScroll:true
},
items: [ipec_config_panel],
bbar: commands_statusbar,
listeners: {
afterrender : function(){
genScanSettingsPanel(zombie, commands_statusbar);
},
autoScroll:true
}
});
};
Ext.extend(ZombieTab_IpecTab, Ext.TabPanel, {} );

View File

@@ -0,0 +1,415 @@
/**
* @Author : venkatakrishnan ganesh
* @file : wterm.jquery.js
* @url : http://wterminal.appspot.com
* @desc :
*
* Allows Emulation of Terminal on the browser.
* Completely Extendible.
* Command History.
* Commandline Editing.
*
* Modified by antisnatchor
* */
( function( $ ) {
var VERSION = '0.0.4';
/**
*
* @function : get_defaults
* @returns : Object
* @desc : Returns Global Defaults
*
* */
var get_defaults = function() {
return {
// PS1 : The Primary Prompt
PS1 : 'BeEF-bind-$',
// TERMINAL_CLASS
// Will be applied to the primary terminal container
TERMINAL_CLASS : 'wterm_terminal',
// PROMPT_CLASS
// Will Applied to prompt container
PROMPT_CLASS : 'wterm_prompt',
// THEME_CLASS_PREFIX
// All Theme Classes will be prefixed by this string
THEME_CLASS_PREFIX : 'wterm_theme',
// DEFAULT_THEME
// The theme that is applied by default
DEFAULT_THEME : '_green_on_black',
// HIGHLIGHT_CLASS
// The Class that is applied to highlighted text
HIGHLIGHT_CLASS : 'wterm_highlight',
// KEYWORD_CLASS
// The Class that is applied to keywords
KEYWORD_CLASS : 'wterm_keyword',
// CONTENT_CLASS
// The Class that is applied to content section
KEYWORD_CLASS : 'wterm_content',
// WIDTH | HIGHT
// Explicitly set width and height of the terminal
// container. This may also be done in TERMINAL_CLASS
WIDTH : '90%',
HEIGHT : '90%',
// WELCOME_MESSAGE
// Message to be shown when the terminal is first
// published
WELCOME_MESSAGE : 'Welcome to Wterm version-' + VERSION ,
// NOT_FOUND
// Message to be published if the command is not found
// Note: "CMD" will be replaced with the actual command
NOT_FOUND : '<div> CMD: Command Not Found </div>',
// AUTOCOMPLETE
// Is Autocomplete feature Enabled
// Please see the manual on how AUTOCOMPLETE is implemented
AUTOCOMPLETE : true,
// HISTORY
// Is Command History Enabled
HISTORY : true,
// HISTORY
// No of entries to be stored in HISTORY
HISTORY_ENTRIES : 100,
// AJAX_METHOD
// The HTTP Method that must be used for Ajax Requests
AJAX_METHOD : 'GET',
// AJAX_PARAMETER
// The GET/POST parameter that should be used to make requests
AJAX_PARAM : 'tokens',
// ERROR_PREFIX
// Prefix For Error Messages
ERROR_PREFIX : 'An Error Occured: '
};
};
/**
* @property : dispatch
* @accessor : $.register_command ( See Below )
* @private
* @desc :
*
* dispatch table stores command name and action
* to be taken when user enters a command. See
* Manual for more details on how to implement
* your own commands
*
**/
var dispatch = {
};
/**
*
* @method : wterm
* @public
* @desc : Sets up the terminal on the JQ object that
* represents a ( or a group ) of HTML NODE (s)
*
**/
$.fn.wterm = function( options ) {
// Merge defaults with options
var settings = get_defaults();
$.extend( true, settings, options );
// JQ Plugin surprised??
return this.each( function() {
var element = $( this );
var history = [ ];
var hcurrent = null;
// Set up some markup in the element
// required for terminal emulation
element.addClass( settings.TERMINAL_CLASS ).addClass( settings.THEME_CLASS_PREFIX + settings.DEFAULT_THEME );
if( settings.WIDTH && settings.HEIGHT ) element.css( { width: settings.WIDTH, height: settings.HEIGHT } )
element.html( '' ).append( '<div>' + settings.WELCOME_MESSAGE + '</div>' );
element.append( '<div class="' + settings.CONTENT_CLASS + '"></div>' );
element.append( '<div><span class="' + settings.PROMPT_CLASS + '">' + settings.PS1 + '&nbsp;</span>' +
'<form> <input type="text" ></form></div>' );
// Representing prompt, form, input and content section
// in the terminal
var _prompt = element.find( 'div:last span:last' );
var input_form = element.find( 'div:last form' );
var input = element.find( 'div:last form input' );
var content = element.find( '.' + settings.CONTENT_CLASS );
// Custom Dispatcher
var cdispatch = null;
// Temprary storage for autocomplete configuration
var ac_save = null;
// Temporary store for current prompt
var cprompt = null;
// Curson always needs to be on the prompt
input.focus();
element.click( function() { input.focus(); } );
/**
* @method : hide
* @private :
* @desc : Hides the prompt
**/
var hide = function() {
_prompt.hide();
};
/**
* @method : show
* @private :
* @desc : Shows the prompt
**/
var show = function() {
_prompt.show();
input.focus();
};
/**
* @method : update_content
* @private :
* @desc : Updates the content section
* @args : current_prompt, command, data
**/
var update_content = function( p, cmd, data ) {
content.append( '<div><span>' + p + ' ' + cmd + '</span><div>' + ( ( data ) ? data : '' ) + '</div></div>' );
};
/**
* @method : clear_content
* @private :
* @desc : Updates the content section
* @args : current_prompt, command, data
**/
var clear_content = function() {
content.html( '' );
};
// Add the command to the dispatch
dispatch.clear = clear_content;
/**
* @method : set_prompt
* @private :
* @desc : Set the current prompt
* @args : string
**/
set_prompt = function( p ) {
if( p && p.length ) element.find( '.' + settings.PROMPT_CLASS).html( p + '&nbsp;' );
};
/**
*
* @method : Anonymous
* @private :
* @event_handler
*
**/
input_form.submit( function( e ) {
e.preventDefault();
e.stopPropagation();
var value = input.attr( 'value' );
if( settings.HISTORY ) {
if( history.length > settings.HISTORY_ENTRIES ) history.shift();
history.push( value );
}
// Reset The Input
input.attr( 'value', '' );
var tokens = value.split( /\s+/ );
var key = tokens[0];
hide();
var get_current_prompt = function() {
return ( cprompt ) ? cprompt : settings.PS1;
}
var _dispatch = function( key, tokens ) {
if( typeof key === 'function' ) {
data = key( tokens );
if( data ) { update_content( get_current_prompt(), value, data ) }
} else if( typeof key === 'string' ) {
var to_send = { };
to_send[ settings.AJAX_PARAM ] = tokens.join( ' ' );
var on_complete = function( data, text_status ) {
update_content( get_current_prompt(), value, data )
};
$[ settings.AJAX_METHOD.toLowerCase() ]( key, to_send, on_complete );
}
};
if( key == '' ) {
update_content( get_current_prompt() , '' )
} else if( cdispatch && key == 'exit' ) {
// Recover old configuration and Dispatch exit hook
settings.AUTOCOMPLETE = ( ac_save ) ? ac_save : false ;
// Todo: test what happens when exit hook is not defined
if( cdispatch.EXIT_HOOK ) {
_dispatch( cdispatch.EXIT_HOOK, tokens );
} else {
_dispatch( function() { return '<b></b>' }, tokens );
}
// Clear temporary values
cdispatch = null;
cprompt = null;
// Reset the prompt
set_prompt( settings.PS1 );
} else if( cdispatch ) {
// Dispatch to the custom dispatcher
_dispatch( cdispatch.DISPATCH, tokens );
} else if( dispatch[ key ] ) {
if( typeof dispatch[ key ] === 'object' ) {
cdispatch = dispatch[ key ];
cprompt = cdispatch.PS1 || key;
set_prompt( cprompt );
ac_save = settings.AUTOCOMPLETE;
settings.AUTOCOMPLETE = false;
// Todo:See what happens if start hook is not defined
if( cdispatch.START_HOOK ) {
_dispatch( cdispatch.START_HOOK, tokens );
} else {
// A stupid Hack
_dispatch( function() { return '<b></b>' }, tokens );
}
} else {
_dispatch( dispatch[ key ], tokens );
}
} else {
update_content( settings.PS1, value, settings.NOT_FOUND.replace( 'CMD', tokens[0] ));
}
show();
} );
/**
*
* @method : Anonymous
* @private :
* @event_handler
*
**/
input.keydown( function( e ) {
var keycode = e.keyCode;
switch( keycode ) {
case 9:
e.preventDefault();
if( settings.AUTOCOMPLETE ) {
var commands = [ ];
var current_value = input.attr( 'value' );
// Command Completion
if( current_value.match( /^[^\s]{0,}$/ ) ) {
for( i in dispatch ) {
if( current_value == '' ) {
commands.push( i );
} else if( i.indexOf( current_value ) == 0 ) {
commands.push( i );
}
}
if( commands.length > 1 ) {
update_content( settings.PS1, current_value, commands.join( '<br>' ) );
} else if( commands.length == 1 ) {
input.attr( 'value', commands.pop() + ' ' );
}
}
}
break;
// History Up
case 38:
e.preventDefault();
if( settings.HISTORY ) {
hcurrent = ( hcurrent === null )? history.length - 1 : ( hcurrent == 0 ) ? history.length - 1 : hcurrent - 1;
input.attr( 'value', history[ hcurrent ] );
}
break;
// History Down
case 40:
e.preventDefault();
if( settings.HISTORY ) {
if( hcurrent === null || hcurrent == (history.length - 1 ) ) break;
hcurrent++;
input.attr( 'value', history[ hcurrent ] );
}
break;
default:
break;
}
});
});
};
$.register_command = function( command, dispatch_method ) {
try {
if( typeof dispatch_method === 'function' || typeof dispatch_method === 'string' || typeof dispatch_method === 'object' ) {
dispatch[ command ] = dispatch_method;
} else {
throw 'Dispatch needs to be a method';
}
} catch ( e ) {
// Error Handling here
}
};
})( jQuery );