Files
beef/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabRTC.js
2025-12-26 19:18:05 +10:00

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, {});