remove support for unneeded browserscript result types

This commit is contained in:
its-a-feature
2026-05-07 17:30:03 -05:00
parent 4c628c1974
commit 62f9146e26
5 changed files with 42 additions and 188 deletions
@@ -1,11 +1,8 @@
import React, {useEffect} from 'react';
import {gql, useLazyQuery, useSubscription} from '@apollo/client';
import {snackActions} from '../../utilities/Snackbar';
import {ResponseDisplayScreenshot} from './ResponseDisplayScreenshot';
import {ResponseDisplayPlaintext} from './ResponseDisplayPlaintext';
import {ResponseDisplayTable} from './ResponseDisplayTable';
import {ResponseDisplayDownload} from './ResponseDisplayDownload';
import {ResponseDisplaySearch} from './ResponseDisplaySearch';
import MythicTextField from '../../MythicComponents/MythicTextField';
import SearchIcon from '@mui/icons-material/Search';
import {useTheme} from '@mui/material/styles';
@@ -316,8 +313,7 @@ const NonInteractiveResponseDisplay = (props) => {
const pageStartIndex = (currentPageRef.current - 1) * pageSize;
const pageEndIndex = currentPageRef.current * pageSize;
const streamedStartIndex = Math.max(0, currentTotalCount - newStreamedResponses.length);
const streamedEndIndex = currentTotalCount;
if(streamedStartIndex >= pageEndIndex || streamedEndIndex <= pageStartIndex){
if(streamedStartIndex >= pageEndIndex || currentTotalCount <= pageStartIndex){
return;
}
const visibleStreamedResponses = newStreamedResponses.reduce( (responses, response, index) => {
@@ -648,11 +644,6 @@ export function ResponseDisplayBrowserScriptComponent({output, browserScriptData
<div className={`mythic-browser-script-response${expand ? " mythic-browser-script-response-expanded" : ""}`}>
{hasBrowserScriptData ? (
<>
{browserScriptData?.screenshot?.map( (scr, index) => (
<ResponseDisplayScreenshot key={"screenshot" + index + 'fortask' + task.id} task={task} {...scr}
displayType={displayType} expand={expand} />
))
}
{browserScriptData?.plaintext !== undefined &&
<ResponseDisplayPlaintext plaintext={browserScriptData["plaintext"]} task={task}
expand={expand} displayType={displayType} />
@@ -664,16 +655,6 @@ export function ResponseDisplayBrowserScriptComponent({output, browserScriptData
/>
))
}
{browserScriptData?.download?.map( (dl, index) => (
<ResponseDisplayDownload download={dl} task={task} displayType={displayType}
key={"download" + index + "fortask" + task.id} />
))
}
{browserScriptData?.search?.map( (s, index) => (
<ResponseDisplaySearch search={s} task={task} displayType={displayType}
key={"searchlink" + index + "fortask" + task.id} />
))
}
{browserScriptData?.media?.map( (s, index) => (
<ResponseDisplayMedia key={"searchmedia" + index + "fortask" + task.id}
displayType={displayType}
@@ -1,39 +0,0 @@
import React from 'react';
import GetAppIcon from '@mui/icons-material/GetApp';
import { Button } from '@mui/material';
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
export const ResponseDisplayDownload = (props) =>{
const scrollContent = (node, isAppearing) => {
// only auto-scroll if you issued the task
document.getElementById(`scrolltotaskbottom${props.task.id}`)?.scrollIntoView({
//behavior: "smooth",
block: "end",
inline: "nearest"
})
}
React.useLayoutEffect( () => {
scrollContent()
}, []);
return (
<div className="mythic-response-inline-output">
<pre className="mythic-response-inline-text">
{props.download?.plaintext || ""}
</pre>
<MythicStyledTooltip title={props?.download?.hoverText || "Download payload"} >
<Button
className="mythic-table-row-action mythic-table-row-action-hover-info mythic-response-inline-action"
variant={props.download?.variant || "text"}
component="a"
target="_blank"
href={"/api/v1.4/files/download/" + props.download.agent_file_id}
download
startIcon={<GetAppIcon />}>
{props.download?.name || "Download"}
</Button>
</MythicStyledTooltip>
</div>
);
}
@@ -1,48 +0,0 @@
import React from 'react';
import {Button} from '@mui/material';
import CameraAltIcon from '@mui/icons-material/CameraAlt';
import {ResponseDisplayScreenshotModal} from './ResponseDisplayScreenshotModal';
import { MythicDialog } from '../../MythicComponents/MythicDialog';
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
export const ResponseDisplayScreenshot = (props) =>{
const [openScreenshot, setOpenScreenshot] = React.useState(false);
const clickOpenScreenshot = () => {
setOpenScreenshot(true);
}
const scrollContent = (node, isAppearing) => {
// only auto-scroll if you issued the task
document.getElementById(`scrolltotaskbottom${props.task.id}`)?.scrollIntoView({
//behavior: "smooth",
block: "end",
inline: "nearest"
})
}
React.useLayoutEffect( () => {
scrollContent()
}, []);
return (
<div className="mythic-response-inline-output">
{openScreenshot &&
<MythicDialog fullWidth={true} maxWidth="xl" open={openScreenshot}
onClose={()=>{setOpenScreenshot(false);}}
innerDialog={<ResponseDisplayScreenshotModal images={[props.agent_file_id]} onClose={()=>{setOpenScreenshot(false);}} />}
/>
}
<pre className="mythic-response-inline-text">
{props?.plaintext || ""}
</pre>
<MythicStyledTooltip title={props?.hoverText || "View Screenshot (s)"} >
<Button
className="mythic-table-row-action mythic-table-row-action-hover-info mythic-response-inline-action"
variant={props.variant ? props.variant : "text"}
onClick={clickOpenScreenshot}
startIcon={<CameraAltIcon />}
>
{props.name || "View screenshot"}
</Button>
</MythicStyledTooltip>
</div>
);
}
@@ -6,7 +6,6 @@ import { MobileStepper } from '@mui/material';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import {useTheme} from '@mui/material/styles';
import {ImageWithAuth} from "../../utilities/ImageWithAuth";
export function ResponseDisplayScreenshotModal({onClose, images, startIndex}) {
const [zoom, setZoom] = React.useState(false);
@@ -14,51 +13,50 @@ export function ResponseDisplayScreenshotModal({onClose, images, startIndex}) {
const [activeStep, setActiveStep] = React.useState(startIndex ? startIndex : 0);
const maxSteps = images?.length || 1;
const toggleZoom = () => {
setZoom(!zoom);
setZoom(!zoom);
}
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
return (
< >
<DialogContent dividers={true} style={{padding: 0}} >
<div style={{height: "calc(80vh)", display: zoom ? "" : "flex", alignItems: zoom ? "" : "flex-start" , background: theme.palette.mode === "dark" ? "rgb(44, 52, 60)" : "grey"}}>
<ImageWithAuth onClick={toggleZoom} src={"/screencaptures/" + images[activeStep]}
style={{width: zoom ? "" : "100%", cursor: zoom ? "zoom-out" : "zoom-in", overflow: "auto"}} />
</div>
</DialogContent>
<MobileStepper
variant="text"
steps={maxSteps}
position="static"
activeStep={activeStep}
nextButton={
<Button
size="small"
onClick={handleNext}
disabled={activeStep === maxSteps - 1}
>
Next
{<KeyboardArrowRight />}
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={activeStep === 0}>
{<KeyboardArrowLeft />}
Back
</Button>
}
/>
<DialogActions >
<Button variant="contained" onClick={onClose} color="primary">
Close
</Button>
</DialogActions>
</>
);
}
return (
< >
<DialogContent dividers={true} style={{padding: 0}} >
<div style={{height: "calc(80vh)", display: zoom ? "" : "flex", alignItems: zoom ? "" : "flex-start" , background: theme.palette.mode === "dark" ? "rgb(44, 52, 60)" : "grey"}}>
<img onClick={toggleZoom} src={"/api/v1.4/files/screencaptures/" + images[activeStep]}
style={{width: zoom ? "" : "100%", cursor: zoom ? "zoom-out" : "zoom-in", overflow: "auto"}} />
</div>
</DialogContent>
<MobileStepper
variant="text"
steps={maxSteps}
position="static"
activeStep={activeStep}
nextButton={
<Button
size="small"
onClick={handleNext}
disabled={activeStep === maxSteps - 1}
>
Next
{<KeyboardArrowRight />}
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={activeStep === 0}>
{<KeyboardArrowLeft />}
Back
</Button>
}
/>
<DialogActions >
<Button variant="contained" onClick={onClose} color="primary">
Close
</Button>
</DialogActions>
</>
);
}
@@ -1,38 +0,0 @@
import React from 'react';
import {Button} from '@mui/material';
import SearchIcon from '@mui/icons-material/Search';
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
export const ResponseDisplaySearch = (props) =>{
const scrollContent = (node, isAppearing) => {
// only auto-scroll if you issued the task
document.getElementById(`scrolltotaskbottom${props.task.id}`)?.scrollIntoView({
//behavior: "smooth",
block: "end",
inline: "nearest"
})
}
React.useLayoutEffect( () => {
scrollContent()
}, []);
return (
<div className="mythic-response-inline-output">
<pre className="mythic-response-inline-text">
{props.search?.plaintext || ""}
</pre>
<MythicStyledTooltip title={props.search?.hoverText || "View on Search Page"} >
<Button
className="mythic-table-row-action mythic-table-row-action-hover-info mythic-response-inline-action"
component="a"
target="_blank"
href={window.location.origin + "/new/search/?" + props.search.search}
startIcon={<SearchIcon />}
>
{props.search?.name || "Open search"}
</Button>
</MythicStyledTooltip>
</div>
);
}