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()?;
|
||||
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_file_header,
|
||||
commands::command_get_pe_data_optional_header,
|
||||
commands::command_get_pe_data_section_headers,
|
||||
commands::set_complete,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
@ -81,4 +80,24 @@ pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError
|
||||
is_64_bit,
|
||||
};
|
||||
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;
|
||||
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(() => {
|
||||
// // 请求数据
|
||||
|
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,61 +1,153 @@
|
||||
import NodeTableComponent, {
|
||||
DataTemplateInterface,
|
||||
} from "../NodeTableComponent/NodeTableComponent";
|
||||
|
||||
export default function SectionHeaders() {
|
||||
const dataTemplate: DataTemplateInterface = {
|
||||
|
||||
DataTemplateInterface,
|
||||
} 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 [data, setData] = useState([]);
|
||||
|
||||
/**
|
||||
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])",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
},
|
||||
{
|
||||
title: "虚拟大小",
|
||||
dataIndex: "offset",
|
||||
key: "offset",
|
||||
hexSwitch: true,
|
||||
},
|
||||
{
|
||||
title: "大小",
|
||||
dataIndex: "size",
|
||||
key: "size",
|
||||
},
|
||||
{
|
||||
title: "值",
|
||||
dataIndex: "value",
|
||||
key: "value",
|
||||
hexSwitch: true,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
title: "描述信息",
|
||||
dataIndex: "description",
|
||||
key: "description",
|
||||
},
|
||||
];
|
||||
const command = "command_get_pe_data_section_headers";
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "字段名",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
},
|
||||
{
|
||||
title: "偏移",
|
||||
dataIndex: "offset",
|
||||
key: "offset",
|
||||
hexSwitch: true,
|
||||
},
|
||||
{
|
||||
title: "大小",
|
||||
dataIndex: "size",
|
||||
key: "size",
|
||||
},
|
||||
{
|
||||
title: "值",
|
||||
dataIndex: "value",
|
||||
key: "value",
|
||||
hexSwitch: true,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
title: "描述信息",
|
||||
dataIndex: "description",
|
||||
key: "description",
|
||||
},
|
||||
];
|
||||
|
||||
const formatDataHandler = (data: any) => {
|
||||
const { base_offset } = data;
|
||||
return (
|
||||
<NodeTableComponent
|
||||
dataTemplate={dataTemplate}
|
||||
columns={columns as any}
|
||||
></NodeTableComponent>
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user