feat: 完成后端状态的优化
This commit is contained in:
parent
175189bbdf
commit
bfe54cae1f
@ -1,6 +1,6 @@
|
|||||||
use thiserror;
|
use thiserror;
|
||||||
|
|
||||||
use crate::pe_parse::error::{self, PEParseError};
|
use crate::pe_parse::error::PEParseError;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum AppError {
|
pub enum AppError {
|
||||||
@ -11,8 +11,16 @@ pub enum AppError {
|
|||||||
#[error("文件未打开!")]
|
#[error("文件未打开!")]
|
||||||
NoFileOpened,
|
NoFileOpened,
|
||||||
|
|
||||||
|
// 文件没有初始化打开
|
||||||
|
#[error("文件未初始化打开!")]
|
||||||
|
NotInitOpenFile,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
PeParseError(#[from] PEParseError),
|
PeParseError(#[from] PEParseError),
|
||||||
|
|
||||||
|
/// 初始化打开文件失败
|
||||||
|
#[error("初始化打开文件失败!: {0}")]
|
||||||
|
InitOpenFileFailed(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::Serialize for AppError {
|
impl serde::Serialize for AppError {
|
||||||
|
30
src-tauri/src/app_state.rs
Normal file
30
src-tauri/src/app_state.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use memmap2::Mmap;
|
||||||
|
use crate::app_error::AppError;
|
||||||
|
use crate::{pe_parse::pe::ReadOnlyPE, services::file};
|
||||||
|
|
||||||
|
/// 应用的状态结构体
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct AppState {
|
||||||
|
/// 文件路径
|
||||||
|
pub file_path: Option<String>,
|
||||||
|
/// 文件Mmap的只读内存映射
|
||||||
|
mmap: Option<Mmap>,
|
||||||
|
/// 文件是否是64位
|
||||||
|
pub is_64_bit: Option<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState {
|
||||||
|
/// 初始化打开文件
|
||||||
|
pub fn init_open_file(&mut self, file_path: &str) -> Result<(), AppError> {
|
||||||
|
self.file_path = Some(file_path.to_string());
|
||||||
|
self.mmap = Some(file::mmap_mut_file(file_path)?);
|
||||||
|
// 读取PE格式来判断是否是64位
|
||||||
|
let mmap: &Mmap = self.mmap.as_ref().unwrap();
|
||||||
|
self.is_64_bit = Some(mmap.is_64_bit()?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// 获取文件内存映射
|
||||||
|
pub fn get_mmap_ref(&self) -> Result<&Mmap, AppError> {
|
||||||
|
self.mmap.as_ref().ok_or(AppError::NoFileOpened)
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
pe_parse::pe::PE,
|
app_state::AppState,
|
||||||
services::{self, file::*, GLOBAL_FILE_DATA},
|
pe_parse::pe::ReadOnlyPE,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tauri::{AppHandle, Manager};
|
use serde_json::{json, Value};
|
||||||
|
use tauri::{AppHandle, Manager, State};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct PeNodeTreeData {
|
pub struct PeNodeTreeData {
|
||||||
@ -12,7 +15,7 @@ pub struct PeNodeTreeData {
|
|||||||
key: String,
|
key: String,
|
||||||
children: Vec<PeNodeTreeData>,
|
children: Vec<PeNodeTreeData>,
|
||||||
}
|
}
|
||||||
// set_complete
|
/// 设置闪屏的切换
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn set_complete(app: AppHandle) -> Result<(), AppError> {
|
pub fn set_complete(app: AppHandle) -> Result<(), AppError> {
|
||||||
let splash_window = app.get_webview_window("splashscreen");
|
let splash_window = app.get_webview_window("splashscreen");
|
||||||
@ -26,18 +29,37 @@ pub fn set_complete(app: AppHandle) -> Result<(), AppError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 命令,打开文件
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppError> {
|
pub fn command_open_file(
|
||||||
// 1. 如果没有打开文件,则返回错误
|
file_path: &str,
|
||||||
if GLOBAL_FILE_DATA.lock().unwrap().is_none() {
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
return Err(AppError::NoFileOpened);
|
) -> Result<(), AppError> {
|
||||||
|
app_state
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.init_open_file(file_path)
|
||||||
|
.map_err(|e| AppError::InitOpenFileFailed(e.to_string()))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
// 从文件路径中获取文件名
|
|
||||||
let file_name: &str = unsafe {
|
#[tauri::command]
|
||||||
let file_path = services::GLOBAL_FILE_PATH.as_ref().unwrap();
|
pub fn command_get_file_pe_node_tree_data(
|
||||||
let file_name = std::path::Path::new(file_path).file_name().unwrap();
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
file_name.to_str().unwrap()
|
) -> Result<Vec<PeNodeTreeData>, AppError> {
|
||||||
};
|
let app_state = app_state.lock().unwrap();
|
||||||
|
|
||||||
|
// 如果没有打开文件,则返回错误
|
||||||
|
if app_state.file_path.is_none() {
|
||||||
|
return Err(AppError::NotInitOpenFile);
|
||||||
|
}
|
||||||
|
let file_path = app_state.file_path.as_ref().unwrap();
|
||||||
|
let file_name = std::path::Path::new(file_path)
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let result = PeNodeTreeData {
|
let result = PeNodeTreeData {
|
||||||
title: format!("文件: {}", file_name),
|
title: format!("文件: {}", file_name),
|
||||||
key: "file_name".to_string(),
|
key: "file_name".to_string(),
|
||||||
@ -77,65 +99,73 @@ pub fn command_get_file_pe_node_tree_data() -> Result<Vec<PeNodeTreeData>, AppEr
|
|||||||
Ok(vec![result])
|
Ok(vec![result])
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令,打开文件
|
|
||||||
#[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_FILE_PATH = Some(file_path.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断文件是否是64位
|
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
|
||||||
let file_data = binding.as_ref().unwrap();
|
|
||||||
let is64bit = file_data.is_64_bit()?;
|
|
||||||
unsafe {
|
|
||||||
services::GLOBAL_IS_64_BIT = Some(is64bit);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 命令,获取DOS头数据
|
// 命令,获取DOS头数据
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_pe_data_dos_header() -> Result<ResponseDOSHeaderData, AppError> {
|
pub fn command_get_pe_data_dos_header(
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
let file_data = binding.as_ref().unwrap();
|
) -> Result<Value, AppError> {
|
||||||
let dos_header = file_data.get_dos_header()?;
|
let app_state = app_state.lock().unwrap();
|
||||||
let result = ResponseDOSHeaderData {
|
let mmap = app_state.get_mmap_ref()?;
|
||||||
fields: dos_header.clone(),
|
let dos_header = mmap.get_dos_header()?;
|
||||||
base_offset: 0,
|
Ok(json!({
|
||||||
};
|
"fields": dos_header.clone(),
|
||||||
Ok(result)
|
"base_offset": 0,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令,获取NT头数据
|
// 命令,获取NT头数据
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_pe_data_nt_header() -> Result<ResponseNTHeaderData, AppError> {
|
pub fn command_get_pe_data_nt_header(
|
||||||
let result = get_nt_headers_data()?;
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
Ok(result)
|
) -> Result<Value, AppError> {
|
||||||
|
let app_state = app_state.lock().unwrap();
|
||||||
|
let mmap = app_state.get_mmap_ref()?;
|
||||||
|
let nt_header: crate::pe_parse::header::ImageNTHeader = mmap.get_nt_header()?;
|
||||||
|
let nt_offset = mmap.get_nt_headers_offset()?;
|
||||||
|
Ok(json! ({
|
||||||
|
"fields": nt_header,
|
||||||
|
"base_offset": nt_offset,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令,获取文件头数据
|
// 命令,获取文件头数据
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_pe_data_file_header() -> Result<ResponseFileHeaderData, AppError> {
|
pub fn command_get_pe_data_file_header(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> {
|
||||||
let result = services::file::get_file_header_data()?;
|
let app_state = app_state.lock().unwrap();
|
||||||
Ok(result)
|
let mmap = app_state.get_mmap_ref()?;
|
||||||
|
let file_header = mmap.get_file_header()?;
|
||||||
|
let file_header_offset = mmap.get_file_header_offset()?;
|
||||||
|
Ok(json!({
|
||||||
|
"fields": file_header.clone(),
|
||||||
|
"base_offset": file_header_offset,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令,获取可选头数据
|
// 命令,获取可选头数据
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_pe_data_optional_header() -> Result<ResponseOptionalHeaderData, AppError> {
|
pub fn command_get_pe_data_optional_header(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> {
|
||||||
let result = services::file::get_optional_header_data()?;
|
let app_state = app_state.lock().unwrap();
|
||||||
Ok(result)
|
let mmap = app_state.get_mmap_ref()?;
|
||||||
|
let optional_header = mmap.get_optional_header()?;
|
||||||
|
let optional_header_offset = mmap.get_optional_header_offset()?;
|
||||||
|
let is_64_bit = mmap.is_64_bit()?;
|
||||||
|
Ok(json!({
|
||||||
|
"fields": optional_header.clone(),
|
||||||
|
"base_offset": optional_header_offset,
|
||||||
|
"is_64_bit": is_64_bit,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令,获取节区头数据
|
// 命令,获取节区头数据
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn command_get_pe_data_section_headers() -> Result<ResponseSectionHeaderData, AppError> {
|
pub fn command_get_pe_data_section_headers(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> {
|
||||||
let result = services::file::get_section_header_data()?;
|
let app_state = app_state.lock().unwrap();
|
||||||
Ok(result)
|
let mmap = app_state.get_mmap_ref()?;
|
||||||
|
let section_headers = mmap.get_section_headers()?;
|
||||||
|
let section_headers_offset = mmap.get_section_headers_offset()?;
|
||||||
|
let vec_section_headers = section_headers.to_vec();
|
||||||
|
Ok(json!({
|
||||||
|
"fields": vec_section_headers,
|
||||||
|
"base_offset": section_headers_offset,
|
||||||
|
}))
|
||||||
}
|
}
|
@ -1,8 +1,13 @@
|
|||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use tauri::Manager;
|
||||||
|
|
||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
pub mod app_error;
|
pub mod app_error;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod pe_parse;
|
pub mod pe_parse;
|
||||||
pub mod services;
|
pub mod services;
|
||||||
|
pub mod app_state;
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
@ -19,6 +24,10 @@ pub fn run() {
|
|||||||
commands::command_get_pe_data_section_headers,
|
commands::command_get_pe_data_section_headers,
|
||||||
commands::set_complete,
|
commands::set_complete,
|
||||||
])
|
])
|
||||||
|
.setup(|app| {
|
||||||
|
app.manage(Mutex::new(app_state::AppState::default()));
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub struct ImageDosHeader {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, Serialize)]
|
#[derive(Debug, Clone, Copy, Serialize)]
|
||||||
pub struct ImageNTHeaders32 {
|
pub struct ImageNTHeader32 {
|
||||||
pub signature: u32,
|
pub signature: u32,
|
||||||
pub file_header: ImageFileHeader,
|
pub file_header: ImageFileHeader,
|
||||||
pub optional_header: ImageOptionalHeader32,
|
pub optional_header: ImageOptionalHeader32,
|
||||||
@ -36,7 +36,7 @@ pub struct ImageNTHeaders32 {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, Serialize)]
|
#[derive(Debug, Clone, Copy, Serialize)]
|
||||||
pub struct ImageNTHeaders64 {
|
pub struct ImageNTHeader64 {
|
||||||
pub signature: u32,
|
pub signature: u32,
|
||||||
pub file_header: ImageFileHeader,
|
pub file_header: ImageFileHeader,
|
||||||
pub optional_header: ImageOptionalHeader64,
|
pub optional_header: ImageOptionalHeader64,
|
||||||
@ -44,9 +44,9 @@ pub struct ImageNTHeaders64 {
|
|||||||
|
|
||||||
#[derive(Serialize, Clone, Copy)]
|
#[derive(Serialize, Clone, Copy)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum ImageNTHeaders{
|
pub enum ImageNTHeader{
|
||||||
NTHeaders32(ImageNTHeaders32),
|
NTHeader32(ImageNTHeader32),
|
||||||
NTHeaders64(ImageNTHeaders64),
|
NTHeader64(ImageNTHeader64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{error::PEParseError, header::*};
|
use super::{error::PEParseError, header::*};
|
||||||
use std::{ops::{Deref, DerefMut}, option};
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
|
||||||
/// Get a reference to a type at a given offset.
|
/// Get a reference to a type at a given offset.
|
||||||
fn get_ref<T>(&self, offset: usize) -> Result<&T, PEParseError> {
|
fn get_ref<T>(&self, offset: usize) -> Result<&T, PEParseError> {
|
||||||
let len = std::mem::size_of::<T>();
|
let len = std::mem::size_of::<T>();
|
||||||
@ -12,16 +12,6 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(unsafe { &*ptr })
|
Ok(unsafe { &*ptr })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to a type at a given offset.
|
|
||||||
fn get_mut<T>(&mut self, offset: usize) -> Result<&mut T, PEParseError> {
|
|
||||||
let len = std::mem::size_of::<T>();
|
|
||||||
if offset + len > self.len() {
|
|
||||||
return Err(PEParseError::OutOfBounds);
|
|
||||||
}
|
|
||||||
let ptr = self.as_mut_ptr().wrapping_offset(offset as isize) as *mut T;
|
|
||||||
Ok(unsafe { &mut *ptr })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是64位还是32位
|
// 判断是64位还是32位
|
||||||
fn is_64_bit(&self) -> Result<bool, PEParseError> {
|
fn is_64_bit(&self) -> Result<bool, PEParseError> {
|
||||||
// 先以32位加载可选头,通过可选头的Magic字段判断
|
// 先以32位加载可选头,通过可选头的Magic字段判断
|
||||||
@ -30,36 +20,27 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(is_64_bit)
|
Ok(is_64_bit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Get the DOS header without verifying its contents.
|
/// Get the DOS header without verifying its contents.
|
||||||
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
||||||
let result = self.get_ref::<ImageDosHeader>(0)?;
|
let result = self.get_ref::<ImageDosHeader>(0)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
/// Get the DOS header without mutating its contents.
|
|
||||||
fn get_dos_header_mut(&mut self) -> Result<&mut ImageDosHeader, PEParseError> {
|
|
||||||
let result = self.get_mut::<ImageDosHeader>(0)?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fn get_nt_header32(&self) -> Result<&ImageNTHeader32, PEParseError> {
|
||||||
|
|
||||||
fn get_nt_headers32(&self) -> Result<&ImageNTHeaders32, PEParseError> {
|
|
||||||
let nt_offset = self.get_nt_headers_offset()?;
|
let nt_offset = self.get_nt_headers_offset()?;
|
||||||
let result = self.get_ref::<ImageNTHeaders32>(nt_offset)?;
|
let result = self.get_ref::<ImageNTHeader32>(nt_offset)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
fn get_nt_headers64(&self) -> Result<&ImageNTHeaders64, PEParseError> {
|
fn get_nt_header64(&self) -> Result<&ImageNTHeader64, PEParseError> {
|
||||||
let nt_offset = self.get_nt_headers_offset()?;
|
let nt_offset = self.get_nt_headers_offset()?;
|
||||||
let result = self.get_ref::<ImageNTHeaders64>(nt_offset)?;
|
let result = self.get_ref::<ImageNTHeader64>(nt_offset)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
fn get_nt_headers(&self) -> Result<ImageNTHeaders, PEParseError> {
|
fn get_nt_header(&self) -> Result<ImageNTHeader, PEParseError> {
|
||||||
let is_64_bit = self.is_64_bit()?;
|
let is_64_bit = self.is_64_bit()?;
|
||||||
let result = match is_64_bit {
|
let result = match is_64_bit {
|
||||||
true => ImageNTHeaders::NTHeaders64(*self.get_nt_headers64()?),
|
true => ImageNTHeader::NTHeader64(*self.get_nt_header64()?),
|
||||||
false => ImageNTHeaders::NTHeaders32(*self.get_nt_headers32()?),
|
false => ImageNTHeader::NTHeader32(*self.get_nt_header32()?),
|
||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -71,13 +52,6 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(nt_offset)
|
Ok(nt_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the NT headers without mutating its contents.
|
|
||||||
fn get_nt_headers_mut(&mut self) -> Result<&mut ImageNTHeaders32, PEParseError> {
|
|
||||||
let nt_offset = self.get_nt_headers_offset()?;
|
|
||||||
let result = self.get_mut::<ImageNTHeaders32>(nt_offset)?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取文件头的偏移
|
// 获取文件头的偏移
|
||||||
fn get_file_header_offset(&self) -> Result<usize, PEParseError> {
|
fn get_file_header_offset(&self) -> Result<usize, PEParseError> {
|
||||||
// 1. 获取nt头偏移
|
// 1. 获取nt头偏移
|
||||||
@ -93,12 +67,6 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
let result = self.get_ref::<ImageFileHeader>(file_header_offset)?;
|
let result = self.get_ref::<ImageFileHeader>(file_header_offset)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
// 获取文件头数据
|
|
||||||
fn get_file_header_mut(&mut self) -> Result<&mut ImageFileHeader, PEParseError> {
|
|
||||||
let file_header_offset = self.get_file_header_offset()?;
|
|
||||||
let result = self.get_mut::<ImageFileHeader>(file_header_offset)?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取节区数量
|
// 获取节区数量
|
||||||
fn get_number_of_sections(&self) -> Result<usize, PEParseError> {
|
fn get_number_of_sections(&self) -> Result<usize, PEParseError> {
|
||||||
@ -147,7 +115,8 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
||||||
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)
|
Ok(section_header_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +128,10 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
let section_header_offset = self.get_section_headers_offset()?;
|
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;
|
||||||
let result = std::slice::from_raw_parts(ptr, number_of_sections);
|
let result = std::slice::from_raw_parts(ptr, number_of_sections);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
@ -1,103 +1,11 @@
|
|||||||
use memmap2::*;
|
use memmap2::*;
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
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};
|
|
||||||
|
|
||||||
|
/// 以只读的方式创建文件映射
|
||||||
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
||||||
let file = std::fs::OpenOptions::new().read(true).open(file_path)?;
|
let file = std::fs::OpenOptions::new().read(true).open(file_path)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
MmapOptions::new()
|
MmapOptions::new()
|
||||||
.map(&file)
|
.map(&file)
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct ResponseDOSHeaderData {
|
|
||||||
pub fields: ImageDosHeader,
|
|
||||||
pub base_offset: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct ResponseNTHeaderData {
|
|
||||||
fields: ImageNTHeaders,
|
|
||||||
base_offset: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_nt_headers_data<'a>() -> Result<ResponseNTHeaderData, AppError> {
|
|
||||||
// pub static GLOBAL_FILE_DATA: Mutex<Option<PeData>> = Mutex::new(None);
|
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
|
||||||
// `binding` does not live long enough borrowed value does not live long enough
|
|
||||||
let file_data = binding.as_ref().unwrap();
|
|
||||||
let nt_header_enmu= file_data.get_nt_headers()?;
|
|
||||||
let nt_offset = file_data.get_nt_headers_offset()?;
|
|
||||||
let result = ResponseNTHeaderData {
|
|
||||||
fields: nt_header_enmu,
|
|
||||||
base_offset: nt_offset,
|
|
||||||
};
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取文件头数据
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct ResponseFileHeaderData {
|
|
||||||
pub fields: ImageFileHeader,
|
|
||||||
pub base_offset: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_file_header_data() -> Result<ResponseFileHeaderData, AppError> {
|
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
|
||||||
let file_data = binding.as_ref().unwrap();
|
|
||||||
let file_header = file_data.get_file_header()?;
|
|
||||||
let file_header_offset = file_data.get_file_header_offset()?;
|
|
||||||
let result = ResponseFileHeaderData {
|
|
||||||
fields: file_header.clone(),
|
|
||||||
base_offset: file_header_offset,
|
|
||||||
};
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
// 获取可选头数据
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct ResponseOptionalHeaderData {
|
|
||||||
pub fields: ImageOptionalHeader,
|
|
||||||
pub base_offset: usize,
|
|
||||||
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();
|
|
||||||
let optional_header = file_data.get_optional_header()?;
|
|
||||||
let optional_header_offset = file_data.get_optional_header_offset()?;
|
|
||||||
let is_64_bit = file_data.is_64_bit()?;
|
|
||||||
let result = ResponseOptionalHeaderData {
|
|
||||||
fields: optional_header.clone(),
|
|
||||||
base_offset: optional_header_offset,
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,32 +1,6 @@
|
|||||||
use memmap2::{Mmap, MmapMut};
|
use memmap2::Mmap;
|
||||||
use std::{
|
use crate::pe_parse::pe::ReadOnlyPE;
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
sync::Mutex,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::pe_parse::pe::PE;
|
|
||||||
pub mod file;
|
pub mod file;
|
||||||
|
|
||||||
// 全局文件路径
|
// 为文件映射实现PE结构
|
||||||
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
impl ReadOnlyPE for Mmap {}
|
||||||
// 文件是否是64位
|
|
||||||
pub static mut GLOBAL_IS_64_BIT: Option<bool> = 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);
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"label": "main",
|
"label": "main",
|
||||||
"title": "My CFF",
|
"title": "My CFF",
|
||||||
"width": 1000,
|
"width": 1000,
|
||||||
"height": 800,
|
"height": 600,
|
||||||
"visible": false
|
"visible": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user