diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0d31a79..85ebeae 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2409,6 +2409,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pe_serialize_proc_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.90", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -3764,6 +3774,7 @@ version = "0.1.0" dependencies = [ "bitflags 2.6.0", "memmap", + "pe_serialize_proc_macro", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 488baee..76a0c2b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,9 +1,9 @@ [package] +authors = ["you"] +description = "A Tauri App" +edition = "2021" name = "test-tauri" version = "0.1.0" -description = "A Tauri App" -authors = ["you"] -edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,19 +11,19 @@ edition = "2021" # The `_lib` suffix may seem redundant but it is necessary # to make the lib name unique and wouldn't conflict with the bin name. # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 -name = "test_tauri_lib" crate-type = ["staticlib", "cdylib", "rlib"] +name = "test_tauri_lib" [build-dependencies] -tauri-build = { version = "2", features = [] } +tauri-build = {version = "2", features = [] } [dependencies] -tauri = { version = "2", features = [] } -tauri-plugin-shell = "2" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -thiserror = "2.0.4" bitflags = "2.6.0" memmap = "0.7.0" +pe_serialize_proc_macro = {path = "./pe_serialize_proc_macro"} +serde = {version = "1", features = ["derive"] } +serde_json = "1" +tauri = {version = "2", features = [] } tauri-plugin-dialog = "2" - +tauri-plugin-shell = "2" +thiserror = "2.0.4" diff --git a/src-tauri/pe_serialize_proc_macro/.gitignore b/src-tauri/pe_serialize_proc_macro/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/src-tauri/pe_serialize_proc_macro/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/src-tauri/pe_serialize_proc_macro/Cargo.lock b/src-tauri/pe_serialize_proc_macro/Cargo.lock new file mode 100644 index 0000000..f156b99 --- /dev/null +++ b/src-tauri/pe_serialize_proc_macro/Cargo.lock @@ -0,0 +1,68 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "pe_serialize_proc_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff --git a/src-tauri/pe_serialize_proc_macro/Cargo.toml b/src-tauri/pe_serialize_proc_macro/Cargo.toml new file mode 100644 index 0000000..4195813 --- /dev/null +++ b/src-tauri/pe_serialize_proc_macro/Cargo.toml @@ -0,0 +1,16 @@ +[lib] +proc-macro = true + +[package] +name = "pe_serialize_proc_macro" +version = "0.1.0" +edition = "2021" + +[dependencies] +proc-macro2 = "1.0.92" +quote = "1.0.37" +serde = "1.0.215" +syn = "2.0.90" + +[serde.features] +default = ["derive"] \ No newline at end of file diff --git a/src-tauri/pe_serialize_proc_macro/src/lib.rs b/src-tauri/pe_serialize_proc_macro/src/lib.rs new file mode 100644 index 0000000..b4a134c --- /dev/null +++ b/src-tauri/pe_serialize_proc_macro/src/lib.rs @@ -0,0 +1,85 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::Data; + +fn impl_serialize_ex(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let fields = match ast.data { + Data::Struct(ref data) => &data.fields, + _ => panic!("CustomSerialize 只能用于结构体!"), + }; + let field_len = fields.len(); + // 迭代器,为每一个字段实现serialize_field + let serialize_fields = match fields { + syn::Fields::Named(ref fields) => { + fields.named.iter().map(|f| { + let name = &f.ident; + let ty = &f.ty; + let mut child_token_stream = proc_macro2::TokenStream::new(); + // 如果字段是数组类型 + if let syn::Type::Array(ref array) = ty { + let len = &array.len; + let child_ty = &array.elem; + // 类型所占字节 + + child_token_stream = quote! { + children = Some(Vec::new()); + let field_size = std::mem::size_of::<#child_ty>(); + for i in 0..#len { + let child_value = serde_json::json!({ + "name": format!("{}[{}]", stringify!(#name), i), + "value": format!("0x{:0width$X}",self.#name[i], width=field_size), + "field_type": stringify!(#child_ty), + "size": field_size, + "offset": (&self.#name[i] as *const _ as usize) - (self as *const _ as usize), + "children": null + }); + children.as_mut().unwrap().push(child_value); + } + }; + }else{ + child_token_stream = quote! { + let field_size = std::mem::size_of::<#ty>(); + value = serde_json::json!(format!("0x{:0width$X}",&self.#name, width=field_size)); + }; + } + quote! { + let mut value = serde_json::Value::Null; + let mut children: Option> = None; + #child_token_stream + + let json_value = serde_json::json!({ + "name": stringify!(#name), + "value": value, + "field_type": stringify!(#ty), + "size": std::mem::size_of::<#ty>(), + "offset": (&self.#name as *const _ as usize) - (self as *const _ as usize), + "children": &children + }); + state.serialize_field(stringify!(#name), &json_value)?; + } + }) + } + _ => panic!("CustomSerialize 只能用于结构体!"), + }; + + let gen = quote! { + impl serde::Serialize for #name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer { + let mut state = serializer.serialize_struct(stringify!(#name), #field_len)?; + #(#serialize_fields)* + state.end() + } + } + }; + gen.into() +} + +// 拓展Serialize +#[proc_macro_derive(SerializeEX)] +pub fn serialize_ex(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + impl_serialize_ex(&ast) +} diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 0efb3fd..722e7f0 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -3,8 +3,8 @@ use crate::{ pe_parse::{header::ImageDosHeader, pe::PE}, services::{self, GLOBAL_FILE_DATA}, }; -use serde::{ser::SerializeStruct, Serialize, Serializer}; -use serde_json::Value; +use serde::Serialize; + #[tauri::command] pub fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) @@ -99,250 +99,6 @@ pub struct ResponseDOSHeaderData { children: Option>, } -fn serialize_field( - state: &mut S, - name: &'static str, - value: Option, - size: usize, - field_type: &str, - offset: usize, - children: Option>, -) -> 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( - &self, - serializer: S, - ) -> Result<::Ok, ::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::(), - 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::(), - 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 { diff --git a/src-tauri/src/pe_parse/header.rs b/src-tauri/src/pe_parse/header.rs index efa3fc4..655a083 100644 --- a/src-tauri/src/pe_parse/header.rs +++ b/src-tauri/src/pe_parse/header.rs @@ -1,8 +1,10 @@ use super::types::*; use bitflags::bitflags; -use serde::Serialize; +use pe_serialize_proc_macro::SerializeEX; +use serde::ser::SerializeStruct; + #[repr(C)] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, SerializeEX)] pub struct ImageDosHeader { pub e_magic: u16, // Magic number 固定值 0x5A4D pub e_cblp: u16, @@ -22,7 +24,7 @@ pub struct ImageDosHeader { pub e_oemid: u16, pub e_oeminfo: u16, pub e_res2: [u16; 10], - pub e_lfanew: Offset, // File address of new exe header nt头的偏移 + pub e_lfanew: u32, // File address of new exe header nt头的偏移 } #[repr(C)]