feat: dos header的读取写完了。
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
use thiserror;
|
||||
|
||||
use crate::pe_parse::error::{self, PEParseError};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum AppError {
|
||||
#[error(transparent)]
|
||||
@@ -8,6 +10,9 @@ pub enum AppError {
|
||||
// 未打开文件映射
|
||||
#[error("文件未打开!")]
|
||||
NoFileOpened,
|
||||
|
||||
#[error(transparent)]
|
||||
PeParseError(#[from] PEParseError),
|
||||
}
|
||||
|
||||
impl serde::Serialize for AppError {
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
use crate::{app_error::AppError, services};
|
||||
use serde::Serialize;
|
||||
use crate::{
|
||||
app_error::AppError,
|
||||
pe_parse::{header::ImageDosHeader, pe::PE},
|
||||
services::{self, GLOBAL_FILE_DATA},
|
||||
};
|
||||
use serde::{ser::SerializeStruct, Serialize, Serializer};
|
||||
use serde_json::Value;
|
||||
#[tauri::command]
|
||||
pub fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
}
|
||||
|
||||
macro_rules! offset_of {
|
||||
($base:expr, $field:ident) => {
|
||||
(&$base.$field as *const _ as usize) - ($base as *const _ as usize)
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct PeNodeTreeData {
|
||||
title: String,
|
||||
@@ -14,8 +26,8 @@ pub struct PeNodeTreeData {
|
||||
// TODO: 获取PE节点树的JSON数据
|
||||
#[tauri::command]
|
||||
pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppError> {
|
||||
// 1. 如果全局内存映射句柄为空,则返回错误
|
||||
if unsafe { services::GLOBAL_MEMMAP_HANDLE.is_none() } {
|
||||
// 1. 如果没有打开文件,则返回错误
|
||||
if GLOBAL_FILE_DATA.lock().unwrap().is_none() {
|
||||
return Err(AppError::NoFileOpened);
|
||||
}
|
||||
// 从文件路径中获取文件名
|
||||
@@ -26,28 +38,28 @@ pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppEr
|
||||
};
|
||||
let result = PeNodeTreeData {
|
||||
title: format!("文件: {}", file_name),
|
||||
key: "fileName".to_string(),
|
||||
key: "file_name".to_string(),
|
||||
children: vec![
|
||||
PeNodeTreeData {
|
||||
title: "DOS 头部".to_string(),
|
||||
key: "DOS Header".to_string(),
|
||||
key: "dos_header".to_string(),
|
||||
children: vec![], // 空数组表示没有子节点
|
||||
},
|
||||
PeNodeTreeData {
|
||||
title: "NT 头部".to_string(),
|
||||
key: "NT Headers".to_string(),
|
||||
key: "nt_header".to_string(),
|
||||
children: vec![
|
||||
PeNodeTreeData {
|
||||
title: "文件头部".to_string(),
|
||||
key: "File Header".to_string(),
|
||||
key: "file_header".to_string(),
|
||||
children: vec![],
|
||||
},
|
||||
PeNodeTreeData {
|
||||
title: "可选头部".to_string(),
|
||||
key: "Optional Header".to_string(),
|
||||
key: "optional_header".to_string(),
|
||||
children: vec![PeNodeTreeData {
|
||||
title: "数据目录".to_string(),
|
||||
key: "Data Directories".to_string(),
|
||||
key: "data_directories".to_string(),
|
||||
children: vec![],
|
||||
}],
|
||||
},
|
||||
@@ -55,7 +67,7 @@ pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppEr
|
||||
},
|
||||
PeNodeTreeData {
|
||||
title: "节区头部".to_string(),
|
||||
key: "Section Headers".to_string(),
|
||||
key: "section_header".to_string(),
|
||||
children: vec![],
|
||||
},
|
||||
],
|
||||
@@ -66,9 +78,276 @@ pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppEr
|
||||
// 命令,打开文件
|
||||
#[tauri::command]
|
||||
pub fn command_open_file(file_path: &str) -> Result<(), AppError> {
|
||||
let mmap = Some(services::file::mmap_mut_file(file_path)?);
|
||||
// 将内存clone到Vec中
|
||||
let mmap = mmap.as_ref().unwrap();
|
||||
let mmap = mmap.to_vec();
|
||||
*services::GLOBAL_FILE_DATA.lock().unwrap() = Some(services::PeData(mmap));
|
||||
unsafe {
|
||||
services::GLOBAL_MEMMAP_HANDLE = Some(services::file::mmap_mut_file(file_path)?);
|
||||
services::GLOBAL_FILE_PATH = Some(file_path.to_string());
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Serialize, Default)]
|
||||
pub struct ResponseDOSHeaderData {
|
||||
name: String,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
field_type: String,
|
||||
value: Option<String>,
|
||||
children: Option<Vec<ResponseDOSHeaderData>>,
|
||||
}
|
||||
|
||||
fn serialize_field<S>(
|
||||
state: &mut S,
|
||||
name: &'static str,
|
||||
value: Option<String>,
|
||||
size: usize,
|
||||
field_type: &str,
|
||||
offset: usize,
|
||||
children: Option<Vec<ResponseDOSHeaderData>>,
|
||||
) -> Result<(), S::Error>
|
||||
where
|
||||
S: serde::ser::SerializeStruct,
|
||||
{
|
||||
state.serialize_field(
|
||||
name,
|
||||
&ResponseDOSHeaderData {
|
||||
name: name.to_string(),
|
||||
value,
|
||||
size,
|
||||
field_type: field_type.to_string(),
|
||||
offset,
|
||||
children,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
impl Serialize for ImageDosHeader {
|
||||
fn serialize<S>(
|
||||
&self,
|
||||
serializer: S,
|
||||
) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("ResponseDOSHeaderData", 19)?;
|
||||
// 序列化每个字段
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_magic",
|
||||
Some(format!("0x{:04X}", self.e_magic)),
|
||||
std::mem::size_of_val(&self.e_magic),
|
||||
"u16",
|
||||
offset_of!(self, e_magic),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_cblp",
|
||||
Some(format!("0x{:04X}", self.e_cblp)),
|
||||
std::mem::size_of_val(&self.e_cblp),
|
||||
"u16",
|
||||
offset_of!(self, e_cblp),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_cp",
|
||||
Some(format!("0x{:04X}", self.e_cp)),
|
||||
std::mem::size_of_val(&self.e_cp),
|
||||
"u16",
|
||||
offset_of!(self, e_cp),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_crlc",
|
||||
Some(format!("0x{:04X}", self.e_crlc)),
|
||||
std::mem::size_of_val(&self.e_crlc),
|
||||
"u16",
|
||||
offset_of!(self, e_crlc),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_cparhdr",
|
||||
Some(format!("0x{:04X}", self.e_cparhdr)),
|
||||
std::mem::size_of_val(&self.e_cparhdr),
|
||||
"u16",
|
||||
offset_of!(self, e_cparhdr),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_minalloc",
|
||||
Some(format!("0x{:04X}", self.e_minalloc)),
|
||||
std::mem::size_of_val(&self.e_minalloc),
|
||||
"u16",
|
||||
offset_of!(self, e_minalloc),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_maxalloc",
|
||||
Some(format!("0x{:04X}", self.e_maxalloc)),
|
||||
std::mem::size_of_val(&self.e_maxalloc),
|
||||
"u16",
|
||||
offset_of!(self, e_maxalloc),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_ss",
|
||||
Some(format!("0x{:04X}", self.e_ss)),
|
||||
std::mem::size_of_val(&self.e_ss),
|
||||
"u16",
|
||||
offset_of!(self, e_ss),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_sp",
|
||||
Some(format!("0x{:04X}", self.e_sp)),
|
||||
std::mem::size_of_val(&self.e_sp),
|
||||
"u16",
|
||||
offset_of!(self, e_sp),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_csum",
|
||||
Some(format!("0x{:04X}", self.e_csum)),
|
||||
std::mem::size_of_val(&self.e_csum),
|
||||
"u16",
|
||||
offset_of!(self, e_csum),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_ip",
|
||||
Some(format!("0x{:04X}", self.e_ip)),
|
||||
std::mem::size_of_val(&self.e_ip),
|
||||
"u16",
|
||||
offset_of!(self, e_ip),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_cs",
|
||||
Some(format!("0x{:04X}", self.e_cs)),
|
||||
std::mem::size_of_val(&self.e_cs),
|
||||
"u16",
|
||||
offset_of!(self, e_cs),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_lfarlc",
|
||||
Some(format!("0x{:04X}", self.e_lfarlc)),
|
||||
std::mem::size_of_val(&self.e_lfarlc),
|
||||
"u16",
|
||||
offset_of!(self, e_lfarlc),
|
||||
None,
|
||||
)?;
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_ovno",
|
||||
Some(format!("0x{:04X}", self.e_ovno)),
|
||||
std::mem::size_of_val(&self.e_ovno),
|
||||
"u16",
|
||||
offset_of!(self, e_ovno),
|
||||
None,
|
||||
)?;
|
||||
|
||||
// e_res 序列化,带 children
|
||||
let mut e_res_children = Vec::new();
|
||||
for (index, value) in self.e_res.iter().enumerate() {
|
||||
e_res_children.push(ResponseDOSHeaderData {
|
||||
name: format!("e_res[{}]", index),
|
||||
value: Some(format!("0x{:04X}", value)),
|
||||
size: std::mem::size_of_val(value),
|
||||
field_type: "u16".to_string(),
|
||||
offset: offset_of!(self, e_res) + index * std::mem::size_of::<u16>(),
|
||||
children: None,
|
||||
});
|
||||
}
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_res",
|
||||
None,
|
||||
std::mem::size_of_val(&self.e_res),
|
||||
"[u16;4]",
|
||||
offset_of!(self, e_res),
|
||||
Some(e_res_children),
|
||||
)?;
|
||||
// e_oemid 序列化
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_oemid",
|
||||
Some(format!("0x{:04X}", self.e_oemid)),
|
||||
std::mem::size_of_val(&self.e_oemid),
|
||||
"u16",
|
||||
offset_of!(self, e_oemid),
|
||||
None,
|
||||
)?;
|
||||
|
||||
// e_oeminfo 序列化
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_oeminfo",
|
||||
Some(format!("0x{:04X}", self.e_oeminfo)),
|
||||
std::mem::size_of_val(&self.e_oeminfo),
|
||||
"u16",
|
||||
offset_of!(self, e_oeminfo),
|
||||
None,
|
||||
)?;
|
||||
|
||||
|
||||
|
||||
// e_res2 序列化
|
||||
let mut e_res2_children = Vec::new();
|
||||
for (index, value) in self.e_res2.iter().enumerate() {
|
||||
e_res2_children.push(ResponseDOSHeaderData {
|
||||
name: format!("e_res2[{}]", index),
|
||||
value: Some(format!("0x{:04X}", value)),
|
||||
size: std::mem::size_of_val(value),
|
||||
field_type: "u16".to_string(),
|
||||
offset: offset_of!(self, e_res2) + index * std::mem::size_of::<u16>(),
|
||||
children: None,
|
||||
});
|
||||
}
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_res2",
|
||||
None,
|
||||
std::mem::size_of_val(&self.e_res2),
|
||||
"[u16;10]",
|
||||
offset_of!(self, e_res2),
|
||||
Some(e_res2_children),
|
||||
)?;
|
||||
|
||||
// e_lfanew 序列化
|
||||
serialize_field(
|
||||
&mut state,
|
||||
"e_lfanew",
|
||||
Some(format!("0x{:04X}", self.e_lfanew.0)), // 假设 Offset 是简单的 tuple struct
|
||||
std::mem::size_of_val(&self.e_lfanew),
|
||||
"Offset",
|
||||
offset_of!(self, e_lfanew),
|
||||
None,
|
||||
)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
// 命令,获取DOS头数据
|
||||
#[tauri::command]
|
||||
pub fn command_get_pe_data_dos_header() -> Result<ImageDosHeader, AppError> {
|
||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
||||
let file_data = binding.as_ref().unwrap();
|
||||
let dos_header = file_data.get_dos_header()?;
|
||||
Ok(dos_header.clone())
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ pub mod services;
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::command_open_file,
|
||||
commands::command_get_file_pe_node_tree_data
|
||||
commands::command_get_file_pe_node_tree_data,
|
||||
commands::command_get_pe_data_dos_header,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
|
||||
fn main() {
|
||||
test_tauri_lib::run()
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ pub enum PEParseError {
|
||||
#[error("Invalid optional header size")]
|
||||
InvalidOptionalSize,
|
||||
#[error("解析超出了文件范围")]
|
||||
OutOfBounds
|
||||
}
|
||||
OutOfBounds,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use super::types::*;
|
||||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ImageDosHeader {
|
||||
pub e_magic: u16, // Magic number 固定值 0x5A4D
|
||||
pub e_cblp: u16,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod error;
|
||||
pub mod header;
|
||||
pub mod types;
|
||||
pub mod pe;
|
||||
pub mod error;
|
||||
pub mod types;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use super::{error::PEParseError, header::*};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||
/// Get a reference to a type at a given offset.
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#[repr(C)]
|
||||
pub struct Offset(pub u32);
|
||||
use serde::Serialize;
|
||||
|
||||
pub struct RVA(pub u32);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct Offset(pub u32);
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct RVA(pub u32);
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use memmap::*;
|
||||
|
||||
// TODO: 打开文件,并将文件映射到内存
|
||||
pub fn mmap_mut_file(file_path: &str) -> Result<MmapMut, std::io::Error> {
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(file_path)?;
|
||||
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
||||
let file = std::fs::OpenOptions::new().read(true).open(file_path)?;
|
||||
|
||||
unsafe {
|
||||
MmapOptions::new()
|
||||
.map_mut(&file)
|
||||
.map(&file)
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
use memmap::MmapMut;
|
||||
use memmap::{Mmap, MmapMut};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
use crate::pe_parse::pe::PE;
|
||||
pub mod file;
|
||||
|
||||
// 映射到内存的文件句柄
|
||||
pub static mut GLOBAL_MEMMAP_HANDLE: Option<MmapMut> = None;
|
||||
|
||||
// 全局文件路径
|
||||
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
||||
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
||||
|
||||
pub(crate) struct PeData(pub Vec<u8>);
|
||||
// 实现Deref
|
||||
impl Deref for PeData {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
// 实现DerefMut
|
||||
impl DerefMut for PeData {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
impl PE for PeData {}
|
||||
// 文件的内存映射clone
|
||||
pub static GLOBAL_FILE_DATA: Mutex<Option<PeData>> = Mutex::new(None);
|
||||
|
||||
Reference in New Issue
Block a user