feat: 解析导入表

This commit is contained in:
381848900@qq.com 2024-12-15 14:32:28 +08:00
parent ce85787be9
commit 9806c9bacd
6 changed files with 228 additions and 15 deletions

View File

@ -16,11 +16,13 @@
"@tauri-apps/plugin-shell": "^2",
"antd": "^5.22.3",
"lodash-es": "^4.17.21",
"moment": "^2.30.1",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@tauri-apps/cli": "^2",
"@types/antd": "^1.0.4",
"@types/lodash-es": "^4.17.12",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",

View File

@ -22,10 +22,13 @@ importers:
version: 2.0.1
antd:
specifier: ^5.22.3
version: 5.22.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 5.22.3(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
lodash-es:
specifier: ^4.17.21
version: 4.17.21
moment:
specifier: ^2.30.1
version: 2.30.1
react:
specifier: ^18.0.0
version: 18.3.1
@ -36,6 +39,9 @@ importers:
'@tauri-apps/cli':
specifier: ^2
version: 2.1.0
'@types/antd':
specifier: ^1.0.4
version: 1.0.4(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@types/lodash-es':
specifier: ^4.17.12
version: 4.17.12
@ -659,6 +665,10 @@ packages:
'@tauri-apps/plugin-shell@2.0.1':
resolution: {integrity: sha512-akU1b77sw3qHiynrK0s930y8zKmcdrSD60htjH+mFZqv5WaakZA/XxHR3/sF1nNv9Mgmt/Shls37HwnOr00aSw==}
'@types/antd@1.0.4':
resolution: {integrity: sha512-gp4PGQckP1kNjj2H6juhjKIVwkpXwCIyIvOlwp2DC6geuhVpDHEEB5gwH4hJabVgBAFtrjBPJ58VIRV9VV9W2g==}
deprecated: This is a stub types definition. antd provides its own type definitions, so you do not need this installed.
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@ -825,6 +835,9 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -1704,6 +1717,16 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.1.1
'@types/antd@1.0.4(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
antd: 5.22.3(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
transitivePeerDependencies:
- date-fns
- luxon
- moment
- react
- react-dom
'@types/babel__core@7.20.5':
dependencies:
'@babel/parser': 7.26.3
@ -1755,7 +1778,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
antd@5.22.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
antd@5.22.3(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@ant-design/colors': 7.1.0
'@ant-design/cssinjs': 1.22.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -1787,7 +1810,7 @@ snapshots:
rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-notification: 5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-pagination: 4.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-picker: 4.8.3(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-picker: 4.8.3(dayjs@1.11.13)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-progress: 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-rate: 2.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -1934,6 +1957,8 @@ snapshots:
picomatch: 2.3.1
optional: true
moment@2.30.1: {}
ms@2.1.3: {}
nanoid@3.3.8: {}
@ -2104,7 +2129,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
rc-picker@4.8.3(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
rc-picker@4.8.3(dayjs@1.11.13)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.26.0
'@rc-component/trigger': 2.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -2116,6 +2141,7 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
dayjs: 1.11.13
moment: 2.30.1
rc-progress@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:

View File

@ -173,7 +173,7 @@ impl AppState {
import_module.module_name_rva = origin_item.name;
import_module.timestamp = origin_item.time_date_stamp;
// 2. 获取函数表
let mut functions: Vec<ImportFunctionTableItem> = Vec::new();
let mut functions: Vec<ImportFunctionTable> = Vec::new();
// 获取函数表的FOA
let mut base_offset = mmap.rva_to_foa(origin_item.original_first_thunk)? as usize;
// 循环解析函数表
@ -222,10 +222,11 @@ impl AppState {
CStr::from_ptr(ptr).to_str()?.to_string()
};
import_function_table.function_name = function_name;
functions.push(ImportFunctionTableItem::Named(import_function_table));
functions.push(import_function_table);
}
false => {
functions.push(ImportFunctionTableItem::Ordinal(import_function_table));
import_function_table.function_type = ImportFunctionTableItem::Ordinal;
functions.push(import_function_table);
}
}
// 下一个
@ -242,7 +243,7 @@ impl AppState {
#[derive(Debug, Default, Clone, Serialize)]
pub struct ImportModuleTable {
pub module_name: String, // 模块名称
pub functions: Vec<ImportFunctionTableItem>, // 这里要另一个结构体来描述
pub functions: Vec<ImportFunctionTable>, // 这里要另一个结构体来描述
pub timestamp: u32, // 时间戳
pub forwarder_chain: u32, // 转发链
pub module_name_rva: u32, // dll名称的RVA
@ -251,12 +252,13 @@ pub struct ImportModuleTable {
}
// 因为导入查找表可能是函数名、也可能是序号 所以用枚举包一下最好
#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, Default)]
pub enum ImportFunctionTableItem {
// 命名的导入函数
Named(ImportFunctionTable),
#[default]
Named,
// 序号表示的
Ordinal(ImportFunctionTable),
Ordinal,
}
#[derive(Debug, Default, Clone, Serialize)]
@ -264,4 +266,5 @@ pub struct ImportFunctionTable {
pub function_name: String, // 函数名称
pub function_address: u32, // 函数地址 IAT
pub function_hint: u16, // 函数提示
pub function_type: ImportFunctionTableItem
}

View File

@ -1,7 +1,10 @@
// import MainLayout from "./layouts/MainLayout";
import MainPage from "./pages/MainPage";
import moment from "moment";
import "./App.css";
// 初始化moment地区
moment.locale("zh-cn");
function App() {
return (

View File

@ -0,0 +1,7 @@
.moduleContainer{
flex-direction: column;
}
.functionContainer{
}

View File

@ -1,10 +1,178 @@
import { invoke } from "@tauri-apps/api/core";
import { useEffect } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import styles from "./ImportDirectory.module.scss";
import moment from "moment";
import { Flex, Table } from "antd";
import Title from "antd/es/typography/Title";
interface ModuleProps {
module_name: String;
timestamp: number;
forwarder_chain: number;
module_name_rva: number;
functions: FunctionProps[];
}
interface FunctionProps {
function_name: string;
function_address: number;
function_hint: number;
function_type: "Named" | "Ordinal";
}
interface ImportModuleComponentProps {
moduleList: ModuleProps[];
}
interface ModuleFuntionsComponentProps {
functionList: FunctionProps[];
}
const ImportModuleComponent: React.FC<ImportModuleComponentProps> = (props) => {
const { moduleList } = props;
const [selectedRowKey, setSelectedRowKey] = useState([]);
const handleRowSelection = (selectedRowKeys: any) => {
setSelectedRowKey(selectedRowKeys);
};
const columns = [
{
title: "模块名称",
dataIndex: "module_name",
key: "module_name",
},
{
title: "导入函数数量",
render: (_text: any, record: any) => {
console.log("record", record);
return record.functions.length;
},
},
{
title: "时间戳",
dataIndex: "timestamp",
key: "timestamp",
render: (text: number) => {
return moment(text).format("YYYY-MM-DD HH:mm:ss");
},
},
{
title: "转发链",
dataIndex: "forwarder_chain",
key: "forwarder_chain",
},
{
title: "模块名称的RVA",
dataIndex: "module_name_rva",
key: "module_name_rva",
render: (text: number) => {
return "0x" + text.toString(16).toUpperCase();
},
},
];
const select_functions = useMemo(() => {
return moduleList.find((module) => module.module_name === selectedRowKey[0])
?.functions;
}, [selectedRowKey]);
return (
<Flex className={styles.moduleContainer}>
<div>
<Title level={3}></Title>
<Table
columns={columns}
rowSelection={{
type: "radio",
selectedRowKeys: selectedRowKey,
selections: [
{
key: "module_name",
text: "模块名称",
},
],
}}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
handleRowSelection([record.module_name]);
},
};
}}
bordered
dataSource={moduleList}
rowKey="module_name"
pagination={false}
/>
</div>
<div>
<Title level={3}></Title>
<ModuleFuntionsComponent functionList={select_functions} />
</div>
</Flex>
);
};
const ModuleFuntionsComponent: React.FC<ModuleFuntionsComponentProps> = (
props
) => {
const { functionList } = props;
console.log("functionList", functionList);
const columns = [
{
title: "序号",
render:(_text,_record,index)=>`${index+1}`,
rowScope: 'row',
},
{
title: "函数名称",
dataIndex: "function_name",
key: "function_name",
},
{
title: "函数地址",
dataIndex: "function_address",
key: "function_address",
render: (text: number) => {
return "0x" + text.toString(16).toUpperCase();
},
},
{
title: "函数提示",
dataIndex: "function_hint",
key: "function_hint",
},
{
title: "函数类型",
dataIndex: "function_type",
key: "function_type",
render: (text: string) => {
console.log("text", text);
return text == "Named" ? "命名" : "序数";
},
},
];
return (
<Flex className={styles.functionContainer}>
<Table
columns={columns}
dataSource={functionList}
rowKey="function_name"
pagination={false}
bordered
/>
</Flex>
);
};
export default function ImportDirectory() {
const [data, setData] = useState([]);
const getData = () => {
invoke("command_get_pe_data_import_directory")
.then((res) => {
console.log("res", res);
const { fields } = res as any;
setData(fields);
})
.catch((err) => {
console.log("err", err);
@ -15,5 +183,9 @@ export default function ImportDirectory() {
getData();
}, []);
return <div>ImportDirectory</div>;
return (
<div>
<ImportModuleComponent moduleList={data} />
</div>
);
}