feat: 展示节区头

This commit is contained in:
381848900@qq.com 2024-12-11 20:48:10 +08:00
parent d7038a42d8
commit 175189bbdf
8 changed files with 220 additions and 72 deletions

View File

@ -132,3 +132,10 @@ pub fn command_get_pe_data_optional_header() -> Result<ResponseOptionalHeaderDat
let result = services::file::get_optional_header_data()?;
Ok(result)
}
// 命令,获取节区头数据
#[tauri::command]
pub fn command_get_pe_data_section_headers() -> Result<ResponseSectionHeaderData, AppError> {
let result = services::file::get_section_header_data()?;
Ok(result)
}

View File

@ -16,6 +16,7 @@ pub fn run() {
commands::command_get_pe_data_nt_header,
commands::command_get_pe_data_file_header,
commands::command_get_pe_data_optional_header,
commands::command_get_pe_data_section_headers,
commands::set_complete,
])
.run(tauri::generate_context!())

View File

@ -142,15 +142,21 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
Ok(optional_header_offset)
}
// 获取所有节区头数据
fn get_image_section_headers(&self) -> Result<&[ImageSectionHeader], PEParseError> {
// 1. 获取节区数量
let number_of_sections = self.get_number_of_sections()?;
// 2. 找到节区头的偏移
// 获取节区头的偏移
fn get_section_headers_offset(&self) -> Result<usize, PEParseError> {
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
let optional_header_size = self.get_size_of_optional_header()?;
let file_header_offset = self.get_file_header_offset()?;
let section_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>() + optional_header_size;
Ok(section_header_offset)
}
// 获取所有节区头数据
fn get_section_headers(&self) -> Result<&[ImageSectionHeader], PEParseError> {
// 1. 获取节区数量
let number_of_sections = self.get_number_of_sections()?;
// 2. 获取节区头偏移
let section_header_offset = self.get_section_headers_offset()?;
// 3. 获取节区头数据
unsafe {
let ptr = self.as_ptr().wrapping_offset(section_header_offset as isize) as *const ImageSectionHeader;

View File

@ -1,7 +1,7 @@
use memmap2::*;
use serde::Serialize;
use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders, ImageNTHeaders32, ImageOptionalHeader}, pe::PE}};
use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders, ImageNTHeaders32, ImageOptionalHeader, ImageSectionHeader}, pe::PE}};
use super::{GLOBAL_FILE_DATA, GLOBAL_IS_64_BIT};
@ -68,7 +68,6 @@ pub struct ResponseOptionalHeaderData {
pub is_64_bit: bool,
}
pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError> {
let binding = GLOBAL_FILE_DATA.lock().unwrap();
let file_data = binding.as_ref().unwrap();
@ -82,3 +81,23 @@ pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError
};
Ok(result)
}
// 获取节区头数据
#[derive(Serialize)]
pub struct ResponseSectionHeaderData {
pub fields: Vec<ImageSectionHeader>,
pub base_offset: usize,
}
pub fn get_section_header_data() -> Result<ResponseSectionHeaderData, AppError> {
let binding = GLOBAL_FILE_DATA.lock().unwrap();
let file_data = binding.as_ref().unwrap();
let section_headers = file_data.get_section_headers()?;
let section_headers_offset = file_data.get_section_headers_offset()?;
let vec_section_headers = section_headers.to_vec();
let result = ResponseSectionHeaderData {
fields: vec_section_headers,
base_offset: section_headers_offset,
};
Ok(result)
}

View File

@ -21,7 +21,7 @@ export interface DataType {
offset: number;
name: string;
size: number;
value: number | number[] | null;
value?: number | number[] | null;
description?: string;
// 枚举值 key:value => value: description
enum?: {
@ -204,7 +204,7 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
const cloneData = cloneDeep(props.dataTemplate);
// 2. 遍历resData更新cloneData
for (let key in cloneData) {
if(!resData || !resData.fields){
if (!resData || !resData.fields) {
continue;
}
@ -247,23 +247,28 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
cloneData[key].children = children;
}
// TODO: 字符数组处理
if (cloneData[key].data_type === "char_array") {
let value: any = resData.fields[key];
// 将ascii码转换为字符
let str = "";
for (let i = 0; i < value.length; i++) {
str += String.fromCharCode(value[i]);
}
cloneData[key].value = str as any;
}
}
// TODO: 应该从columns中获需要排序的字段来进行排序
// 如果cloneData的成员中有offset字段那么需要按照offset排序
let cloneDataArray = Object.values(cloneData);
if (cloneDataArray[0].offset) {
if (cloneDataArray[0] && cloneDataArray[0].offset) {
cloneDataArray.sort((a, b) => a.offset - b.offset);
}
return cloneDataArray;
};
const formatData = useMemo(()=>{
const formatData = useMemo(() => {
return handleData(props.defaultData as any);
}, [props.defaultData])
}, [props.defaultData]);
// useEffect(() => {
// // 请求数据

View File

@ -0,0 +1,16 @@
.NodeTableComponentRootFlex {
min-width: calc(100% - 16px);
}
.NodeTableComponentTable{
height: calc(100% - 16px);
}
.content{
// 垂直flex
display: flex;
flex-direction: column;
}
.tableItem {
margin-bottom: 24px;
}

View File

@ -1,34 +1,98 @@
import NodeTableComponent, {
DataTemplateInterface,
} from "../NodeTableComponent/NodeTableComponent";
} from "../NodeTableComponent/NodeTableComponent";
import { useEffect, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import styles from "./SectionHeaders.module.scss";
import { Flex } from "antd";
const dataTemplate: DataTemplateInterface = {
name: {
name: "name",
offset: 0,
size: 8,
data_type: "char_array",
description: "节区的名称,一般以.开头",
},
virtual_size: {
name: "virtual_size",
offset: 8,
size: 4,
data_type: "hex",
description: "在内存中的大小,不能为0",
},
virtual_address: {
name: "virtual_address",
offset: 12,
size: 4,
data_type: "hex",
description: "在内存中的地址(VA)",
},
size_of_raw_data: {
name: "size_of_raw_data",
offset: 16,
size: 4,
data_type: "hex",
description: "在文件中的大小",
},
pointer_to_raw_data: {
name: "pointer_to_raw_data",
offset: 20,
size: 4,
data_type: "hex",
description: "在文件中的偏移",
},
pointer_to_relocations: {
name: "pointer_to_relocations",
offset: 24,
size: 4,
data_type: "hex",
description: "重定位表的偏移",
},
pointer_to_linenumbers: {
name: "pointer_to_linenumbers",
offset: 28,
size: 4,
data_type: "hex",
description: "行号表的偏移",
},
number_of_relocations: {
name: "number_of_relocations",
offset: 32,
size: 2,
data_type: "hex",
description: "重定位表的数量",
},
number_of_linenumbers: {
name: "number_of_linenumbers",
offset: 34,
size: 2,
data_type: "hex",
description: "行号表的数量",
},
characteristics: {
name: "characteristics",
offset: 36,
size: 4,
data_type: "hex",
description: "属性",
},
};
// 节区头大小
const sectionHeaderSize = 40;
export default function SectionHeaders() {
const dataTemplate: DataTemplateInterface = {
export default function SectionHeaders() {
const [data, setData] = useState([]);
const command = "command_get_pe_data_section_headers";
/**
pub name: [u8; 8],
pub virtual_size: u32,
pub virtual_address: u32,
pub size_of_raw_data: u32,
pub pointer_to_raw_data: u32,
pub pointer_to_relocations: u32,
pub pointer_to_linenumbers: u32,
pub number_of_relocations: u16,
pub number_of_linenumbers: u16,
pub characteristics: SectionCharacteristics,
*/
};
const command = "command_get_pe_data_optional_header";
const columns = [
{
title: "节区名(Byte[8])",
title: "字段名",
dataIndex: "name",
key: "name",
},
{
title: "虚拟大小",
title: "偏移",
dataIndex: "offset",
key: "offset",
hexSwitch: true,
@ -51,11 +115,39 @@ import NodeTableComponent, {
key: "description",
},
];
return (
<NodeTableComponent
dataTemplate={dataTemplate}
columns={columns as any}
></NodeTableComponent>
);
}
const formatDataHandler = (data: any) => {
const { base_offset } = data;
return (
data?.fields?.map((item: any, index: number) => {
return {
base_offset: base_offset + index * sectionHeaderSize,
fields: { ...item },
};
}) || []
);
};
useEffect(() => {
invoke(command).then((res) => {
setData(formatDataHandler(res));
});
}, []);
console.log("yhyy", data);
return (
<Flex className={styles.content}>
{data.map((item, index) => {
return (
<div className={styles.tableItem}>
<NodeTableComponent
key={index}
dataTemplate={dataTemplate}
defaultData={item}
columns={columns as any}
/>
</div>
);
})}
</Flex>
);
}

View File

@ -9,6 +9,7 @@ import SiderTree from "../components/side_tree/SideTree";
import DosHeader from "../components/DosHeader/DosHeader";
import NtHeader from "../components/NTHeader/NTHeader";
import FileHeader from "../components/FileHeader/FileHeader";
import SectionHeaders from "../components/SectionHeaders/SectionHeaders";
import OptionalHeader from "../components/OptionalHeader/OptionalHeader";
import { open } from "@tauri-apps/plugin-dialog";
@ -17,6 +18,7 @@ const SelectNodeMap = {
nt_header: <NtHeader />,
file_header: <FileHeader />,
optional_header: <OptionalHeader />,
section_header: <SectionHeaders />,
};
export default function MainPage() {