Skip to content

Commit 3d0b778

Browse files
0x707a15ecRickdeJager
authored andcommitted
Change hotkeys, enable flow marking, fix flow change behavior, fix README
1 parent b8af07c commit 3d0b778

File tree

8 files changed

+92
-43
lines changed

8 files changed

+92
-43
lines changed

‎README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ Tulip was developed by Team Europe for use in the first International Cyber Secu
1313
* Synchronized with Suricata.
1414
* Flow diffing
1515
* Time and size-based plots for correlation.
16-
* Linking HTTP sessions together based on cookies (Experimental, disabled by default)
16+
* Linking HTTP sessions together based on cookies (Experimental*, disabled by default)
17+
18+
\* - to enable, add `-experimental` after `./assembler` in `docker-compose.yml`
1719

1820
## Screenshots
1921
![](./demo_images/demo1.png)
@@ -88,7 +90,6 @@ Your Tulip instance will probably contain sensitive CTF information, like flags
8890

8991
# Contributing
9092
If you have an idea for a new feature, bug fixes, UX improvements, or other contributions, feel free to open a pull request or create an issue!
91-
When opening a pull request, please target the `devel` branch.
9293

9394
# Credits
9495
Tulip was written by [@RickdeJager](https://github.com/rickdejager) and [@Bazumo](https://github.com/bazumo), with additional help from [@Sijisu](https://github.com/sijisu). Thanks to our fellow Team Europe players and coaches for testing, feedback and suggestions. Finally, thanks to the team behind [flower](https://github.com/secgroup/flower) for opensourcing their tooling.

‎frontend/src/api.ts‎

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -166,28 +166,28 @@ export const tulipApi = createApi({
166166
}),
167167
// TODO: optimistic cache update
168168

169-
// async onQueryStarted({ id, star }, { dispatch, queryFulfilled }) {
170-
// // `updateQueryData` requires the endpoint name and cache key arguments,
171-
// // so it knows which piece of cache state to update
172-
// const patchResult = dispatch(
173-
// tulipApi.util.updateQueryData("getFlows", undefined, (flows) => {
174-
// // The `flows` is Immer-wrapped and can be "mutated" like in createSlice
175-
// const flow = flows.find((flow) => flow._id.$oid === id);
176-
// if (flow) {
177-
// if (star) {
178-
// flow.tags.push("starred");
179-
// } else {
180-
// flow.tags = flow.tags.filter((tag) => tag != "starred");
181-
// }
182-
// }
183-
// })
184-
// );
185-
// try {
186-
// await queryFulfilled;
187-
// } catch {
188-
// patchResult.undo();
189-
// }
190-
// },
169+
async onQueryStarted({ id, star }, { dispatch, queryFulfilled }) {
170+
// `updateQueryData` requires the endpoint name and cache key arguments,
171+
// so it knows which piece of cache state to update
172+
const patchResult = dispatch(
173+
tulipApi.util.updateQueryData("getFlows", {service: "undefined", tags_include: [], tags_exclude:[]}, (flows) => {
174+
// The `flows` is Immer-wrapped and can be "mutated" like in createSlice
175+
const flow = flows.find((flow) => flow.id === id);
176+
if (flow) {
177+
if (star) {
178+
flow.tags.push("starred");
179+
} else {
180+
flow.tags = flow.tags.filter((tag) => tag != "starred");
181+
}
182+
}
183+
})
184+
);
185+
try {
186+
await queryFulfilled;
187+
} catch {
188+
patchResult.undo();
189+
}
190+
},
191191
}),
192192
}),
193193
});

‎frontend/src/components/Corrie.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export const Corrie = () => {
190190
>
191191
under attack
192192
</button>
193+
<p className="text-left px-2 py-2">After clicking on a flow, press 'w' to scroll to it in flow list</p>
193194
</div>
194195
</div>
195196
<div className="flex-1 w-full overflow-hidden p-4">

‎frontend/src/components/FlowList.tsx‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
START_FILTER_KEY,
1515
END_FILTER_KEY,
1616
FLOW_LIST_REFETCH_INTERVAL_MS,
17+
FORCE_REFETCH_ON_STAR,
1718
} from "../const";
1819
import { useAppSelector, useAppDispatch } from "../store";
1920
import { toggleFilterTag, toggleTagIntersectMode } from "../store/filter";
@@ -118,6 +119,7 @@ export function FlowList() {
118119

119120
const onHeartHandler = async (flow: Flow) => {
120121
await starFlow({ id: flow.id, star: !flow.tags.includes("starred") });
122+
if(FORCE_REFETCH_ON_STAR) refetch();
121123
};
122124

123125
const navigate = useNavigate();
@@ -164,7 +166,30 @@ export function FlowList() {
164166
[transformedFlowData]
165167
)
166168

169+
useHotkeys('x', async () => {
170+
if(transformedFlowData) {
171+
let flow = transformedFlowData[flowIndex ?? 0]
172+
await onHeartHandler(flow);
173+
}
174+
})
175+
167176
useHotkeys('j', () => setFlowIndex(fi => Math.min((transformedFlowData?.length ?? 1)-1, fi + 1)), [transformedFlowData?.length]);
177+
useHotkeys('w', () => {
178+
if(transformedFlowData) {
179+
let idAtIndex = transformedFlowData[flowIndex ?? 0].id;
180+
if (idAtIndex != openedFlowID) {
181+
let flowids = flowData?.map((flow, idx) => ([flow.id, idx]))
182+
if (flowids) {
183+
let found = flowids.filter((el)=>(el[0] == openedFlowID))
184+
if (found.length > 0) {
185+
let n = Number(found[0][1])
186+
setFlowIndex(n)
187+
}
188+
}
189+
}
190+
}
191+
}
192+
);
168193
useHotkeys('k', () => setFlowIndex(fi => Math.max(0, fi - 1)));
169194
useHotkeys('i', () => {
170195
setShowFilters(true)
@@ -178,6 +203,12 @@ export function FlowList() {
178203
dispatch(toggleFilterTag("flag-out"))
179204
}
180205
}, [availableTags]);
206+
useHotkeys('t', () => {
207+
setShowFilters(true)
208+
if ((availableTags ?? []).includes("starred")) {
209+
dispatch(toggleFilterTag("starred"))
210+
}
211+
}, [availableTags]);
181212
useHotkeys('r', () => refetch());
182213

183214
const [showFilters, setShowFilters] = useState(false);

‎frontend/src/components/Header.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ function SecondDiff() {
196196
setSearchParams(searchParams);
197197
}
198198

199-
useHotkeys("g", () => {
199+
useHotkeys("e", () => {
200200
setSecondDiffFlow();
201201
});
202202

@@ -249,6 +249,9 @@ export function Header() {
249249
let { currentTick, setToLastnTicks, setTimeParam } = getTickStuff();
250250
let [searchParams] = useSearchParams();
251251

252+
let navigate = useNavigate();
253+
254+
useHotkeys('g', () => navigate(`/corrie?${searchParams}`, { replace: true }))
252255
useHotkeys('a', () => setToLastnTicks(5));
253256
useHotkeys('c', () => {
254257
(document.getElementById("startdateselection") as HTMLInputElement).value = "";

‎frontend/src/const.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ export const TICK_REFETCH_INTERVAL_MS = 10000;
1414
export const FLOW_LIST_REFETCH_INTERVAL_MS = 30000;
1515
export const UNDER_ATTACK_REFETCH_INTERVAL_MS = 30000;
1616
export const MAX_LENGTH_FOR_HIGHLIGHT = 400000;
17+
18+
export const FORCE_REFETCH_ON_STAR = true;

‎frontend/src/pages/FlowView.tsx‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -535,19 +535,25 @@ export function FlowView() {
535535
// TODO: account for user scrolling - update currentFlow accordingly
536536
const [currentFlow, setCurrentFlow] = useState<number>(-1);
537537

538-
useHotkeys("h", () => {
538+
// reset scroll on flow switch
539+
useHotkeys('j', () => setCurrentFlow(0))
540+
useHotkeys('k', () => setCurrentFlow(0))
541+
542+
useHotkeys('h', () => {
539543
// we do this for the scroll to top
540544
if (currentFlow === 0) {
541-
document.getElementById(`${id}-${currentFlow}`)?.scrollIntoView(true)
545+
// document.getElementById(`${id}-${currentFlow}`)?.scrollIntoView(true)
546+
let el = document.querySelector("main > div > div:nth-child(2)")
547+
if (el) el.scrollIntoView()
542548
}
543549
setCurrentFlow(fi => Math.max(0, fi - 1))
544550
}, [currentFlow]);
545-
useHotkeys("l", () => {
546-
if (currentFlow === (flow?.flow[reprId]?.flow?.length ?? 1) - 1) {
547-
document.getElementById(`${id}-${currentFlow}`)?.scrollIntoView(true)
548-
}
549-
setCurrentFlow(fi => Math.min((flow?.flow[reprId]?.flow?.length ?? 1) - 1, fi + 1))
550-
}, [currentFlow, flow?.flow[reprId]?.flow?.length, reprId]);
551+
useHotkeys('l', () => {
552+
// if (currentFlow === (flow?.flow?.length ?? 1)-1) {
553+
// document.getElementById(`${id}-${currentFlow}`)?.scrollIntoView(true)
554+
// }
555+
setCurrentFlow(fi => Math.min((flow?.flow?.length ?? 1)-1, fi + 1))
556+
}, [currentFlow, flow?.flow?.length]);
551557

552558
useEffect(
553559
() => {

‎frontend/src/pages/Home.tsx‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
const shortcutTableData = [
22
[
33
{ key: 'j/k', action: 'Down/Up in FlowList' },
4-
{ key: 's', action: 'Focus search bar' },
4+
{ key: 'h/l', action: 'Up/Down in Flow' },
5+
{ key: 's', action: 'Focus (s)earch bar' },
56
{ key: 'esc', action: 'Unfocus search bar' },
6-
{ key: 'i/o', action: 'Toggle flag in/out filters' },
77
],
88
[
9-
{ key: 'h/l', action: 'Up/Down in Flow' },
10-
{ key: 'a', action: 'Last 5 ticks' },
11-
{ key: 'c', action: 'Clear time selection' },
12-
{ key: 'r', action: 'Refresh flows' },
9+
{ key: 'a', action: 'L(a)st 5 ticks' },
10+
{ key: 'c', action: '(C)lear time selection' },
11+
{ key: 'r', action: '(R)efresh flows' },
1312
],
1413
[
15-
{ key: 'm', action: 'Switch between decoders' },
16-
{ key: 'd', action: 'Diff view' },
17-
{ key: 'f', action: 'Load flow to first diff slot' },
18-
{ key: 'g', action: 'Load flow to second diff slot' },
14+
{ key: 'd', action: '(D)iff view' },
15+
{ key: 'f', action: 'Load flow to (f)irst diff slot' },
16+
{ key: 'e', action: 'Load flow to s(e)cond diff slot' },
17+
{ key: 'g', action: '(G)raph view' },
18+
],
19+
[
20+
{ key: 'w', action: 'Scroll to current flo(w) in flow list' },
21+
{ key: 'i/o', action: 'Toggle flag in/out filters' },
22+
{ key: 't', action: 'Toggle s(t)arred filters' },
23+
{ key: 'x', action: 'Star selected flow' },
1924
]
2025
];
2126

0 commit comments

Comments
 (0)