Skip to content

Commit

Permalink
v3.2.18-rc7
Browse files Browse the repository at this point in the history
Added `import` and `export` features to c2 profile instances
  • Loading branch information
its-a-feature committed Feb 21, 2024
1 parent 21f799d commit 29b3c89
Show file tree
Hide file tree
Showing 29 changed files with 326 additions and 53 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.2.18-rc7] - 2024-02-21

### Changed

- Added support for exporting and importing c2 profile instances (green save icon next to a c2 profile then export/import)

## [3.2.18-rc6] - 2024-02-19

### Changed
Expand Down
6 changes: 6 additions & 0 deletions MythicReactUI/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.72]

### Changed

- Added an export and import button for saved c2 configuration instances

## [0.1.71] - 2024-02-19

### Changed
Expand Down
77 changes: 70 additions & 7 deletions MythicReactUI/src/components/pages/Callbacks/C2PathDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import ReactFlow, {
applyEdgeChanges, applyNodeChanges,
Handle, Position, useReactFlow, ReactFlowProvider, Panel,
MiniMap, Controls, ControlButton, useUpdateNodeInternals,
getConnectedEdges, updateEdge
getConnectedEdges
} from 'reactflow';
import 'reactflow/dist/style.css';
import { toPng, toSvg } from 'html-to-image';
Expand All @@ -36,6 +36,7 @@ import {ResponseDisplayTableDialogTable} from "./ResponseDisplayTableDialogTable
import SendIcon from '@mui/icons-material/Send';
import {getIconName} from "./ResponseDisplayTable";
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import RestartAltIcon from '@mui/icons-material/RestartAlt';

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
Expand Down Expand Up @@ -1644,6 +1645,7 @@ export const DrawBrowserScriptElementsFlowWithProvider = (props) => {
}
const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contextMenu, providedNodes, task}) => {
const [graphData, setGraphData] = React.useState({nodes: [], edges: [], groups: [], view_config});
const selectedNodes = React.useRef([]);
const [localContextMenu, setLocalContextMenu] = React.useState(contextMenu);
const [openTaskingButton, setOpenTaskingButton] = React.useState(false);
const [openDictionaryButton, setOpenDictionaryButton] = React.useState(false);
Expand All @@ -1657,7 +1659,7 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
setOpenTableButton(false);
setTaskingData({});
}
const [nodes, setNodes] = React.useState();
const [nodes, setNodes] = React.useState([]);
const [edgeFlow, setEdgeFlow] = React.useState([]);
const [openContextMenu, setOpenContextMenu] = React.useState(false);
const [contextMenuCoord, setContextMenuCord] = React.useState({});
Expand Down Expand Up @@ -1687,8 +1689,29 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
top: event.clientY,
left: event.clientX,
});
let tempContextMenu = [...contextMenu, {
title: selectedNodes.current.length > 0 ? "Hide Selected Nodes" : "Hide Node",
onClick: function(node) {
if(selectedNodes.current.length > 0){

const newEdges = edgeFlow.filter( e => {
return selectedNodes.current.findIndex((node) => node.id === e.source || node.id === e.destination) < 0;
})
const newNodes = nodes.filter( n => {
return selectedNodes.current.findIndex((node) => node.id === n.id) < 0;
})
setEdgeFlow(newEdges);
setNodes(newNodes);
} else {
const newEdges = edgeFlow.filter( e => e.source !== node.id && e.destination !== node.id)
const newNodes = nodes.filter( n => n.id !== node.id)
setEdgeFlow(newEdges);
setNodes(newNodes);
}
}
}];
if(node?.data?.buttons?.length > 0){
setLocalContextMenu([...contextMenu, ...node?.data?.buttons?.map(b => {
setLocalContextMenu([...tempContextMenu, ...node?.data?.buttons?.map(b => {
let title = b.name;
if( b?.startIcon){
title = <><FontAwesomeIcon icon={getIconName(b?.startIcon)} style={{color: b?.startIconColor || ""}}/> {title}</>;
Expand Down Expand Up @@ -1720,13 +1743,31 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
}
})]);
} else {
setLocalContextMenu([...contextMenu]);
setLocalContextMenu([...tempContextMenu]);
}

setOpenContextMenu(true);
}, [contextMenu]);
}, [contextMenu, edgeFlow, nodes, selectedNodes.current]);
const onEdgeContextMenu = useCallback( (event, edge) => {
event.preventDefault();
contextMenuNode.current = {...edge};
setContextMenuCord({
top: event.clientY,
left: event.clientX,
});
let tempContextMenu = [{
title: "Hide Edge",
onClick: function(edge) {
const newEdges = edgeFlow.filter( e => e.id !== edge.id)
setEdgeFlow(newEdges);
}
}];
setLocalContextMenu([...tempContextMenu]);
setOpenContextMenu(true);
}, [edgeFlow, nodes]);
const onPaneClick = useCallback( () => {
setOpenContextMenu(false);
selectedNodes.current = [];
const updatedEdges = graphData.edges.map( e => {
return {...e,
animated: e.oldAnimated ? e.oldAnimated : e.animated,
Expand All @@ -1739,7 +1780,17 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
//setGraphData({...graphData, edges: updatedEdges});
}, [setOpenContextMenu, graphData]);
const onNodeSelected = useCallback( (event, node) => {
const connectedEdges = getConnectedEdges([node], graphData.edges);
if(event.shiftKey){
let alreadySelected = selectedNodes.current.filter( s => s.id === node.id).length > 0;
if(alreadySelected){
selectedNodes.current = selectedNodes.current.filter(s => s.id !== node.id);
} else {
selectedNodes.current.push(node);
}
} else {
selectedNodes.current = [node];
}
const connectedEdges = getConnectedEdges(selectedNodes.current, graphData.edges);
const updatedEdges = graphData.edges.map( e => {
let included = connectedEdges.filter( ce => ce.id === e.id).length > 0;
if(included){
Expand All @@ -1766,7 +1817,7 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
})
//setGraphData({...graphData, edges: updatedEdges});
setEdgeFlow(updatedEdges);
}, [graphData]);
}, [graphData, selectedNodes.current]);
React.useEffect( () => {
let tempNodes = [];
let tempEdges = [];
Expand Down Expand Up @@ -1998,6 +2049,14 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
a.click();
});
};
const revertHidden = () => {
if(localViewConfig?.revert){
setLocalViewConfig({...localViewConfig, revert: true});
} else {
setLocalViewConfig({...localViewConfig, revert: false});
}

}
return (
<div style={{height: "100%", width: "100%", overflow: "hidden"}} ref={viewportRef}>
<ReactFlow
Expand All @@ -2014,6 +2073,7 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
onPaneClick={onPaneClick}
onNodeContextMenu={onNodeContextMenu}
onNodeClick={onNodeSelected}
onEdgeContextMenu={onEdgeContextMenu}
>
<Panel position={"top-left"} >{panel}</Panel>
<Controls showInteractive={false} style={{marginLeft: "40px"}} >
Expand All @@ -2023,6 +2083,9 @@ const DrawBrowserScriptElementsFlow = ({edges, panel, view_config, theme, contex
<ControlButton onClick={onDownloadImageClickSvg} title={"Download SVG"}>
<InsertPhotoIcon />
</ControlButton>
<ControlButton onClick={revertHidden} title={"Revert Hidden"}>
<RestartAltIcon />
</ControlButton>
</Controls>
<MiniMap pannable={true} zoomable={true} />
</ReactFlow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ export const ResponseDisplayGraph = ({graph, task, expand}) =>{
}, []);
const finalGraphNodes = graph?.nodes?.map( n => {
return {...n, img: getIcons(n?.img, n?.style || {}), overlay_img: getIcons(n?.overlay_img, n?.overlay_style)}
})
});
const contextMenu = React.useMemo(() => {return [
{
title: 'View All Data',
onClick: function(node) {
dictionaryData.current = node.data;
setViewAllDataDialogOpen(true);
}
}
},
]}, []);
return (
<div style={{height: expand ? "100%" : "400px", width: "100%", position: "relative"}}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ export function TaskParametersDialog(props) {

}
</Typography>
<TableContainer component={Paper} elevation={5} className="mythicElement" style={{backgroundColor: theme.tableHover, marginTop: "10px"}}>
<TableContainer>
<Table size="small" style={{"tableLayout": "fixed", "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,10 @@ export function TaskParametersDialogRow(props){
<TableBody>
{arrayValue.map( (a, i) => (
<TableRow key={'array' + props.name + i} >
<MythicStyledTableCell style={{width: "2rem", paddingLeft:"0"}}>
<IconButton onClick={(e) => {removeArrayValue(i)}} size="large"><DeleteIcon color="error" /> </IconButton>
<MythicStyledTableCell style={{width: "2rem"}}>
<DeleteIcon onClick={(e) => {removeArrayValue(i)}} color="error"
style={{cursor: "pointer"}}
/>
</MythicStyledTableCell>
<MythicStyledTableCell>
<MythicTextField required={props.required} fullWidth={true} placeholder={""} value={a} multiline={true} autoFocus={props.autoFocus || i > 0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function CreatePayloadC2ProfileParametersTable(props){
props.onChange(props.name, paramName, value, error);
}
return (
<TableContainer component={Paper} className="mythicElement">
<TableContainer >

<Table size="small" style={{"tableLayout": "fixed", "maxWidth": "calc(100vw)", "overflow": "auto"}}>
<TableHead>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,19 @@ export function CreatePayloadParameter({onChange, parameter_type, default_value,
let values = [...arrayValue];
if(value.includes("\n")){
let new_values = value.split("\n");
values = [...values, ...new_values.slice(1)];
values[index] = values[index] + new_values[0];
if(values[index] === ""){
values = [...values.slice(0, index+1), ...new_values.slice(1), ...values.slice(index+1)];
values[index] = values[index] + new_values[0];
} else if(values[index] === new_values[0]){
values = [...values.slice(0, index+1), ...new_values.slice(1), ...values.slice(index+1)];
} else {
new_values[0] = new_values[0].slice(values[index].length)
values = [...values.slice(0, index+1), ...new_values, ...values.slice(index+1)];
}
console.log(values);
}else{
values[index] = value;
}

setArrayValue(values);
onChange(name, values, false);
}
Expand Down Expand Up @@ -345,17 +352,19 @@ export function CreatePayloadParameter({onChange, parameter_type, default_value,
);
case "Array":
return (
<TableContainer component={Paper} className="mythicElement">
<TableContainer >
<Table size="small" style={{tableLayout: "fixed", maxWidth: "100%", "overflow": "auto"}}>
<TableBody>
{arrayValue.map( (a, i) => (
<TableRow key={'array' + name + i} >
<MythicStyledTableCell style={{width: "3rem"}}>
<IconButton onClick={(e) => {removeArrayValue(i)}} size="large"><DeleteIcon color="error" /> </IconButton>
<TableRow key={'array' + name + i} style={{}} >
<MythicStyledTableCell style={{width: "2rem"}}>
<DeleteIcon onClick={(e) => {removeArrayValue(i)}} color="error"
style={{cursor: "pointer"}}
/>
</MythicStyledTableCell>
<MythicStyledTableCell>
<MythicTextField required={required} fullWidth={true} placeholder={""} value={a} multiline={true}
onChange={(n,v,e) => onChangeArrayText(v, e, i)} display="inline-block"
onChange={(n,v,e) => onChangeArrayText(v, e, i)} display="inline-block" autoFocus={a === ""}
validate={testParameterValues} errorText={"Must match: " + verifier_regex}
/>
</MythicStyledTableCell>
Expand Down
Loading

0 comments on commit 29b3c89

Please sign in to comment.