Skip to content

Commit

Permalink
Merge pull request yaklang#200 from yaklang/nonight/feature/send-operate
Browse files Browse the repository at this point in the history
feat: 漏洞与风险页新增等级列 & mitm页SSL证书下载功能 & fix: 修复主页中tab页名称内容展示问题
  • Loading branch information
VillanCh authored Mar 31, 2022
2 parents c8e1c50 + d6dba15 commit 848bff8
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 53 deletions.
6 changes: 3 additions & 3 deletions app/main/handlers/communication.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ module.exports = (win, getClient) => {
ipcMain.handle("change-main-menu", async (e) => {
win.webContents.send("fetch-new-main-menu");
});
// 远程打开一个fuzzer工具页面 / open a fuzzer tool page remotely
ipcMain.handle("send-to-fuzzer", async (e, params) => {
win.webContents.send("fetch-send-to-fuzzer", params);
// 远程打开一个工具页面 / open a tool page remotely
ipcMain.handle("send-to-tab", async (e, params) => {
win.webContents.send("fetch-send-to-tab", params);
});
// 请求包通过通信打开一个数据包插件执行弹窗
ipcMain.handle("send-to-packet-hack", async (e, params) => {
Expand Down
2 changes: 1 addition & 1 deletion app/main/handlers/execYak.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ module.exports = (win, getClient) => {
const asyncSaveFileDialog = async (params) => {
return new Promise((resolve, reject) => {
dialog
.showSaveDialog({
.showSaveDialog(win, {
title: "保存文件",
defaultPath: params,
})
Expand Down
9 changes: 6 additions & 3 deletions app/renderer/src/main/src/components/FuzzableParamList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ export const FuzzableParamList: React.FC<FuzzableParamListProp> = (props) => {
title: "操作", render: (i: FuzzableParams) => <Space>
<Popconfirm title={"测试该参数将会暂时进入 Web Fuzzer"}
onConfirm={(e) => {
ipcRenderer.invoke("send-to-fuzzer", {
isHttps: i.IsHTTPS,
request: new Buffer(i.AutoTemplate).toString("utf8")
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{
isHttps: i.IsHTTPS,
request: new Buffer(i.AutoTemplate).toString("utf8")
}
})
if (props.sendToWebFuzzer) props.sendToWebFuzzer()
}}
Expand Down
10 changes: 8 additions & 2 deletions app/renderer/src/main/src/components/HTTPFlowDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,14 @@ export const HTTPFlowDetail: React.FC<HTTPFlowDetailProp> = (props) => {
label: '发送到Fuzzer',
contextMenuGroupId: 'send-fuzzer-info',
run: () => {
ipcRenderer.invoke("send-to-fuzzer", {isHttps: flow?.IsHTTPS, request: Buffer.from(flow?.Request || []).toString("utf8")})
if (props.onClose) props.onClose()
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{
isHttps: flow?.IsHTTPS,
request: Buffer.from(flow?.Request || []).toString("utf8")
}
})
if (props.onClose) props.onClose()
}
},
{
Expand Down
8 changes: 7 additions & 1 deletion app/renderer/src/main/src/components/HTTPFlowMiniTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,13 @@ export const HTTPFlowMiniTable: React.FC<HTTPFlowMiniTableProp> = (props) => {
onClick={() => {
const req = findHTTPFlowById(i);
if (req) {
ipcRenderer.invoke("send-to-fuzzer", {isHttps: req.IsHTTPS, request: new Buffer(req.Request).toString()})
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{
isHttps: req.IsHTTPS,
request: new Buffer(req.Request).toString()
}
})
}
}}
>发送到Fuzzer</Button>}
Expand Down
18 changes: 12 additions & 6 deletions app/renderer/src/main/src/components/HTTPFlowTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,12 @@ export const HTTPFlowTable: React.FC<HTTPFlowTableProp> = (props) => {
const ref = useHotkeys('ctrl+r', e => {
const selected = getSelected()
if (selected) {
ipcRenderer.invoke("send-to-fuzzer", {
isHttps: selected?.IsHTTPS,
request: new Buffer(selected.Request).toString()
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{
isHttps: selected?.IsHTTPS,
request: new Buffer(selected.Request).toString()
}
})
}
})
Expand Down Expand Up @@ -1111,9 +1114,12 @@ export const HTTPFlowTable: React.FC<HTTPFlowTableProp> = (props) => {
{
title: '发送到 Web Fuzzer',
onClick: () => {
ipcRenderer.invoke("send-to-fuzzer", {
isHttps: rowData.IsHTTPS,
request: new Buffer(rowData.Request).toString("utf8")
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{
isHttps: rowData.IsHTTPS,
request: new Buffer(rowData.Request).toString("utf8")
}
})
}
},
Expand Down
61 changes: 33 additions & 28 deletions app/renderer/src/main/src/pages/MainOperator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import {PerformanceDisplay} from "../components/PerformanceDisplay"

import "./main.css"
import {useHotkeys} from "react-hotkeys-hook";
import {execTest} from "./invoker/ExecutePacketYakScript";
import {useMemoizedFn} from "ahooks"
import ReactDOM from "react-dom"
import debounce from "lodash/debounce"
Expand Down Expand Up @@ -130,6 +129,7 @@ const Main: React.FC<MainProp> = (props) => {
const [status, setStatus] = useState<{ addr: string; isTLS: boolean }>()
const [hideMenu, setHideMenu] = useState(false)
const [menuItems, setMenuItems] = useState<MenuItemGroup[]>([])
const [routeMenuData, setRouteMenuData] = useState<MenuDataProps[]>(RouteMenuData)
const [loading, setLoading] = useState(false)
const [pageCache, setPageCache] = useState<PageCache[]>([
{
Expand All @@ -139,7 +139,6 @@ const Main: React.FC<MainProp> = (props) => {
verbose: "MITM"
}
])
const [extraGeneralModule, setExtraGeneralModule] = useState<YakScript[]>([])
const [notification, setNotification] = useState("")
const [riskStats, setRiskStats] = useState<RiskStats>({
RiskLevelStats: {Values: []}, RiskTypeStats: {Values: []}
Expand Down Expand Up @@ -353,7 +352,30 @@ const Main: React.FC<MainProp> = (props) => {
Type: "yak"
} as QueryYakScriptRequest)
.then((data: QueryYakScriptsResponse) => {
setExtraGeneralModule(data.Data)
const tabList: MenuDataProps[] = cloneDeep(RouteMenuData)
for(let item of tabList){
if(item.subMenuData){
if(item.key === Route.GeneralModule){
const extraMenus: MenuDataProps[] = data.Data.map((i) => {
return {
icon: <EllipsisOutlined/>,
key: `plugin:${i.Id}`,
label: i.ScriptName,
} as unknown as MenuDataProps
})

item.subMenuData.push(...extraMenus)
let subMenuMap = new Map<string, MenuDataProps>()
item.subMenuData.forEach((e) => subMenuMap.set(e.key as string, e))
item.subMenuData = []
subMenuMap.forEach((v) => item.subMenuData?.push(v))
item.subMenuData.sort((a, b) => a.label.localeCompare(b.label))
}else{
item.subMenuData.sort((a, b) => a.label.localeCompare(b.label))
}
}
}
setRouteMenuData(tabList)
})
}

Expand Down Expand Up @@ -504,17 +526,20 @@ const Main: React.FC<MainProp> = (props) => {
ipcRenderer.on("fetch-new-main-menu", (e) => {
updateMenuItems()
})
ipcRenderer.on("fetch-send-to-fuzzer", (e, res: any) => addFuzzer(res))
ipcRenderer.on("fetch-send-to-tab", (e, res: any) => {
const {type, data = {}} = res
if(type === "fuzzer") addFuzzer(data)
})

return () => {
ipcRenderer.removeAllListeners("fetch-new-main-menu")
ipcRenderer.removeAllListeners("fetch-send-to-fuzzer")
ipcRenderer.removeAllListeners("fetch-send-to-tab")
}
}, [])

const pluginKey = (item: PluginMenuItem) => `plugin:${item.Group}:${item.YakScriptId}`;
const routeKeyToLabel = new Map<string, string>();
RouteMenuData.forEach(k => {
routeMenuData.forEach(k => {
(k.subMenuData || []).forEach(subKey => {
routeKeyToLabel.set(`${subKey.key}`, subKey.label)
})
Expand Down Expand Up @@ -766,31 +791,11 @@ const Main: React.FC<MainProp> = (props) => {
</Menu.SubMenu>
)
})}
{(RouteMenuData || []).map((i) => {
{(routeMenuData || []).map((i) => {
if (i.subMenuData) {
let subMenus = cloneDeep(i.subMenuData)

if (i.key === `${Route.GeneralModule}`) {
const extraMenus = extraGeneralModule.map((i) => {
return {
icon: <EllipsisOutlined/>,
key: `plugin:${i.Id}`,
label: i.ScriptName,
} as unknown as MenuDataProps
})
subMenus.push(...extraMenus)
let subMenuMap = new Map<string, MenuDataProps>()
subMenus.forEach((e) => {
subMenuMap.set(e.key as string, e)
})
subMenus = []
subMenuMap.forEach((v) => subMenus?.push(v))
subMenus.sort((a, b) => a.label.localeCompare(b.label))
}
subMenus.sort((a, b) => (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0))
return (
<Menu.SubMenu icon={i.icon} key={i.key} title={i.label}>
{(subMenus || []).map((subMenu) => {
{(i.subMenuData || []).map((subMenu) => {
return (
<MenuItem icon={subMenu.icon} key={subMenu.key}
disabled={subMenu.disabled}>
Expand Down
5 changes: 4 additions & 1 deletion app/renderer/src/main/src/pages/fuzzer/HTTPFuzzerPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,10 @@ export const HTTPFuzzerPage: React.FC<HTTPFuzzerPageProp> = (props) => {
})

const sendToFuzzer = useMemoizedFn((isHttps: boolean, request: string) => {
ipcRenderer.invoke("send-to-fuzzer", {isHttps: isHttps, request: request})
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{isHttps: isHttps, request: request}
})
})
const sendToPlugin = useMemoizedFn((request: Uint8Array, isHTTPS: boolean, response?: Uint8Array) => {
let m = showDrawer({
Expand Down
9 changes: 6 additions & 3 deletions app/renderer/src/main/src/pages/mitm/MITMPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {AutoCard} from "../../components/AutoCard";
import {ResizeBox} from "../../components/ResizeBox";
import {MITMPluginLogViewer} from "./MITMPluginLogViewer";
import {MITMPluginList, MITMPluginListProp} from "./MITMPluginList";
import {openABSFileLocated} from "../../utils/openWebsite";
import {openABSFileLocated, saveABSFileToOpen} from "../../utils/openWebsite";

const {Text} = Typography;
const {Item} = Form;
Expand Down Expand Up @@ -470,7 +470,7 @@ export const MITMPage: React.FC<MITMPageProp> = (props) => {
<AutoCard extra={<Button
type={"link"}
onClick={() => {
alert("no implemented")
saveABSFileToOpen("yakit证书.crt.pem", caCerts.CaCerts)
// openABSFileLocated(caCerts.LocalFile)
}}
>
Expand Down Expand Up @@ -521,7 +521,10 @@ export const MITMPage: React.FC<MITMPageProp> = (props) => {
})

const execFuzzer = useMemoizedFn((value: string) => {
ipcRenderer.invoke("send-to-fuzzer", {isHttps: currentPacketInfo.isHttp, request: value})
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{isHttps: currentPacketInfo.isHttp, request: value}
})
})
const execPlugin = useMemoizedFn((value: string) => {
ipcRenderer.invoke("send-to-packet-hack", {
Expand Down
5 changes: 1 addition & 4 deletions app/renderer/src/main/src/pages/risks/RiskPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from "react";
import {PageHeader} from "antd";
import {RiskTable} from "./RiskTable";

export interface RiskPageProp {

}
export interface RiskPageProp {}

export const RiskPage: React.FC<RiskPageProp> = (props) => {
return <div>
Expand Down
21 changes: 21 additions & 0 deletions app/renderer/src/main/src/pages/risks/RiskTable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.title-debug{
color: #000000;
}
.title-info{
color: #8c8c8c;
}
.title-low{
color: #ffa940;
}
.title-middle{
color: #ff7a45;
}
.title-high{
color: #f5222d;
}
.title-fatal{
color: #a8071a;
}
.title-default{
color: #000000;
}
19 changes: 19 additions & 0 deletions app/renderer/src/main/src/pages/risks/RiskTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {showModal} from "../../utils/showModal"
import ReactJson from "react-json-view"
import {InputItem, ManyMultiSelectForString} from "../../utils/inputUtil"

import "./RiskTable.css"

export interface RiskTableProp {
}

Expand Down Expand Up @@ -60,6 +62,15 @@ const mergeFieldNames = (f: Fields) => {
return items
}

const TitleColor = [
{key: ["trace", "debug", "note"], value: "title-debug", name: "调试信息"},
{key: ["info", "fingerprint", "infof", "default"], value: "title-info", name: "信息/指纹"},
{key: ["low"], value: "title-low", name: "低危"},
{key: ["middle", "warn", "warning"], value: "title-middle", name: "中危"},
{key: ["high"], value: "title-high", name: "高危"},
{key: ["fatal", "critical", "panic"], value: "title-fatal", name: "严重"},
]

export const RiskTable: React.FC<RiskTableProp> = (props) => {
const [response, setResponse] = useState<QueryGeneralResponse<Risk>>({
Data: [],
Expand Down Expand Up @@ -220,6 +231,14 @@ export const RiskTable: React.FC<RiskTableProp> = (props) => {
)
}
},
{
title: "等级",
render: (i: Risk) => {
const title = TitleColor.filter(item => item.key.includes(i.Severity || ""))[0]
return <span className={title.value}>{title ? title.name : i.Severity || "-"}</span>
},
width: 90
},
{
title: "IP",
render: (i: Risk) => i?.IP || "-",
Expand Down
2 changes: 2 additions & 0 deletions app/renderer/src/main/src/pages/risks/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ export interface Risk {
Id: number
CreatedAt: number
UpdatedAt?: number

Severity?: string
}
5 changes: 4 additions & 1 deletion app/renderer/src/main/src/utils/editors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,10 @@ export const HTTPPacketEditor: React.FC<HTTPPacketEditorProp> = React.memo((prop
type={"primary"}
icon={<ThunderboltFilled/>}
onClick={() => {
ipcRenderer.invoke("send-to-fuzzer", {isHttps: props.defaultHttps || false, request: strValue})
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data:{isHttps: props.defaultHttps || false, request: strValue}
})
}}
>FUZZ</Button>}
<Tooltip title={"不自动换行"}>
Expand Down
17 changes: 17 additions & 0 deletions app/renderer/src/main/src/utils/openWebsite.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import { success } from "./notification";

const {ipcRenderer} = window.require("electron");

Expand All @@ -14,6 +15,22 @@ export const openABSFileLocated = (u: string) => {
ipcRenderer.invoke("open-specified-file", u)
}

export const saveABSFileToOpen = (name: string, data?: Uint8Array | string) => {
const isArr = Array.isArray(data)
ipcRenderer.invoke("show-save-dialog", name).then((res) => {
if (res.canceled) return
ipcRenderer
.invoke("write-file", {
route: res.filePath,
data: isArr ? new Buffer((data || []) as Uint8Array).toString() : data || ""
})
.then(() => {
success('下载完成')
ipcRenderer.invoke("open-specified-file", res.filePath)
})
})
}

export interface ExternalUrlProp {
url: string
title?: React.ReactNode
Expand Down

0 comments on commit 848bff8

Please sign in to comment.