Skip to content

Commit

Permalink
new mitm and new assets
Browse files Browse the repository at this point in the history
  • Loading branch information
VillanCh committed Mar 27, 2022
1 parent e3b51b4 commit 25f4eeb
Show file tree
Hide file tree
Showing 9 changed files with 733 additions and 538 deletions.
32 changes: 32 additions & 0 deletions app/main/handlers/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,36 @@ module.exports = (win, getClient) => {
ipcMain.handle("DeleteRisk", async (e, params) => {
return await asyncDeleteRisk(params)
})

// asyncQueryAvailableRiskType wrapper
const asyncQueryAvailableRiskType = (params) => {
return new Promise((resolve, reject) => {
getClient().QueryAvailableRiskType(params, (err, data) => {
if (err) {
reject(err)
return
}
resolve(data)
})
})
}
ipcMain.handle("QueryAvailableRiskType", async (e, params) => {
return await asyncQueryAvailableRiskType(params)
})

// asyncQueryAvailableRiskLevel wrapper
const asyncQueryAvailableRiskLevel = (params) => {
return new Promise((resolve, reject) => {
getClient().QueryAvailableRiskLevel(params, (err, data) => {
if (err) {
reject(err)
return
}
resolve(data)
})
})
}
ipcMain.handle("QueryAvailableRiskLevel", async (e, params) => {
return await asyncQueryAvailableRiskLevel(params)
})
};
32 changes: 32 additions & 0 deletions app/protos/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,41 @@ service Yak {
rpc QueryRisks(QueryRisksRequest) returns (QueryRisksResponse);
rpc QueryRisk(QueryRiskRequest) returns (Risk);
rpc DeleteRisk(QueryRiskRequest) returns (Empty);
rpc QueryAvailableRiskType(Empty) returns (Fields);
rpc QueryAvailableRiskLevel(Empty) returns (Fields);

// DNSLog
rpc RequireDNSLogDomain(YakDNSLogBridgeAddr) returns (DNSLogRootDomain);
rpc QueryDNSLogByToken(QueryDNSLogByTokenRequest) returns (QueryDNSLogByTokenResponse);
rpc QueryICMPTrigger(QueryICMPTriggerRequest) returns (QueryICMPTriggerResponse);
}

message FieldName {
string Name = 1;
string Verbose = 2;
int32 Total = 3;
}

message Fields {
repeated FieldName Values = 1;
}

message QueryICMPTriggerRequest {
int32 Length = 1;
}

message QueryICMPTriggerResponse {
repeated ICMPTriggerNotification Notification = 1;
}

message ICMPTriggerNotification {
int32 Size = 1;
int32 CurrentRemoteAddr = 2;
repeated string Histories = 3;
int32 CurrentRemoteCachedConnectionCount = 4;
int32 SizedCachedHistoryConnectionCount = 5;
int64 TriggerTimestamp = 7;
int64 Timestamp = 8;
}

message GetHistoryHTTPFuzzerTaskRequest {
Expand Down Expand Up @@ -341,6 +372,7 @@ message QueryRisksRequest {
string RiskType = 5;
string Token = 6;
bool WaitingVerified = 7;
string Severity = 8;
}

message QueryRisksResponse {
Expand Down
403 changes: 203 additions & 200 deletions app/renderer/src/main/src/pages/mitm/MITMPage.tsx

Large diffs are not rendered by default.

49 changes: 17 additions & 32 deletions app/renderer/src/main/src/pages/mitm/MITMPluginCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,12 @@ import ReactJson from "react-json-view";
import {SelectOne} from "../../utils/inputUtil";
import {YakScriptParamsSetter} from "../invoker/YakScriptParamsSetter";
import "../main.css";
import {MITMPluginOperatorProps} from "./MITMPluginOperator";
import {MITMPluginListProp} from "./MITMPluginList";


export interface MITMPluginCardProp {
proxy?: string
downloadCertNode?: React.ReactNode
setFilterNode?: React.ReactNode
// hooks: YakScriptHooks[]
messages: ExecResultLog[]
onSubmitScriptContent?: (script: string) => any
onSubmitYakScriptId?: (id: number, params: YakExecutorParam[]) => any
onSendToWebFuzzer?: (isHttps: boolean, request: string) => any
onExit?: () => any
autoUpdate?: boolean
export interface MITMPluginCardProp extends MITMPluginListProp {

}

const {ipcRenderer} = window.require("electron");
Expand All @@ -45,27 +38,19 @@ export const MITMPluginCard: React.FC<MITMPluginCardProp> = (props) => {
}, [])

return <div style={{height: "100%"}}>
{/* <Tabs
className={"httphacker-tabs"}
size={"small"} type={"card"} activeKey={tab} onChange={setTab}
style={{
paddingTop: 4
}}
>
<Tabs.TabPane key={"history"} tab={"历史请求"}> */}
<div style={{height: "100%", overflow: "hidden"}}>
<HTTPFlowMiniTable
simple={true}
onTotal={setTotal}
filter={{
SearchURL: "",
Pagination: {...genDefaultPagination(), Page: 1, Limit: 20}
}}
source={""}
autoUpdate={props.autoUpdate}
/>
</div>
{/* </Tabs.TabPane>
<div style={{height: "100%", overflow: "hidden"}}>
<HTTPFlowMiniTable
simple={true}
onTotal={setTotal}
filter={{
SearchURL: "",
Pagination: {...genDefaultPagination(), Page: 1, Limit: 20}
}}
source={""}
autoUpdate={true}
/>
</div>
{/* </Tabs.TabPane>
</Tabs> */}
</div>
};
Expand Down
197 changes: 197 additions & 0 deletions app/renderer/src/main/src/pages/mitm/MITMPluginList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import React, {useEffect, useState} from "react";
import {AutoCard} from "../../components/AutoCard";
import {Button, Empty, Form, List, Popconfirm, Space} from "antd";
import {SelectOne} from "../../utils/inputUtil";
import {PoweroffOutlined, ReloadOutlined} from "@ant-design/icons";
import {getValue, saveValue} from "../../utils/kv";
import {EditorProps, YakCodeEditor} from "../../utils/editors";
import {YakModuleList} from "../yakitStore/YakitStorePage";
import {YakScript, YakScriptHooks} from "../invoker/schema";
import {useMap, useMemoizedFn} from "ahooks";
import {ExecResultLog} from "../invoker/batch/ExecMessageViewer";
import {YakExecutorParam} from "../invoker/YakExecutorParams";
import {MITMPluginTemplateShort} from "../invoker/data/MITMPluginTamplate";
import {MITMYakScriptLoader} from "./MITMYakScriptLoader";
import {failed} from "../../utils/notification";

export const MITM_HOTPATCH_CODE = `MITM_HOTPATCH_CODE`

export interface MITMPluginListProp {
proxy?: string
downloadCertNode?: () => React.ReactNode
setFilterNode?: () => React.ReactNode
onSubmitScriptContent?: (script: string) => any
onSubmitYakScriptId?: (id: number, params: YakExecutorParam[]) => any
onSendToWebFuzzer?: (isHttps: boolean, request: string) => any
onExit?: () => any
}

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

const updateHooks = () => {
ipcRenderer.invoke("mitm-get-current-hook").catch(e => {
failed(`更新 MITM 插件状态失败: ${e}`)
})
}

export const MITMPluginList: React.FC<MITMPluginListProp> = (props) => {
const [initialed, setInitialed] = useState(false);
const [script, setScript] = useState(MITMPluginTemplateShort);
// const [userDefined, setUserDefined] = useState(false);
const [hooks, handlers] = useMap<string, boolean>(new Map<string, boolean>());
const [mode, setMode] = useState<"hot-patch" | "loaded" | "all">("all");
const [refreshTrigger, setRefreshTrigger] = useState(false);
const refresh = useMemoizedFn(() => {
setRefreshTrigger(!refreshTrigger)
})

useEffect(() => {
getValue(MITM_HOTPATCH_CODE).then(e => {
if (!e) {
return
}
setScript(`${e}`)
})
}, [])

// 设置用户模式
const userDefined = mode === "hot-patch";
let hooksItem: { name: string }[] = [];
hooks.forEach((value, key) => {
if (value) {
hooksItem.push({name: key})
}
});
hooksItem = hooksItem.sort((a, b) => a.name.localeCompare(b.name))

useEffect(() => {
// 用于 MITM 的 查看当前 Hooks
ipcRenderer.on("client-mitm-hooks", (e, data: YakScriptHooks[]) => {
const tmp = new Map<string, boolean>()
data.forEach(i => {
i.Hooks.map(hook => {
tmp.set(hook.YakScriptName, true)
})
})
handlers.setAll(tmp)
})
updateHooks()
setTimeout(() => {
setInitialed(true)
}, 300)
return () => {
ipcRenderer.removeAllListeners("client-mitm-hooks");
}
}, []);

return <AutoCard
bordered={false}
bodyStyle={{padding: 0}}
loading={!initialed}
title={<Space>
<Form size={"small"} onSubmitCapture={e => e.preventDefault()}>
<SelectOne
data={[
{text: "热加载", value: "hot-patch"},
{text: "已启用", value: "loaded"},
{text: "全部", value: "all"},
]}
value={mode}
formItemStyle={{marginBottom: 0}}
setValue={setMode}
/>
</Form>
{mode === "hot-patch" && <Popconfirm
title={"确认重置热加载代码?"}
onConfirm={() => {
setScript(MITMPluginTemplateShort)
refresh()
}}
>
<Button
type={"link"} icon={<ReloadOutlined/>} size={"small"}
/>
</Popconfirm>}
</Space>} size={"small"}
extra={<>
<Space>
{userDefined && <Button
size={"small"} type={"primary"}
onClick={() => {
if (!!script) {
saveValue(MITM_HOTPATCH_CODE, script)
}
props.onSubmitScriptContent && props.onSubmitScriptContent(script)
}}
>加载当前代码</Button>}
{/*: <Button*/}
{/* size={"small"} type={"primary"}*/}
{/* onClick={() => {*/}
{/* enablePlugin()*/}
{/* }}*/}
{/*>加载插件</Button>}*/}
<Button
danger={true}
size={"small"} type={"primary"}
onClick={() => {
props.onExit && props.onExit()
}}
icon={<PoweroffOutlined/>}
>停止</Button>
</Space>
</>}
>
{mode === "hot-patch" && <>
{/* 用户热加载代码 */}
<YakCodeEditor
refreshTrigger={refreshTrigger}
noHeader={true} noPacketModifier={true}
originValue={Buffer.from(script || "")}
onChange={e => setScript(e.toString())}
language={"yak"}
extraEditorProps={{
noMiniMap: true, noWordWrap: true,
} as EditorProps}
/>
</>}
{mode === "all" && <>
<YakModuleList
Type={"mitm"}
onClicked={(script: YakScript) => {

}}
Keyword={""}
onYakScriptRender={(i: YakScript) => {
return <MITMYakScriptLoader
script={i} hooks={hooks}
onSendToPatch={code => {
setScript(code)
setMode("hot-patch")
}}
onSubmitYakScriptId={props.onSubmitYakScriptId}
/>
}}
/>
</>}
{mode === "loaded" && <>
{hooks.size > 0 ? <>
<List pagination={false}>
{hooksItem.map(i => {
return <>
<MITMYakScriptLoader
onSendToPatch={code => {
setScript(code)
setMode("hot-patch")
}}
script={{ScriptName: i.name} as YakScript} hooks={hooks}
onSubmitYakScriptId={props.onSubmitYakScriptId}
/>
</>
})}
</List>
</> : <>
<Empty description={"未启用 MITM 插件"}/>
</>}
</>}
</AutoCard>
};
32 changes: 32 additions & 0 deletions app/renderer/src/main/src/pages/mitm/MITMPluginLogViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import {AutoCard} from "../../components/AutoCard";
import {Divider, Space, Tag} from "antd";
import {formatDate} from "../../utils/timeUtil";
import {StatusCardViewer} from "./MITMYakScriptLoader";
import {YakitLogViewers} from "../invoker/YakitLogFormatter";
import {ExecResultLog} from "../invoker/batch/ExecMessageViewer";
import moment from "moment";
import {StatusCardProps} from "../yakitStore/viewers/base";

export interface MITMPluginLogViewerProp {
messages: ExecResultLog[]
status: StatusCardProps[]
}


export const MITMPluginLogViewer: React.FC<MITMPluginLogViewerProp> = React.memo((props) => {
const {status} = props;
const currentTimestamp: number = (props?.messages || []).length > 0 ? props.messages[0].timestamp : moment().unix()

return <AutoCard
title={<Space>
<Tag color={"geekblue"}>{formatDate(currentTimestamp)}</Tag>
</Space>}
size={"small"}
bodyStyle={{overflowY: "auto"}}
>
<StatusCardViewer status={status}/>
<Divider style={{marginTop: 8}}/>
<YakitLogViewers data={props.messages} onlyTime={true}/>
</AutoCard>
});
Loading

0 comments on commit 25f4eeb

Please sign in to comment.