Skip to content

Commit

Permalink
v3.2.18-rc8
Browse files Browse the repository at this point in the history
various UI fixes
  • Loading branch information
its-a-feature committed Feb 26, 2024
1 parent 85b1cdf commit f941848
Show file tree
Hide file tree
Showing 20 changed files with 140 additions and 49 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-rc8] - 2024-02-22

### Changed

- Fixed a bug where files registered would get a comment with a taskID instead of a task's display id, leading to confusing task numbers

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

### Changed
Expand Down
13 changes: 12 additions & 1 deletion MythicReactUI/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ 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]
## [0.1.73] - 2024-02-22

### Changed

- Fixed a bug where the download link for an uploaded file wasn't working
- Added token tracking to the file browser
- Fixed an issue with the experimental table when a size value was 0
- Fixed an issue where opening the process browser wouldn't go to that host's data automatically
- Updated FileBrowser tree to accept clicks anywhere
- Updated FileBrowser tree to accept contextMenu anywhere

## [0.1.72] 2024-02-21

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ const VirtualTreeRow = ({
setOpenContextMenu(false);
};
return (
<div className={"hoverme"} style={ListProps.style}>
<div className={"hoverme"} style={ListProps.style} onContextMenu={handleContextClick} ref={dropdownAnchorRef} onClick={handleOnClickRow}>
<div style={{display: 'flex' , marginBottom: "1px", flexGrow: 1, width: "100%"}}>
{[...Array(itemTreeData.depth)].map((o, i) => (
<div
Expand All @@ -223,16 +223,14 @@ const VirtualTreeRow = ({
<div
className={classes.root}
style={{ backgroundColor: theme.body, color: theme.text, alignItems: 'center', display: 'flex', paddingRight: "10px", textDecoration: itemTreeData.deleted ? 'line-through' : '' }}
onClick={handleOnClickRow}
onContextMenu={handleContextClick}
ref={dropdownAnchorRef}

>
<Popper open={openContextMenu} anchorEl={dropdownAnchorRef.current} role={undefined} transition disablePortal style={{zIndex: 4}}>
<Popper open={openContextMenu} anchorEl={dropdownAnchorRef.current} role={undefined} transition style={{zIndex: 4}}>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom',
transformOrigin: placement === 'bottom' ? 'left top' : 'left bottom',
}}
>
<Paper variant="outlined" className={"dropdownMenuColored"}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {CircularProgress} from '@mui/material';
import {TaskFromUIButton} from './TaskFromUIButton';
import { MythicStyledTooltip } from '../../MythicComponents/MythicStyledTooltip';
import Split from 'react-split';
import {subscriptionCallbackTokens} from "./CallbacksTabsTaskingInput";
import {CallbacksTabsTaskingInputTokenSelect} from "./CallbacksTabsTaskingInputTokenSelect";

const fileDataFragment = gql`
fragment fileObjData on mythictree {
Expand Down Expand Up @@ -293,14 +295,20 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
tableOpenedPathIdRef.current = nodeData.id;
setSelectedFolderData(nodeData);
}, []);
const onListFilesButton = ({ fullPath, callback_id, callback_display_id }) => {
const localSelectedToken = React.useRef("");
const onChangeSelectedToken = (token) => {
localSelectedToken.current = token;
}
const onListFilesButton = ({ fullPath, callback_id, callback_display_id, token }) => {
taskingData.current = ({
"token": token,
"parameters": {path: fullPath, full_path: fullPath, host: selectedFolderData.host, file: ""},
"ui_feature": "file_browser:list", callback_id, callback_display_id});
setOpenTaskingButton(true);
};
const onUploadFileButton = ({ fullPath, callback_id, callback_display_id }) => {
const onUploadFileButton = ({ fullPath, callback_id, callback_display_id, token }) => {
taskingData.current = ({
"token": token,
"parameters": {path: fullPath, full_path: fullPath, host: selectedFolderData.host},
"ui_feature": "file_browser:upload", "openDialog": true,
callback_id, callback_display_id
Expand All @@ -309,6 +317,7 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
};
const onTaskRowAction = useCallback(({ path, full_path, filename, uifeature, openDialog, getConfirmation, callback_id, callback_display_id }) => {
taskingData.current = ({
"token": localSelectedToken.current,
"parameters": {
host: selectedFolderData.host,
path: path,
Expand All @@ -317,7 +326,7 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
}, "ui_feature": uifeature,
openDialog, getConfirmation, callback_id, callback_display_id});
setOpenTaskingButton(true);
}, [selectedFolderData]);
}, [selectedFolderData, localSelectedToken.current]);
const toggleShowDeletedFiles = (showStatus) => {
setShowDeletedFiles(showStatus);
};
Expand All @@ -329,6 +338,7 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
}, [])
const taskListing = (nodeData, callback_id, callback_display_id) => {
taskingData.current = ({
"token": localSelectedToken.current,
"parameters": {path: nodeData.full_path_text, full_path: nodeData.full_path_text, host: selectedFolderData.host, file: ""},
"ui_feature": "file_browser:list", callback_id, callback_display_id});
setOpenTaskingButton(true);
Expand Down Expand Up @@ -357,6 +367,7 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
<div style={{ flexGrow: 0 }}>
<FileBrowserTableTop
tabInfo={tabInfo}
onChangeSelectedToken={onChangeSelectedToken}
selectedFolderData={selectedFolderData}
onListFilesButton={onListFilesButton}
onUploadFileButton={onUploadFileButton}
Expand All @@ -382,7 +393,9 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
</div>
</Split>
{openTaskingButton &&
<TaskFromUIButton ui_feature={taskingData.current?.ui_feature || " "}
<TaskFromUIButton
token={taskingData.current?.token || undefined}
ui_feature={taskingData.current?.ui_feature || " "}
callback_id={taskingData.current?.callback_id || tabInfo.callbackID}
parameters={taskingData.current?.parameters || ""}
tasking_location={"file_browser"}
Expand All @@ -395,17 +408,37 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
};
const FileBrowserTableTop = ({
selectedFolderData,
onChangeSelectedToken,
onListFilesButton,
onUploadFileButton,
toggleShowDeletedFiles,
tabInfo
}) => {
const [fullPath, setFullPath] = React.useState('');
const selectedToken = React.useRef("Default Token");
const [tokenOptions, setTokenOptions] = React.useState([]);
const [placeHolder, setPlaceHolder] = React.useState(selectedFolderData.host);
const [showDeletedFiles, setLocalShowDeletedFiles] = React.useState(false);
const onChangePath = (_, value) => {
setFullPath(value);
};
const changeSelectedToken = (token) => {
onChangeSelectedToken(token);
if(token === "Default Token"){
selectedToken.current = "Default Token";
return;
}
if(token.token_id !== selectedToken.current.token_id){
selectedToken.current = token;
}
}
useSubscription(subscriptionCallbackTokens, {
variables: {callback_id: tabInfo.callbackID}, fetchPolicy: "no-cache",
shouldResubscribe: true,
onData: ({data}) => {
setTokenOptions(data.data.callbacktoken);
}
});
useEffect(() => {
if (selectedFolderData.full_path_text !== undefined) {
setFullPath(selectedFolderData.full_path_text);
Expand All @@ -423,10 +456,10 @@ const FileBrowserTableTop = ({
snackActions.warning('Must provide a path to list');
return;
}
onListFilesButton({ fullPath });
onListFilesButton({ fullPath, token: selectedToken.current });
};
const onLocalUploadFileButton = () => {
onUploadFileButton({ fullPath });
onUploadFileButton({ fullPath, token: selectedToken.current });
};
const onLocalToggleShowDeletedFiles = () => {
setLocalShowDeletedFiles(!showDeletedFiles);
Expand Down Expand Up @@ -468,6 +501,12 @@ const FileBrowserTableTop = ({
</MythicStyledTooltip>
</React.Fragment>
),
startAdornment: (
<React.Fragment>
{tokenOptions.length > 0 ? (
<CallbacksTabsTaskingInputTokenSelect options={tokenOptions} changeSelectedToken={changeSelectedToken}/>
) : null}
</React.Fragment>),
style: { padding: 0 },
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const CallbacksTabsFileBrowserTree = ({ treeRootData, treeAdjMatrix, fetc
{openViewGroupsDialog &&
<MythicDialog
fullWidth={true}
maxWidth={"lg"}
maxWidth={"xl"}
open={openViewGroupsDialog}
onClose={() => {setOpenViewGroupDialog(false);}}
innerDialog={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,21 @@ export const CallbacksTabsProcessBrowserPanel = ({index, value, tabInfo, me}) =>
return prev;
}, {...treeAdjMtx});
setTreeAdjMtx(newMatrix);
const groups = Object.keys(newMatrix).sort();
// first see if we can find a group that matches our host, if not, then we can do first of each
let groups = Object.keys(newMatrix).sort();
if(groups.length > 0){
for(let i = 0; i < groups.length; i++){
const hosts = Object.keys(newMatrix[groups[i]]).sort();
if(hosts.length > 0){
if(hosts.includes(tabInfo.host)){
setSelectedGroup(groups[i]);
setSelectedHost(tabInfo.host);
return;
}
}
}
setSelectedGroup(groups[0]);
const hosts = Object.keys(groups[0]).sort();
const hosts = Object.keys(newMatrix[groups[0]]).sort();
if(hosts.length > 0){
setSelectedHost(hosts[0]);
}
Expand Down Expand Up @@ -210,7 +221,6 @@ export const CallbacksTabsProcessBrowserPanel = ({index, value, tabInfo, me}) =>
return prev;
}, {...treeAdjMtx});
setTreeAdjMtx(newMatrix);

}
})
const onListFilesButton = () => {
Expand All @@ -234,6 +244,7 @@ export const CallbacksTabsProcessBrowserPanel = ({index, value, tabInfo, me}) =>
const updateSelectedGroup = (group) => {
setSelectedGroup(group);
const hosts = Object.keys(treeAdjMtx[group]);
console.log("updated selected group, new hosts", hosts);
if(hosts.length > 0){
setSelectedHost(hosts[0]);
} else {
Expand Down Expand Up @@ -373,7 +384,7 @@ const ProcessBrowserTableTop = ({
{openViewGroupsDialog &&
<MythicDialog
fullWidth={true}
maxWidth={"lg"}
maxWidth={"xl"}
open={openViewGroupsDialog}
onClose={() => {setOpenViewGroupDialog(false);}}
innerDialog={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ subscription GetLoadedCommandsSubscription($callback_id: Int!){
}
`;
const subscriptionCallbackTokens = gql`
export const subscriptionCallbackTokens = gql`
subscription subscriptionCallbackTokens ($callback_id: Int!){
callbacktoken(where: {deleted: {_eq: false}, callback_id: {_eq: $callback_id}}) {
token {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, {useRef, useEffect} from 'react';
import React, {useEffect} from 'react';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
import InputLabel from '@mui/material/InputLabel';
import Input from '@mui/material/Input';

export function CallbacksTabsTaskingInputTokenSelect(props) {
const [options, setOptions] = React.useState([]);
const [selected, setSelected] = React.useState('');
const inputRef = useRef(null);
const handleChange = (event) => {
setSelected(event.target.value);
props.changeSelectedToken(event.target.value);
Expand Down Expand Up @@ -45,7 +43,6 @@ export function CallbacksTabsTaskingInputTokenSelect(props) {
}
return (
<FormControl style={{width: "20%"}}>
<InputLabel ref={inputRef}>Tokens</InputLabel>
<Select
labelId="demo-dialog-select-label"
id="demo-dialog-select"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ export const ResponseDisplayMaterialReactTable = ({table, callback_id, expand, t
}
if(h.type === "number" || h.type === "size"){
try{
return Number(row[h.plaintext]?.plaintext || NaN);
return Number(row[h.plaintext]?.plaintext);
}catch(error){
return row[h.plaintext]?.plaintext || "";
}
Expand Down
17 changes: 13 additions & 4 deletions MythicReactUI/src/components/pages/Callbacks/TaskFromUIButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const getLoadedCommandsBasedOnInput = ({cmd, ui_feature}) => {
}
`;
}
export const TaskFromUIButton = ({callback_id, callback_ids, cmd, ui_feature, parameters, onTasked, tasking_location, getConfirmation, openDialog, acceptText, dontShowSuccessDialog}) =>{
export const TaskFromUIButton = ({callback_id, callback_ids, cmd, ui_feature, parameters, onTasked, tasking_location, getConfirmation, openDialog, acceptText, dontShowSuccessDialog, token}) =>{
const [fileBrowserCommands, setFileBrowserCommands] = React.useState([]);
const [openSelectCommandDialog, setOpenSelectCommandDialog] = React.useState(false);
const [openParametersDialog, setOpenParametersDialog] = React.useState(false);
Expand Down Expand Up @@ -167,8 +167,16 @@ export const TaskFromUIButton = ({callback_id, callback_ids, cmd, ui_feature, pa
}

if(callbackTokenOptions.length > 0){
setOpenCallbackTokenSelectDialog(true);
setTaskingVariables(variables);
console.log("token", token)
if(token){
console.log("setting token")
setSelectedCallbackToken(token);
} else {
console.log("opening token select dialog")
setOpenCallbackTokenSelectDialog(true);
}

}else if(callback_ids){
createTask({variables: {...variables, callback_ids: callback_ids}})
} else {
Expand Down Expand Up @@ -207,7 +215,8 @@ export const TaskFromUIButton = ({callback_id, callback_ids, cmd, ui_feature, pa
onTasked({tasked: false});
}
useEffect( () => {
if(selectedCallbackToken === ""){
console.log(selectedCallbackToken);
if(selectedCallbackToken === "" || selectedCallbackToken === "Default Token"){
// we selected the default token to use
if(callback_ids){
createTask({variables: {...taskingVariables, callback_ids: callback_ids}});
Expand All @@ -225,7 +234,7 @@ export const TaskFromUIButton = ({callback_id, callback_ids, cmd, ui_feature, pa

}

}, [selectedCallbackToken])
}, [selectedCallbackToken]);
useEffect( () => {
if(selectedCommand.commandparameters === undefined){
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import Paper from '@mui/material/Paper';
import {IconButton, Typography} from '@mui/material';
import {MythicDialog} from "../../MythicComponents/MythicDialog";
import LinearProgress from '@mui/material/LinearProgress';
import { Backdrop } from '@mui/material';
import {CircularProgress} from '@mui/material';
import {snackActions} from "../../utilities/Snackbar";


const getCallbackMythicTreeGroups = gql`
Expand Down Expand Up @@ -61,12 +64,17 @@ query getCallbackMythicTreeGroups {
`;
export function ViewCallbackMythicTreeGroupsDialog(props){
const theme = useTheme();
const [backdropOpen, setBackdropOpen] = React.useState(true);
const [groups, setGroups] = React.useState([]);
const [openViewAllCallbacksDialog, setOpenViewAllCallbacksDialog] = React.useState(false);
React.useEffect( () => {
snackActions.info("Loading callbacks...");
}, []);
useQuery(getCallbackMythicTreeGroups, {
fetchPolicy: "no-cache",
variables: {group_name: [props.group_name]},
onCompleted: data => {

const groupData = data.callback.map( c => {
try{
let cIP = JSON.parse(c.ip);
Expand All @@ -80,8 +88,12 @@ export function ViewCallbackMythicTreeGroupsDialog(props){
}
})
setGroups(groupData);
setBackdropOpen(false);
}
});
React.useLayoutEffect(() => {
snackActions.clearAll();
}, [groups]);
return (
<React.Fragment>
<DialogTitle id="form-dialog-title" style={{display: "flex", justifyContent: "space-between"}}>
Expand All @@ -94,6 +106,9 @@ export function ViewCallbackMythicTreeGroupsDialog(props){
All of these callbacks are contributing data that's aggregated together for the "{props.group_name}" group.
</div>
<DialogContent dividers={true} style={{paddingLeft: 0, paddingRight: 0}}>
<Backdrop open={backdropOpen} style={{zIndex: 2, position: "absolute"}} invisible={false}>
<CircularProgress color="inherit" />
</Backdrop>
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word", width: "100%"}}>
<TableHead>
<TableRow>
Expand Down
Loading

0 comments on commit f941848

Please sign in to comment.