diff --git a/monkey/monkey_island/cc/ui/src/components/Main.js b/monkey/monkey_island/cc/ui/src/components/Main.js index 47116c5da..37eb97f3f 100644 --- a/monkey/monkey_island/cc/ui/src/components/Main.js +++ b/monkey/monkey_island/cc/ui/src/components/Main.js @@ -5,6 +5,7 @@ import {Container} from 'react-bootstrap'; import RunServerPage from 'components/pages/RunServerPage'; import ConfigurePage from 'components/pages/ConfigurePage'; import RunMonkeyPage from 'components/pages/RunMonkeyPage/RunMonkeyPage'; +import RunMonkeyPage2 from 'components/pages/RunMonkeyPage/RunMonkeyPage2'; import MapPage from 'components/pages/MapPage'; import TelemetryPage from 'components/pages/TelemetryPage'; import StartOverPage from 'components/pages/StartOverPage'; @@ -29,7 +30,7 @@ const reportZeroTrustRoute = '/report/zeroTrust'; class AppComponent extends AuthComponent { updateStatus = () => { - if (this.state.isLoggedIn === false){ + if (this.state.isLoggedIn === false) { return } this.auth.loggedIn() @@ -148,6 +149,10 @@ class AppComponent extends AuthComponent { )} + {this.renderRoute('/run-monkey2', + )} {this.renderRoute('/infection/map', + {props.commands.map(command => { + return ( + + {command.name} + ); + })} + ); + } + + function getCommandByName(name, commands) { + commands.forEach((command) => { + + }) + } + + return ( + <> + {renderNav()} + +
+ + + + {props.commands[0].command} +
+
+ + ) +} + +commandDisplay.propTypes = { + commands: PropTypes.arrayOf(PropTypes.exact({ + name: PropTypes.string, + command: PropTypes.string + })) +} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js index 89275067a..9680cfbad 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js @@ -1,42 +1,57 @@ -import React, {useEffect} from 'react'; -import NextSelectionButton from '../../ui-components/inline-selection/NextSelectionButton'; +import React, {useEffect, useState} from 'react'; import InlineSelection from '../../ui-components/inline-selection/InlineSelection'; -import CommandSection from '../../ui-components/inline-selection/CommandSection'; import ManualRunOptions from './ManualRunOptions'; -import InterfaceSelection from './InterfaceSelection'; +import DropdownSelect from '../../ui-components/DropdownSelect'; +import {OS_TYPES} from './OsTypes'; +import GenerateLocalWindowsCmd from './commands/local_windows_cmd'; +import GenerateLocalWindowsPowershell from './commands/local_windows_powershell'; +import GenerateLocalLinuxWget from './commands/local_linux_wget'; +import GenerateLocalLinuxCurl from './commands/local_linux_curl'; +import CommandDisplay from './CommandDisplay'; + const LocalManualRunOptions = (props) => { return InlineSelection(getContents, props, ManualRunOptions) } -const win64commands = [{name: "CMD", command: "monkey.exe m0nk3y -s 192.168.56.1"}] - const getContents = (props) => { + + const osTypes = { + [OS_TYPES.WINDOWS_64]: 'Windows 64bit', + [OS_TYPES.WINDOWS_32]: 'Windows 32bit', + [OS_TYPES.LINUX_64]: 'Linux 64bit', + [OS_TYPES.LINUX_32]: 'Linux 32bit' + } + + const [osType, setOsType] = useState(OS_TYPES.WINDOWS_64); + const [selectedIp, setSelectedIp] = useState(props.ips[0]); + const [commands, setCommands] = useState(generateCommands()); + + useEffect(() => { + setCommands(generateCommands()); + }, [osType, selectedIp]) + + function setIp(index) { + setSelectedIp(props.ips[index]); + } + + function generateCommands() { + if(osType === OS_TYPES.WINDOWS_64 || osType === OS_TYPES.WINDOWS_32) { + return [{name: 'CMD', command: GenerateLocalWindowsCmd(selectedIp, osType)}, + {name: 'Powershell', command: GenerateLocalWindowsPowershell(selectedIp, osType)}] + } else { + return [{name: 'CURL', command: GenerateLocalLinuxCurl(selectedIp, osType)}, + {name: 'WGET', command: GenerateLocalLinuxWget(selectedIp, osType)}] + } + } + return ( <> - { - props.setComponent(InterfaceSelection('Windows64')) - }}/> - { - }}/> - { - }}/> - { - }}/> + + + ) } -const setCommandAsContent = (props) => { - let commandComponent = () => InlineSelection(CommandSection, - { - commands: win64commands, - setComponent: props.setComponent - }, - LocalManualRunOptions - ); - props.setComponent(commandComponent, props); -} - export default LocalManualRunOptions; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js index 0b84084ab..6874fc2c8 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js @@ -2,6 +2,7 @@ import React, {useEffect, useState} from 'react'; import NextSelectionButton from '../../ui-components/inline-selection/NextSelectionButton'; import LocalManualRunOptions from './LocalManualRunOptions'; import AuthComponent from '../../AuthComponent'; +import BackButton from '../../ui-components/inline-selection/BackButton'; function ManualRunOptions(props) { @@ -16,7 +17,7 @@ function ManualRunOptions(props) { authComponent.authFetch('/api') .then(res => res.json()) .then(res => { - setIps([res['ip_addresses']]); + setIps([res['ip_addresses']][0]); setInitialized(true); }); } @@ -48,6 +49,7 @@ function ManualRunOptions(props) { }}/> { }}/> + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/OsTypes.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/OsTypes.js new file mode 100644 index 000000000..b24c9b302 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/OsTypes.js @@ -0,0 +1,6 @@ +export const OS_TYPES = { + WINDOWS_32: 'win32', + WINDOWS_64: 'win64', + LINUX_32: 'linux32', + LINUX_64: 'linux64' +} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js index 19650fc19..1a01ac913 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js @@ -1,11 +1,9 @@ import React from 'react'; import {css} from '@emotion/core'; import {Button, Col, Card, Nav, Collapse, Row} from 'react-bootstrap'; -import CopyToClipboard from 'react-copy-to-clipboard'; import GridLoader from 'react-spinners/GridLoader'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; -import {faClipboard} from '@fortawesome/free-solid-svg-icons/faClipboard'; import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'; import {faSync} from '@fortawesome/free-solid-svg-icons/faSync'; import {faInfoCircle} from '@fortawesome/free-solid-svg-icons/faInfoCircle'; @@ -17,6 +15,7 @@ import AwsRunTable from '../../run-monkey/AwsRunTable'; import MissingBinariesModal from '../../ui-components/MissingBinariesModal'; import ManualRunOptions from './ManualRunOptions'; +import Emoji from '../../ui-components/Emoji'; const loading_css_override = css` display: block; @@ -29,12 +28,9 @@ class RunMonkeyPageComponent extends AuthComponent { constructor(props) { super(props); this.state = { - ips: [], runningOnIslandState: 'not_running', runningOnClientState: 'not_running', awsClicked: false, - selectedIp: '0.0.0.0', - selectedOs: 'windows-32', showManual: false, showAws: false, isOnAws: false, @@ -52,13 +48,6 @@ class RunMonkeyPageComponent extends AuthComponent { } componentDidMount() { - this.authFetch('/api') - .then(res => res.json()) - .then(res => this.setState({ - ips: res['ip_addresses'], - selectedIp: res['ip_addresses'][0] - })); - this.authFetch('/api/local-monkey') .then(res => res.json()) .then(res => { @@ -113,17 +102,7 @@ class RunMonkeyPageComponent extends AuthComponent { }); } - static generateLinuxCmd(ip, is32Bit) { - let bitText = is32Bit ? '32' : '64'; - return `wget --no-check-certificate https://${ip}:5000/api/monkey/download/monkey-linux-${bitText}; chmod +x monkey-linux-${bitText}; ./monkey-linux-${bitText} m0nk3y -s ${ip}:5000` - } - - static generateWindowsCmd(ip, is32Bit) { - let bitText = is32Bit ? '32' : '64'; - return `powershell [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; (New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/monkey-windows-${bitText}.exe','.\\monkey.exe'); ;Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`; - } - - runLocalMonkey = () => { + runIslandMonkey = () => { this.authFetch('/api/local-monkey', { method: 'POST', @@ -154,41 +133,6 @@ class RunMonkeyPageComponent extends AuthComponent { }); }; - generateCmdDiv() { - let isLinux = (this.state.selectedOs.split('-')[0] === 'linux'); - let is32Bit = (this.state.selectedOs.split('-')[1] === '32'); - let cmdText = ''; - if (isLinux) { - cmdText = RunMonkeyPageComponent.generateLinuxCmd(this.state.selectedIp, is32Bit); - } else { - cmdText = RunMonkeyPageComponent.generateWindowsCmd(this.state.selectedIp, is32Bit); - } - return ( - -
- - - - {cmdText} -
-
- ) - } - - setSelectedOs = (key) => { - this.setState({ - selectedOs: key - }); - }; - - setSelectedIp = (key) => { - this.setState({ - selectedIp: key - }); - }; - static renderIconByState(state) { if (state === 'running') { return () @@ -274,14 +218,6 @@ class RunMonkeyPageComponent extends AuthComponent { rel="noopener noreferrer" target="_blank">Read the documentation!

- { - this.state.ips.length > 1 ? - - :
- } { return ( - -

1. Run Monkey

-

- Go ahead and run the monkey! - (Or configure the monkey to fine tune its behavior) -

+ <>

- OR

-

- -
-

- Choose the operating system where you want to run the monkey: -

- - - - - +

+ Go ahead and monitor the ongoing infection in the Infection Map view. +

+ + ) + } - {this.state.ips.length > 1 ? -
- - -

- Choose the interface to communicate with: -

- -
- - - - - -
- :
- } -

- Copy the following command to your machine and run it with Administrator or root privileges. -

- {this.generateCmdDiv()} -
- + disableManualOptions = () => { + this.setState({showManual: false}) + } + + render() { + return ( + +

1. Run Monkey

+

+ Go ahead and run the monkey! + (Or configure the monkey to fine tune its behavior) +

+ {this.state.showManual ? + : + this.renderIslandVsManual()} { this.state.isLoadingAws ?
@@ -459,10 +351,6 @@ class RunMonkeyPageComponent extends AuthComponent { } - -

- Go ahead and monitor the ongoing infection in the Infection Map view. -

); } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage2.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage2.js new file mode 100644 index 000000000..8edd0e44e --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage2.js @@ -0,0 +1,472 @@ +import React from 'react'; +import {css} from '@emotion/core'; +import {Button, Col, Card, Nav, Collapse, Row} from 'react-bootstrap'; +import CopyToClipboard from 'react-copy-to-clipboard'; +import GridLoader from 'react-spinners/GridLoader'; + +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faClipboard} from '@fortawesome/free-solid-svg-icons/faClipboard'; +import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'; +import {faSync} from '@fortawesome/free-solid-svg-icons/faSync'; +import {faInfoCircle} from '@fortawesome/free-solid-svg-icons/faInfoCircle'; +import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons/faExclamationTriangle'; + +import {Link} from 'react-router-dom'; +import AuthComponent from '../../AuthComponent'; +import AwsRunTable from '../../run-monkey/AwsRunTable'; + +import MissingBinariesModal from '../../ui-components/MissingBinariesModal'; +import ManualRunOptions from './ManualRunOptions'; +import Emoji from '../../ui-components/Emoji'; + +const loading_css_override = css` + display: block; + margin-right: auto; + margin-left: auto; +`; + +class RunMonkeyPageComponent2 extends AuthComponent { + + constructor(props) { + super(props); + this.state = { + ips: [], + runningOnIslandState: 'not_running', + runningOnClientState: 'not_running', + awsClicked: false, + selectedIp: '0.0.0.0', + selectedOs: 'windows-32', + showManual: false, + showAws: false, + isOnAws: false, + awsUpdateClicked: false, + awsUpdateFailed: false, + awsMachines: [], + isLoadingAws: true, + isErrorWhileCollectingAwsMachines: false, + awsMachineCollectionErrorMsg: '', + showModal: false, + errorDetails: '' + }; + + this.closeModal = this.closeModal.bind(this); + } + + componentDidMount() { + this.authFetch('/api') + .then(res => res.json()) + .then(res => this.setState({ + ips: res['ip_addresses'], + selectedIp: res['ip_addresses'][0] + })); + + this.authFetch('/api/local-monkey') + .then(res => res.json()) + .then(res => { + if (res['is_running']) { + this.setState({runningOnIslandState: 'running'}); + } else { + this.setState({runningOnIslandState: 'not_running'}); + } + }); + + this.fetchAwsInfo(); + this.fetchConfig(); + + this.authFetch('/api/client-monkey') + .then(res => res.json()) + .then(res => { + if (res['is_running']) { + this.setState({runningOnClientState: 'running'}); + } else { + this.setState({runningOnClientState: 'not_running'}); + } + }); + + this.props.onStatusChange(); + } + + fetchAwsInfo() { + return this.authFetch('/api/remote-monkey?action=list_aws') + .then(res => res.json()) + .then(res => { + let is_aws = res['is_aws']; + if (is_aws) { + // On AWS! + // Checks if there was an error while collecting the aws machines. + let is_error_while_collecting_aws_machines = (res['error'] != null); + if (is_error_while_collecting_aws_machines) { + // There was an error. Finish loading, and display error message. + this.setState({ + isOnAws: true, + isErrorWhileCollectingAwsMachines: true, + awsMachineCollectionErrorMsg: res['error'], + isLoadingAws: false + }); + } else { + // No error! Finish loading and display machines for user + this.setState({isOnAws: true, awsMachines: res['instances'], isLoadingAws: false}); + } + } else { + // Not on AWS. Finish loading and don't display the AWS div. + this.setState({isOnAws: false, isLoadingAws: false}); + } + }); + } + + static generateLinuxCmd(ip, is32Bit) { + let bitText = is32Bit ? '32' : '64'; + return `wget --no-check-certificate https://${ip}:5000/api/monkey/download/monkey-linux-${bitText}; chmod +x monkey-linux-${bitText}; ./monkey-linux-${bitText} m0nk3y -s ${ip}:5000` + } + + static generateWindowsCmd(ip, is32Bit) { + let bitText = is32Bit ? '32' : '64'; + return `powershell [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; (New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/monkey-windows-${bitText}.exe','.\\monkey.exe'); ;Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`; + } + + runLocalMonkey = () => { + this.authFetch('/api/local-monkey', + { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({action: 'run'}) + }) + .then(res => res.json()) + .then(res => { + if (res['is_running']) { + this.setState({ + runningOnIslandState: 'installing' + }); + } else { + /* If Monkey binaries are missing, change the state accordingly */ + if (res['error_text'].startsWith('Copy file failed')) { + this.setState({ + showModal: true, + errorDetails: res['error_text'] + } + ); + } + this.setState({ + runningOnIslandState: 'not_running' + }); + } + + this.props.onStatusChange(); + }); + }; + + generateCmdDiv() { + let isLinux = (this.state.selectedOs.split('-')[0] === 'linux'); + let is32Bit = (this.state.selectedOs.split('-')[1] === '32'); + let cmdText = ''; + if (isLinux) { + cmdText = RunMonkeyPageComponent2.generateLinuxCmd(this.state.selectedIp, is32Bit); + } else { + cmdText = RunMonkeyPageComponent2.generateWindowsCmd(this.state.selectedIp, is32Bit); + } + return ( + +
+ + + + {cmdText} +
+
+ ) + } + + setSelectedOs = (key) => { + this.setState({ + selectedOs: key + }); + }; + + setSelectedIp = (key) => { + this.setState({ + selectedIp: key + }); + }; + + static renderIconByState(state) { + if (state === 'running') { + return () + } else if (state === 'installing') { + return () + } else { + return ''; + } + } + + toggleManual = () => { + this.setState({ + showManual: !this.state.showManual + }); + }; + + toggleAws = () => { + this.setState({ + showAws: !this.state.showAws + }); + }; + + runOnAws = () => { + this.setState({ + awsClicked: true + }); + + let instances = this.awsTable.state.selection.map(x => this.instanceIdToInstance(x)); + + this.authFetch('/api/remote-monkey', + { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({type: 'aws', instances: instances, island_ip: this.state.selectedIp}) + }).then(res => res.json()) + .then(res => { + let result = res['result']; + + // update existing state, not run-over + let prevRes = this.awsTable.state.result; + for (let key in result) { + if (result.hasOwnProperty(key)) { + prevRes[key] = result[key]; + } + } + this.awsTable.setState({ + result: prevRes, + selection: [], + selectAll: false + }); + + this.setState({ + awsClicked: false + }); + }); + }; + + fetchConfig() { + return this.authFetch('/api/configuration/island') + .then(res => res.json()) + .then(res => { + return res.configuration; + }) + } + + instanceIdToInstance = (instance_id) => { + let instance = this.state.awsMachines.find( + function (inst) { + return inst['instance_id'] === instance_id; + }); + return {'instance_id': instance_id, 'os': instance['os']} + + }; + + renderAwsMachinesDiv() { + return ( +
+
+

+ + Not sure what this is? Not seeing your AWS EC2 instances? Read the documentation! +

+
+ { + this.state.ips.length > 1 ? + + :
+ } + + (this.awsTable = r)} + /> +
+ +
+
+ ) + } + + closeModal = () => { + this.setState({ + showModal: false + }) + }; + + render() { + return ( + +

1. Run Monkey

+

+ Go ahead and run the monkey! + (Or configure the monkey to fine tune its behavior) +

+

+ + +

+

+ OR +

+ +

+ +

+ +
+

+ Choose the operating system where you want to run the monkey: +

+ + + + + + + {this.state.ips.length > 1 ? +
+ + +

+ Choose the interface to communicate with: +

+ +
+ + + + + +
+ :
+ } +

+ Copy the following command to your machine and run it with Administrator or root privileges. +

+ {this.generateCmdDiv()} +
+ + { + this.state.isLoadingAws ? +
+
+ +
+
+ : null + } + { + this.state.isOnAws ? +

+ OR +

+ : + null + } + { + this.state.isOnAws ? +

+ +

+ : + null + } + + { + this.state.isErrorWhileCollectingAwsMachines ? +
+

+ + Error while collecting AWS machine data. Error + message: {this.state.awsMachineCollectionErrorMsg}
+ Are you sure you've set the correct role on your Island AWS machine?
+ Not sure what this is? Read + the documentation! +

+
+ : + this.renderAwsMachinesDiv() + } + +
+ +

+ Go ahead and monitor the ongoing infection in the Infection Map view. +

+ + ); + } +} + +export default RunMonkeyPageComponent2; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandTypes.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js similarity index 100% rename from monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandTypes.js rename to monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js new file mode 100644 index 000000000..fb0171bfd --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js @@ -0,0 +1,13 @@ +import {OS_TYPES} from '../OsTypes'; + + +export default function generateLocalLinuxCurl(ip, osType) { + let bitText = osType === OS_TYPES.LINUX_32 ? '32' : '64'; + return `curl https://${ip}:5000/api/monkey/download/monkey-linux-${bitText} -k + -o monkey-linux-${bitText}; + chmod +x monkey-linux-${bitText}; + ./monkey-linux-${bitText} m0nk3y -s ${ip}:5000\`;`; + } + + + diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js new file mode 100644 index 000000000..766822ee1 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js @@ -0,0 +1,10 @@ +import {OS_TYPES} from '../OsTypes'; + + +export default function generateLocalLinuxWget(ip, osType) { + let bitText = osType === OS_TYPES.LINUX_32 ? '32' : '64'; + return `wget --no-check-certificate https://${ip}:5000/api/monkey/download/ + monkey-linux-${bitText}; + chmod +x monkey-linux-${bitText}; + ./monkey-linux-${bitText} m0nk3y -s ${ip}:5000`; + } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_cmd.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_cmd.js new file mode 100644 index 000000000..74afbe512 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_cmd.js @@ -0,0 +1,10 @@ +import {OS_TYPES} from '../OsTypes'; + + +export default function generateLocalWindowsCmd(ip, osType) { + let bitText = osType === OS_TYPES.WINDOWS_32 ? '32' : '64'; + return `powershell [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; + (New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/ + monkey-windows-${bitText}.exe','.\\monkey.exe'); + ;Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`; +} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js new file mode 100644 index 000000000..1ebd1f4ac --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js @@ -0,0 +1,10 @@ +import {OS_TYPES} from '../OsTypes'; + + +export default function generateLocalWindowsPowershell(ip, osType) { + let bitText = osType === OS_TYPES.WINDOWS_32 ? '32' : '64'; + return `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; + (New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/ + monkey-windows-${bitText}.exe','.\\monkey.exe'); + ;Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`; +} diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js new file mode 100644 index 000000000..d57f14fe4 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js @@ -0,0 +1,62 @@ +import React, {useState} from 'react'; +import {Dropdown} from 'react-bootstrap'; +import PropTypes from 'prop-types'; + +export default function DropdownSelect(props) { + const [selectedOption, setSelectedOption] = useState(props.defaultKey); + + function generateDropdownItems(data) { + if (Array.isArray(data)) { + return generateDropdownItemsFromArray(data); + } else if (typeof data === 'object') { + return generateDropdownItemsFromObject(data); + } else { + throw "Component can only generate dropdown intems from lists and objects." + } + } + + function generateDropdownItemsFromArray(data) { + const dropdownItems = []; + for (let i = 0; i < data.length; i++) { + dropdownItems.push(generateDropdownItem(i, data[i])); + } + return dropdownItems; + } + + function generateDropdownItemsFromObject(data) { + const dropdownItems = []; + for (let [key, value] of Object.entries(data)) { + dropdownItems.push(generateDropdownItem(key, value)); + } + return dropdownItems; + } + + function generateDropdownItem(key, value) { + return ( + { setSelectedOption(key); + props.onClick(key)}} + active={(key === selectedOption)}> + {value} + ); + } + + return ( + <> + + + {props.options[selectedOption]} + + + + {generateDropdownItems(props.options)} + + + + ) +} + +DropdownSelect.propTypes = { + options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), + defaultKey: PropTypes.oneOfType([PropTypes.string,PropTypes.number]), + onClick: PropTypes.func +} diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/Emoji.js b/monkey/monkey_island/cc/ui/src/components/ui-components/Emoji.js new file mode 100644 index 000000000..1773efbd2 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/Emoji.js @@ -0,0 +1,12 @@ +import React from 'react'; +const Emoji = props => ( + + {props.symbol} + +); +export default Emoji; diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js index 97bb82d99..2a6dbc897 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js @@ -18,7 +18,7 @@ function setPreviousComponent(props, previousComponent) { if(previousComponent === ManualRunOptions){ return props.setComponent() } else { - return props.setComponent(previousComponent) + return props.setComponent(previousComponent, props) } }