357 lines
13 KiB
JavaScript
357 lines
13 KiB
JavaScript
//
|
|
// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
|
// Browser Exploitation Framework (BeEF) - https://beefproject.com
|
|
// See the file 'doc/COPYING' for copying permission
|
|
//
|
|
|
|
/*
|
|
* The RTC tab panel for the selected zombie browser.
|
|
* Loaded in /ui/panel/index.html
|
|
*/
|
|
ZombieTab_Rtc = function(zombie) {
|
|
var zombie_id = beefwui.get_hb_id(zombie.session);
|
|
|
|
// The status bar.
|
|
var commands_statusbar = new Beef_StatusBar('webrtc-bbar-zombie-'+zombie.session);
|
|
// RESTful API token
|
|
var token = beefwui.get_rest_token();
|
|
|
|
/*
|
|
* The panel that displays all identified network services grouped by host
|
|
********************************************/
|
|
var rtc_events_panel_store = new Ext.ux.data.PagingJsonStore({
|
|
storeId: 'rtc-events-store-zombie-'+zombie.session,
|
|
proxy: new Ext.data.HttpProxy({
|
|
url: '/api/webrtc/events/'+zombie_id+'?token='+token,
|
|
method: 'GET'
|
|
}),
|
|
remoteSort: false,
|
|
autoDestroy: true,
|
|
autoLoad: false,
|
|
root: 'events',
|
|
fields: ['id', 'hb_id', 'target_id', 'status', 'created_at', 'updated_at'],
|
|
sortInfo: {field: 'id', direction: 'ASC'}
|
|
});
|
|
|
|
var req_pagesize = 50;
|
|
|
|
var rtc_events_panel_bbar = new Ext.PagingToolbar({
|
|
pageSize: req_pagesize,
|
|
store: rtc_events_panel_store,
|
|
displayInfo: true,
|
|
displayMsg: 'Displaying RTC events {0} - {1} of {2}',
|
|
emptyMsg: 'No events to display'
|
|
});
|
|
|
|
var rtc_events_panel_grid = new Ext.grid.GridPanel({
|
|
id: 'rtc-events-grid-zombie-'+zombie.session,
|
|
store: rtc_events_panel_store,
|
|
bbar: rtc_events_panel_bbar,
|
|
border: false,
|
|
loadMask: {msg:'Loading events...'},
|
|
|
|
viewConfig: {
|
|
forceFit: true
|
|
},
|
|
|
|
view: new Ext.grid.GridView({
|
|
forceFit: true,
|
|
emptyText: "No events",
|
|
enableRowBody:true
|
|
}),
|
|
|
|
columns: [
|
|
{header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},
|
|
{header: 'From', width: 10, sortable: true, dataIndex: 'hb_id', hidden:true},
|
|
{header: 'Peer', width: 10, sortable: true, dataIndex: 'target_id', renderer: function(value){
|
|
if (value === zombie_id) {
|
|
return $jEncoder.encoder.encodeForHTML(value) + " (selected)";
|
|
} else {
|
|
// return $jEncoder.encoder.encodeForHTML(value) + " <img src='/ui/media/images/icons/chrome.png' style='padding-top:3px;' width='13px' height='13px'/> (" + beefwui.get_info_from_id(value) + ")";
|
|
return $jEncoder.encoder.encodeForHTML(value) + " (" + beefwui.get_info_from_id(value)['ip'] + ")";
|
|
}
|
|
}},
|
|
{header: 'Status', width: 20, sortable: true, dataIndex: 'status', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
|
{header: 'Created At', width: 10, sortable: true, dataIndex: 'created_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
|
{header: 'Updated At', width: 10, sortable: true, dataIndex: 'updated_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}
|
|
],
|
|
|
|
listeners: {
|
|
contextmenu: function(e, element, options) {
|
|
e.preventDefault();
|
|
},
|
|
containercontextmenu: function(view, e) {
|
|
e.preventDefault();
|
|
},
|
|
rowcontextmenu: function(grid, rowIndex, e) {
|
|
e.preventDefault();
|
|
grid.getSelectionModel().selectRow(rowIndex);
|
|
if (!!grid.rowCtxMenu) {
|
|
grid.rowCtxMenu.destroy();
|
|
}
|
|
var record = grid.selModel.getSelected();
|
|
if (record.json.status==="Connected") {
|
|
grid.rowCtxMenu = new Ext.menu.Menu({
|
|
items: [
|
|
{
|
|
text: "Command Peer to Stealth",
|
|
handler: function() {
|
|
if (zombie_id === record.json.hb_id) {
|
|
var from = record.json.hb_id;
|
|
var to = record.json.target_id;
|
|
} else {
|
|
var from = record.json.target_id;
|
|
var to = record.json.hb_id;
|
|
}
|
|
commands_statusbar.update_sending("Sending stealth command");
|
|
var url = "/api/webrtc/msg?token=" + beefwui.get_rest_token();
|
|
Ext.Ajax.request({
|
|
url: url,
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json; charset=UTF-8'},
|
|
jsonData: {
|
|
'from': from,
|
|
'to': to,
|
|
'message': "!gostealth"
|
|
},
|
|
success: function(data){
|
|
commands_statusbar.update_sent("Stealth command sent successfully");
|
|
},
|
|
error: function(){
|
|
commands_statusbar.update_fail("Error sending stealth command");
|
|
}
|
|
});
|
|
}
|
|
},{
|
|
text: "Execute Command Module via RTC",
|
|
handler: function() {
|
|
var url = "/api/webrtc/cmdexec?token=" + beefwui.get_rest_token();
|
|
var cmd_id = prompt("Enter command module ID:");
|
|
if (!cmd_id || cmd_id == "" || isNaN(cmd_id)) {
|
|
commands_statusbar.update_fail('Invalid command module ID');
|
|
return;
|
|
}
|
|
var cmd_opts = prompt("Parameters:");
|
|
if (cmd_opts == "") {
|
|
cmd_opts = "[]";
|
|
}
|
|
try {
|
|
cmd_opts = JSON.parse(cmd_opts);
|
|
} catch (e) {
|
|
commands_statusbar.update_fail("Invalid JSON")
|
|
return;
|
|
}
|
|
if (zombie_id === record.json.hb_id) {
|
|
var from = record.json.hb_id;
|
|
var to = record.json.target_id;
|
|
} else {
|
|
var from = record.json.target_id;
|
|
var to = record.json.hb_id;
|
|
}
|
|
commands_statusbar.update_sending("Sending command [id: " + cmd_id + "]");
|
|
Ext.Ajax.request({
|
|
url: url,
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json; charset=UTF-8'},
|
|
jsonData: {
|
|
'from': from,
|
|
'to': to,
|
|
'cmdid': cmd_id,
|
|
'options': cmd_opts
|
|
},
|
|
success: function(data){
|
|
commands_statusbar.update_sent("Command [id: " + cmd_id + "] sent successfully");
|
|
},
|
|
error: function(){
|
|
commands_statusbar.update_fail("Error executing module [id: " + cmd_id + "]");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
]
|
|
});
|
|
grid.rowCtxMenu.showAt(e.getXY());
|
|
} else if (record.json.status==="Stealthed!!") {
|
|
grid.rowCtxMenu = new Ext.menu.Menu({
|
|
items: [
|
|
{
|
|
text: "Command Peer to un-stealth",
|
|
handler: function() {
|
|
if (zombie_id === record.json.hb_id) {
|
|
commands_statusbar.update_sending("Sending un-stealth command");
|
|
var url = "/api/webrtc/msg?token=" + beefwui.get_rest_token();
|
|
Ext.Ajax.request({
|
|
url: url,
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json; charset=UTF-8'},
|
|
jsonData: {
|
|
'from': record.json.hb_id,
|
|
'to': record.json.target_id,
|
|
'message': "!endstealth"
|
|
},
|
|
success: function(data){
|
|
commands_statusbar.update_sent("Un-stealth command sent successfully");
|
|
},
|
|
error: function(){
|
|
commands_statusbar.update_fail("Error sending un-stealth command");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},{
|
|
text: "Execute Command Module via RTC",
|
|
handler: function() {
|
|
var url = "/api/webrtc/cmdexec?token=" + beefwui.get_rest_token();
|
|
var cmd_id = prompt("Enter command module ID:");
|
|
if (!cmd_id || cmd_id == "" || isNaN(cmd_id)) {
|
|
commands_statusbar.update_fail('Invalid command module ID');
|
|
return;
|
|
}
|
|
var cmd_opts = prompt("Parameters:");
|
|
if (cmd_opts == "") {
|
|
cmd_opts = "[]";
|
|
}
|
|
try {
|
|
cmd_opts = JSON.parse(cmd_opts);
|
|
} catch (e) {
|
|
commands_statusbar.update_fail("Invalid JSON")
|
|
return;
|
|
}
|
|
commands_statusbar.update_sending("Sending command [id: " + cmd_id + "]")
|
|
Ext.Ajax.request({
|
|
url: url,
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json; charset=UTF-8'},
|
|
jsonData: {
|
|
'from': record.json.hb_id,
|
|
'to': record.json.target_id,
|
|
'cmdid': cmd_id,
|
|
'options': cmd_opts
|
|
},
|
|
success: function(data){
|
|
commands_statusbar.update_sent("Command [id: " + cmd_id + "] sent successfully");
|
|
},
|
|
error: function(){
|
|
commands_statusbar.update_fail("Error executing module [id: " + cmd_id + "]");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
]
|
|
});
|
|
grid.rowCtxMenu.showAt(e.getXY());
|
|
}
|
|
},
|
|
afterrender: function(datagrid) {
|
|
datagrid.store.reload({params: {nonce: Ext.get("nonce").dom.value}});
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
var rtc_events_panel = new Ext.Panel({
|
|
id: 'rtc-events-host-panel-zombie-'+zombie.session,
|
|
title: 'Peers',
|
|
items:[rtc_events_panel_grid],
|
|
layout: 'fit',
|
|
listeners: {
|
|
activate: function(hosts_panel) {
|
|
rtc_events_panel.items.items[0].store.reload({ params: {nonce: Ext.get ("nonce").dom.value} });
|
|
}
|
|
}
|
|
});
|
|
|
|
/*
|
|
* The panel that displays all command modules executed via RTC
|
|
********************************************/
|
|
var rtc_moduleevents_panel_store = new Ext.ux.data.PagingJsonStore({
|
|
storeId: 'rtc-moduleevents-store-zombie-'+zombie.session,
|
|
proxy: new Ext.data.HttpProxy({
|
|
url: '/api/webrtc/cmdevents/'+zombie_id+'?token='+token,
|
|
method: 'GET'
|
|
}),
|
|
remoteSort: false,
|
|
autoDestroy: true,
|
|
autoLoad: false,
|
|
root: 'events',
|
|
fields: ['id', 'hb_id', 'target_id', 'status', 'created_at', 'updated_at', 'mod'],
|
|
sortInfo: {field: 'id', direction: 'ASC'}
|
|
});
|
|
|
|
var rtc_moduleevents_panel_bbar = new Ext.PagingToolbar({
|
|
pageSize: req_pagesize,
|
|
store: rtc_moduleevents_panel_store,
|
|
displayInfo: true,
|
|
displayMsg: 'Displaying RTC command events {0} - {1} of {2}',
|
|
emptyMsg: 'No events to display'
|
|
});
|
|
|
|
var rtc_moduleevents_panel_grid = new Ext.grid.GridPanel({
|
|
id: 'rtc-moduleevents-grid-zombie-'+zombie.session,
|
|
store: rtc_moduleevents_panel_store,
|
|
bbar: rtc_moduleevents_panel_bbar,
|
|
border: false,
|
|
loadMask: {msg:'Loading events...'},
|
|
|
|
viewConfig: {
|
|
forceFit: true
|
|
},
|
|
|
|
view: new Ext.grid.GridView({
|
|
forceFit: true,
|
|
emptyText: "No events",
|
|
enableRowBody:true
|
|
}),
|
|
|
|
columns: [
|
|
{header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},
|
|
{header: 'From', width: 10, sortable: true, dataIndex: 'hb_id', hidden:true},
|
|
{header: 'Peer', width: 10, sortable: true, dataIndex: 'target_id', renderer: function(value){
|
|
if (value === zombie_id) {
|
|
return $jEncoder.encoder.encodeForHTML(value) + " (selected)";
|
|
} else {
|
|
return $jEncoder.encoder.encodeForHTML(value) + " (" + beefwui.get_info_from_id(value)['ip'] + ")";
|
|
}
|
|
}},
|
|
{header: 'Module', width: 10, sortable: true, dataIndex: 'mod', renderer: function(value){
|
|
return $jEncoder.encoder.encodeForHTML(value);
|
|
}},
|
|
{header: 'Status', width: 20, sortable: true, dataIndex: 'status', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
|
{header: 'Created At', width: 10, sortable: true, dataIndex: 'created_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
|
{header: 'Updated At', width: 10, sortable: true, dataIndex: 'updated_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}
|
|
]
|
|
});
|
|
|
|
var rtc_moduleevents_panel = new Ext.Panel({
|
|
id: 'rtc-moduleevents-host-panel-zombie-'+zombie.session,
|
|
title: 'Command module results',
|
|
items:[rtc_moduleevents_panel_grid],
|
|
layout: 'fit',
|
|
listeners: {
|
|
activate: function(hosts_panel) {
|
|
rtc_moduleevents_panel.items.items[0].store.reload({ params: {nonce: Ext.get ("nonce").dom.value} });
|
|
}
|
|
}
|
|
});
|
|
/*
|
|
* The Network tab constructor
|
|
********************************************/
|
|
ZombieTab_Rtc.superclass.constructor.call(this, {
|
|
id: 'zombie-rtc-tab-zombie-'+zombie.session,
|
|
title: 'WebRTC',
|
|
activeTab: 0,
|
|
viewConfig: {
|
|
forceFit: true,
|
|
stripRows: true,
|
|
type: 'fit'
|
|
},
|
|
items: [rtc_events_panel,rtc_moduleevents_panel],
|
|
bbar: commands_statusbar,
|
|
listeners: {
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
Ext.extend(ZombieTab_Rtc, Ext.TabPanel, {});
|