feat: 展示节区头
This commit is contained in:
parent
d7038a42d8
commit
175189bbdf
@ -132,3 +132,10 @@ pub fn command_get_pe_data_optional_header() -> Result<ResponseOptionalHeaderDat
|
|||||||
let result = services::file::get_optional_header_data()?;
|
let result = services::file::get_optional_header_data()?;
|
||||||
Ok(result)
|
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)
|
||||||
|
}
|
@ -16,6 +16,7 @@ pub fn run() {
|
|||||||
commands::command_get_pe_data_nt_header,
|
commands::command_get_pe_data_nt_header,
|
||||||
commands::command_get_pe_data_file_header,
|
commands::command_get_pe_data_file_header,
|
||||||
commands::command_get_pe_data_optional_header,
|
commands::command_get_pe_data_optional_header,
|
||||||
|
commands::command_get_pe_data_section_headers,
|
||||||
commands::set_complete,
|
commands::set_complete,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
@ -142,15 +142,21 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(optional_header_offset)
|
Ok(optional_header_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有节区头数据
|
// 获取节区头的偏移
|
||||||
fn get_image_section_headers(&self) -> Result<&[ImageSectionHeader], PEParseError> {
|
fn get_section_headers_offset(&self) -> Result<usize, PEParseError> {
|
||||||
// 1. 获取节区数量
|
|
||||||
let number_of_sections = self.get_number_of_sections()?;
|
|
||||||
// 2. 找到节区头的偏移
|
|
||||||
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
||||||
let optional_header_size = self.get_size_of_optional_header()?;
|
let optional_header_size = self.get_size_of_optional_header()?;
|
||||||
let file_header_offset = self.get_file_header_offset()?;
|
let file_header_offset = self.get_file_header_offset()?;
|
||||||
let section_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>() + optional_header_size;
|
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. 获取节区头数据
|
// 3. 获取节区头数据
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.as_ptr().wrapping_offset(section_header_offset as isize) as *const ImageSectionHeader;
|
let ptr = self.as_ptr().wrapping_offset(section_header_offset as isize) as *const ImageSectionHeader;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use memmap2::*;
|
use memmap2::*;
|
||||||
use serde::Serialize;
|
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};
|
use super::{GLOBAL_FILE_DATA, GLOBAL_IS_64_BIT};
|
||||||
|
|
||||||
@ -68,7 +68,6 @@ pub struct ResponseOptionalHeaderData {
|
|||||||
pub is_64_bit: bool,
|
pub is_64_bit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError> {
|
pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError> {
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
||||||
let file_data = binding.as_ref().unwrap();
|
let file_data = binding.as_ref().unwrap();
|
||||||
@ -82,3 +81,23 @@ pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError
|
|||||||
};
|
};
|
||||||
Ok(result)
|
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)
|
||||||
|
}
|
@ -21,7 +21,7 @@ export interface DataType {
|
|||||||
offset: number;
|
offset: number;
|
||||||
name: string;
|
name: string;
|
||||||
size: number;
|
size: number;
|
||||||
value: number | number[] | null;
|
value?: number | number[] | null;
|
||||||
description?: string;
|
description?: string;
|
||||||
// 枚举值 key:value => value: description
|
// 枚举值 key:value => value: description
|
||||||
enum?: {
|
enum?: {
|
||||||
@ -247,11 +247,20 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
|
|||||||
cloneData[key].children = children;
|
cloneData[key].children = children;
|
||||||
}
|
}
|
||||||
// TODO: 字符数组处理
|
// 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中获需要排序的字段,来进行排序
|
// TODO: 应该从columns中获需要排序的字段,来进行排序
|
||||||
// 如果cloneData的成员中有offset字段,那么需要按照offset排序
|
// 如果cloneData的成员中有offset字段,那么需要按照offset排序
|
||||||
let cloneDataArray = Object.values(cloneData);
|
let cloneDataArray = Object.values(cloneData);
|
||||||
if (cloneDataArray[0].offset) {
|
if (cloneDataArray[0] && cloneDataArray[0].offset) {
|
||||||
cloneDataArray.sort((a, b) => a.offset - b.offset);
|
cloneDataArray.sort((a, b) => a.offset - b.offset);
|
||||||
}
|
}
|
||||||
return cloneDataArray;
|
return cloneDataArray;
|
||||||
@ -259,11 +268,7 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
|
|||||||
|
|
||||||
const formatData = useMemo(() => {
|
const formatData = useMemo(() => {
|
||||||
return handleData(props.defaultData as any);
|
return handleData(props.defaultData as any);
|
||||||
|
}, [props.defaultData]);
|
||||||
}, [props.defaultData])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// // 请求数据
|
// // 请求数据
|
||||||
|
16
src/components/SectionHeaders/SectionHeaders.module.scss
Normal file
16
src/components/SectionHeaders/SectionHeaders.module.scss
Normal 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;
|
||||||
|
}
|
@ -1,34 +1,98 @@
|
|||||||
import NodeTableComponent, {
|
import NodeTableComponent, {
|
||||||
DataTemplateInterface,
|
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() {
|
export default function SectionHeaders() {
|
||||||
const dataTemplate: DataTemplateInterface = {
|
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 = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: "节区名(Byte[8])",
|
title: "字段名",
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
key: "name",
|
key: "name",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "虚拟大小",
|
title: "偏移",
|
||||||
dataIndex: "offset",
|
dataIndex: "offset",
|
||||||
key: "offset",
|
key: "offset",
|
||||||
hexSwitch: true,
|
hexSwitch: true,
|
||||||
@ -51,11 +115,39 @@ import NodeTableComponent, {
|
|||||||
key: "description",
|
key: "description",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const formatDataHandler = (data: any) => {
|
||||||
|
const { base_offset } = data;
|
||||||
return (
|
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
|
<NodeTableComponent
|
||||||
|
key={index}
|
||||||
dataTemplate={dataTemplate}
|
dataTemplate={dataTemplate}
|
||||||
|
defaultData={item}
|
||||||
columns={columns as any}
|
columns={columns as any}
|
||||||
></NodeTableComponent>
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ import SiderTree from "../components/side_tree/SideTree";
|
|||||||
import DosHeader from "../components/DosHeader/DosHeader";
|
import DosHeader from "../components/DosHeader/DosHeader";
|
||||||
import NtHeader from "../components/NTHeader/NTHeader";
|
import NtHeader from "../components/NTHeader/NTHeader";
|
||||||
import FileHeader from "../components/FileHeader/FileHeader";
|
import FileHeader from "../components/FileHeader/FileHeader";
|
||||||
|
import SectionHeaders from "../components/SectionHeaders/SectionHeaders";
|
||||||
import OptionalHeader from "../components/OptionalHeader/OptionalHeader";
|
import OptionalHeader from "../components/OptionalHeader/OptionalHeader";
|
||||||
import { open } from "@tauri-apps/plugin-dialog";
|
import { open } from "@tauri-apps/plugin-dialog";
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ const SelectNodeMap = {
|
|||||||
nt_header: <NtHeader />,
|
nt_header: <NtHeader />,
|
||||||
file_header: <FileHeader />,
|
file_header: <FileHeader />,
|
||||||
optional_header: <OptionalHeader />,
|
optional_header: <OptionalHeader />,
|
||||||
|
section_header: <SectionHeaders />,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MainPage() {
|
export default function MainPage() {
|
||||||
|
Loading…
Reference in New Issue
Block a user