feat: 可选头部已经解析
This commit is contained in:
@@ -1,17 +1,10 @@
|
||||
use crate::{
|
||||
app_error::AppError,
|
||||
pe_parse::{header::ImageDosHeader, pe::PE},
|
||||
services::{
|
||||
self,
|
||||
file::{
|
||||
get_nt_headers_data, ResponseDOSHeaderData, ResponseFileHeaderData,
|
||||
ResponseNTHeaderData,
|
||||
},
|
||||
GLOBAL_FILE_DATA,
|
||||
},
|
||||
pe_parse::pe::PE,
|
||||
services::{self, file::*, GLOBAL_FILE_DATA},
|
||||
};
|
||||
use serde::Serialize;
|
||||
use tauri::{async_runtime::Mutex, AppHandle, Manager, State};
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct PeNodeTreeData {
|
||||
@@ -96,6 +89,15 @@ pub fn command_open_file(file_path: &str) -> Result<(), AppError> {
|
||||
unsafe {
|
||||
services::GLOBAL_FILE_PATH = Some(file_path.to_string());
|
||||
}
|
||||
|
||||
// 判断文件是否是64位
|
||||
// TODO: GLOBAL_IS_64_BIT
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -125,3 +127,10 @@ pub fn command_get_pe_data_file_header() -> Result<ResponseFileHeaderData, AppEr
|
||||
let result = services::file::get_file_header_data()?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// 命令,获取可选头数据
|
||||
#[tauri::command]
|
||||
pub fn command_get_pe_data_optional_header() -> Result<ResponseOptionalHeaderData, AppError> {
|
||||
let result = services::file::get_optional_header_data()?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ pub fn run() {
|
||||
commands::command_get_pe_data_dos_header,
|
||||
commands::command_get_pe_data_nt_header,
|
||||
commands::command_get_pe_data_file_header,
|
||||
commands::set_complete
|
||||
commands::command_get_pe_data_optional_header,
|
||||
commands::set_complete,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -34,6 +34,21 @@ pub struct ImageNTHeaders32 {
|
||||
pub optional_header: ImageOptionalHeader32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct ImageNTHeaders64 {
|
||||
pub signature: u32,
|
||||
pub file_header: ImageFileHeader,
|
||||
pub optional_header: ImageOptionalHeader64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Copy)]
|
||||
#[serde(untagged)]
|
||||
pub enum ImageNTHeaders{
|
||||
NTHeaders32(ImageNTHeaders32),
|
||||
NTHeaders64(ImageNTHeaders64),
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct ImageFileHeader {
|
||||
@@ -45,21 +60,31 @@ pub struct ImageFileHeader {
|
||||
pub size_of_optional_header: u16,
|
||||
pub characteristics: FileCharacteristics,
|
||||
}
|
||||
impl Serialize for FileCharacteristics{
|
||||
impl Serialize for FileCharacteristics {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer {
|
||||
// 直接返回bitflags的整数值
|
||||
serializer.serialize_u16(self.bits())
|
||||
S: serde::Serializer,
|
||||
{
|
||||
// 直接返回bitflags的整数值
|
||||
serializer.serialize_u16(self.bits())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Serialize for DLLCharacteristics{
|
||||
impl Serialize for DLLCharacteristics {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer {
|
||||
serializer.serialize_u16(self.bits())
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_u16(self.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SectionCharacteristics {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_u32(self.bits())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +127,108 @@ bitflags! {
|
||||
const GUARD_CF = 0x4000;
|
||||
const TERMINAL_SERVER_AWARE = 0x8000;
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct SectionCharacteristics: u32 {
|
||||
/// Reserved for future use.
|
||||
const TYPE_REG = 0x00000000;
|
||||
/// Reserved for future use.
|
||||
const TYPE_DSECT = 0x00000001;
|
||||
/// Reserved for future use.
|
||||
const TYPE_NOLOAD = 0x00000002;
|
||||
/// Reserved for future use.
|
||||
const TYPE_GROUP = 0x00000004;
|
||||
/// The section should not be padded to the next boundary.
|
||||
/// This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES.
|
||||
/// This is valid only for object files.
|
||||
const TYPE_NO_PAD = 0x00000008;
|
||||
/// Reserved for future use.
|
||||
const TYPE_COPY = 0x00000010;
|
||||
/// The section contains executable code.
|
||||
const CNT_CODE = 0x00000020;
|
||||
/// The section contains initialized data.
|
||||
const CNT_INITIALIZED_DATA = 0x00000040;
|
||||
/// The section contains uninitialized data.
|
||||
const CNT_UNINITIALIZED_DATA = 0x00000080;
|
||||
/// Reserved for future use.
|
||||
const LNK_OTHER = 0x00000100;
|
||||
/// The section contains comments or other information.
|
||||
/// The .drectve section has this type. This is valid for object files only.
|
||||
const LNK_INFO = 0x00000200;
|
||||
/// Reserved for future use.
|
||||
const TYPE_OVER = 0x00000400;
|
||||
/// The section will not become part of the image.
|
||||
/// This is valid only for object files.
|
||||
const LNK_REMOVE = 0x00000800;
|
||||
/// The section contains COMDAT data. This is valid only for object files.
|
||||
const LNK_COMDAT = 0x00001000;
|
||||
/// Unknown/Reserved.
|
||||
const RESERVED = 0x00002000;
|
||||
/// Unknown flag.
|
||||
const MEM_PROTECTED = 0x00004000;
|
||||
/// Unknown flag.
|
||||
const NO_DEFER_SPEC_EXC = 0x00004000;
|
||||
/// The section contains data referenced through the global pointer (GP).
|
||||
const GPREL = 0x00008000;
|
||||
/// Reserved for future use.
|
||||
const MEM_FARDATA = 0x00008000;
|
||||
/// Reserved for future use.
|
||||
const MEM_SYSHEAP = 0x00010000;
|
||||
/// Reserved for future use.
|
||||
const MEM_PURGEABLE = 0x00020000;
|
||||
/// Reserved for future use.
|
||||
const MEM_16BIT = 0x00020000;
|
||||
/// Reserved for future use.
|
||||
const MEM_LOCKED = 0x00040000;
|
||||
/// Reserved for future use.
|
||||
const MEM_PRELOAD = 0x00080000;
|
||||
/// Align data on a 1-byte boundary. Valid only for object files.
|
||||
const ALIGN_1BYTES = 0x00100000;
|
||||
/// Align data on a 2-byte boundary. Valid only for object files.
|
||||
const ALIGN_2BYTES = 0x00200000;
|
||||
/// Align data on a 4-byte boundary. Valid only for object files.
|
||||
const ALIGN_4BYTES = 0x00300000;
|
||||
/// Align data on an 8-byte boundary. Valid only for object files.
|
||||
const ALIGN_8BYTES = 0x00400000;
|
||||
/// Align data on a 16-byte boundary. Valid only for object files.
|
||||
const ALIGN_16BYTES = 0x00500000;
|
||||
/// Align data on a 32-byte boundary. Valid only for object files.
|
||||
const ALIGN_32BYTES = 0x00600000;
|
||||
/// Align data on a 64-byte boundary. Valid only for object files.
|
||||
const ALIGN_64BYTES = 0x00700000;
|
||||
/// Align data on a 128-byte boundary. Valid only for object files.
|
||||
const ALIGN_128BYTES = 0x00800000;
|
||||
/// Align data on a 256-byte boundary. Valid only for object files.
|
||||
const ALIGN_256BYTES = 0x00900000;
|
||||
/// Align data on a 512-byte boundary. Valid only for object files.
|
||||
const ALIGN_512BYTES = 0x00A00000;
|
||||
/// Align data on a 1024-byte boundary. Valid only for object files.
|
||||
const ALIGN_1024BYTES = 0x00B00000;
|
||||
/// Align data on a 2048-byte boundary. Valid only for object files.
|
||||
const ALIGN_2048BYTES = 0x00C00000;
|
||||
/// Align data on a 4096-byte boundary. Valid only for object files.
|
||||
const ALIGN_4096BYTES = 0x00D00000;
|
||||
/// Align data on an 8192-byte boundary. Valid only for object files.
|
||||
const ALIGN_8192BYTES = 0x00E00000;
|
||||
/// Mask for alignment.
|
||||
const ALIGN_MASK = 0x00F00000;
|
||||
/// The section contains extended relocations.
|
||||
const LNK_NRELOC_OVFL = 0x01000000;
|
||||
/// The section can be discarded as needed.
|
||||
const MEM_DISCARDABLE = 0x02000000;
|
||||
/// The section cannot be cached.
|
||||
const MEM_NOT_CACHED = 0x04000000;
|
||||
/// The section is not pageable.
|
||||
const MEM_NOT_PAGED = 0x08000000;
|
||||
/// The section can be shared in memory.
|
||||
const MEM_SHARED = 0x10000000;
|
||||
/// The section can be executed as code.
|
||||
const MEM_EXECUTE = 0x20000000;
|
||||
/// The section can be read.
|
||||
const MEM_READ = 0x40000000;
|
||||
/// The section can be written to.
|
||||
const MEM_WRITE = 0x80000000;
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
@@ -112,9 +239,9 @@ pub struct ImageOptionalHeader32 {
|
||||
pub size_of_code: u32,
|
||||
pub size_of_initialized_data: u32,
|
||||
pub size_of_uninitialized_data: u32,
|
||||
pub address_of_entry_point: RVA,
|
||||
pub base_of_code: RVA,
|
||||
pub base_of_data: RVA,
|
||||
pub address_of_entry_point: u32,
|
||||
pub base_of_code: u32,
|
||||
pub base_of_data: u32,
|
||||
pub image_base: u32,
|
||||
pub section_alignment: u32,
|
||||
pub file_alignment: u32,
|
||||
@@ -137,3 +264,58 @@ pub struct ImageOptionalHeader32 {
|
||||
pub loader_flags: u32,
|
||||
pub number_of_rva_and_sizes: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Serialize)]
|
||||
pub struct ImageOptionalHeader64 {
|
||||
pub magic: u16,
|
||||
pub major_linker_version: u8,
|
||||
pub minor_linker_version: u8,
|
||||
pub size_of_code: u32,
|
||||
pub size_of_initialized_data: u32,
|
||||
pub size_of_uninitialized_data: u32,
|
||||
pub address_of_entry_point: u32,
|
||||
pub base_of_code: u32,
|
||||
pub image_base: u64,
|
||||
pub section_alignment: u32,
|
||||
pub file_alignment: u32,
|
||||
pub major_operating_system_version: u16,
|
||||
pub minor_operating_system_version: u16,
|
||||
pub major_image_version: u16,
|
||||
pub minor_image_version: u16,
|
||||
pub major_subsystem_version: u16,
|
||||
pub minor_subsystem_version: u16,
|
||||
pub win32_version_value: u32,
|
||||
pub size_of_image: u32,
|
||||
pub size_of_headers: u32,
|
||||
pub checksum: u32,
|
||||
pub subsystem: u16,
|
||||
pub dll_characteristics: DLLCharacteristics,
|
||||
pub size_of_stack_reserve: u64,
|
||||
pub size_of_stack_commit: u64,
|
||||
pub size_of_heap_reserve: u64,
|
||||
pub size_of_heap_commit: u64,
|
||||
pub loader_flags: u32,
|
||||
pub number_of_rva_and_sizes: u32,
|
||||
}
|
||||
#[derive(Serialize, Clone, Copy)]
|
||||
#[serde(untagged)]
|
||||
pub enum ImageOptionalHeader {
|
||||
OptionalHeader32(ImageOptionalHeader32),
|
||||
OptionalHeader64(ImageOptionalHeader64),
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct ImageSectionHeader {
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{error::PEParseError, header::*};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::{ops::{Deref, DerefMut}, option};
|
||||
|
||||
pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||
/// Get a reference to a type at a given offset.
|
||||
@@ -22,6 +22,16 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||
Ok(unsafe { &mut *ptr })
|
||||
}
|
||||
|
||||
// 判断是64位还是32位
|
||||
fn is_64_bit(&self) -> Result<bool, PEParseError> {
|
||||
// 先以32位加载可选头,通过可选头的Magic字段判断
|
||||
let optional_header: &ImageOptionalHeader32 = self.get_optional_header_32()?;
|
||||
let is_64_bit = optional_header.magic == 0x20b;
|
||||
Ok(is_64_bit)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Get the DOS header without verifying its contents.
|
||||
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
||||
let result = self.get_ref::<ImageDosHeader>(0)?;
|
||||
@@ -33,12 +43,26 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get the NT headers without verifying its contents.
|
||||
fn get_nt_headers(&self) -> Result<&ImageNTHeaders32, PEParseError> {
|
||||
|
||||
|
||||
fn get_nt_headers32(&self) -> Result<&ImageNTHeaders32, PEParseError> {
|
||||
let nt_offset = self.get_nt_headers_offset()?;
|
||||
let result = self.get_ref::<ImageNTHeaders32>(nt_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
fn get_nt_headers64(&self) -> Result<&ImageNTHeaders64, PEParseError> {
|
||||
let nt_offset = self.get_nt_headers_offset()?;
|
||||
let result = self.get_ref::<ImageNTHeaders64>(nt_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
fn get_nt_headers(&self) -> Result<ImageNTHeaders, PEParseError> {
|
||||
let is_64_bit = self.is_64_bit()?;
|
||||
let result = match is_64_bit {
|
||||
true => ImageNTHeaders::NTHeaders64(*self.get_nt_headers64()?),
|
||||
false => ImageNTHeaders::NTHeaders32(*self.get_nt_headers32()?),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// 获取nt头的偏移
|
||||
fn get_nt_headers_offset(&self) -> Result<usize, PEParseError> {
|
||||
@@ -76,5 +100,62 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// 获取节区数量
|
||||
fn get_number_of_sections(&self) -> Result<usize, PEParseError> {
|
||||
let file_header = self.get_file_header()?;
|
||||
Ok(file_header.number_of_sections as usize)
|
||||
}
|
||||
|
||||
// 获取可选头大小
|
||||
fn get_size_of_optional_header(&self) -> Result<usize, PEParseError> {
|
||||
let file_header = self.get_file_header()?;
|
||||
Ok(file_header.size_of_optional_header as usize)
|
||||
}
|
||||
|
||||
fn get_optional_header_32(&self) -> Result<&ImageOptionalHeader32, PEParseError> {
|
||||
let file_header_offset = self.get_file_header_offset()?;
|
||||
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||||
let result = self.get_ref::<ImageOptionalHeader32>(optional_header_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// 获取可选头
|
||||
fn get_optional_header_64(&self) -> Result<&ImageOptionalHeader64, PEParseError> {
|
||||
let file_header_offset = self.get_file_header_offset()?;
|
||||
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||||
let result = self.get_ref::<ImageOptionalHeader64>(optional_header_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn get_optional_header(&self) -> Result<ImageOptionalHeader, PEParseError> {
|
||||
let is_64_bit = self.is_64_bit()?;
|
||||
let result = match is_64_bit {
|
||||
true => ImageOptionalHeader::OptionalHeader64(*self.get_optional_header_64()?),
|
||||
false => ImageOptionalHeader::OptionalHeader32(*self.get_optional_header_32()?),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn get_optional_header_offset(&self) -> Result<usize, PEParseError> {
|
||||
let file_header_offset = self.get_file_header_offset()?;
|
||||
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||||
Ok(optional_header_offset)
|
||||
}
|
||||
|
||||
// 获取所有节区头数据
|
||||
fn get_image_section_headers(&self) -> Result<&[ImageSectionHeader], PEParseError> {
|
||||
// 1. 获取节区数量
|
||||
let number_of_sections = self.get_number_of_sections()?;
|
||||
// 2. 找到节区头的偏移
|
||||
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
||||
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;
|
||||
// 3. 获取节区头数据
|
||||
unsafe {
|
||||
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);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use memmap2::*;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders32}, pe::PE}};
|
||||
use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders, ImageNTHeaders32, ImageOptionalHeader}, pe::PE}};
|
||||
|
||||
use super::GLOBAL_FILE_DATA;
|
||||
use super::{GLOBAL_FILE_DATA, GLOBAL_IS_64_BIT};
|
||||
|
||||
// TODO: 打开文件,并将文件映射到内存
|
||||
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
||||
@@ -25,20 +25,22 @@ pub struct ResponseDOSHeaderData {
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct ResponseNTHeaderData {
|
||||
fields: ImageNTHeaders32,
|
||||
fields: ImageNTHeaders,
|
||||
base_offset: usize,
|
||||
}
|
||||
|
||||
pub fn get_nt_headers_data() -> Result<ResponseNTHeaderData, AppError> {
|
||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
||||
let file_data = binding.as_ref().unwrap();
|
||||
let nt_header = file_data.get_nt_headers()?;
|
||||
let nt_offset = file_data.get_nt_headers_offset()?;
|
||||
let result = ResponseNTHeaderData {
|
||||
fields: nt_header.clone(),
|
||||
base_offset: nt_offset,
|
||||
};
|
||||
Ok(result)
|
||||
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)
|
||||
}
|
||||
|
||||
// 获取文件头数据
|
||||
@@ -58,4 +60,23 @@ pub fn get_file_header_data() -> Result<ResponseFileHeaderData, AppError> {
|
||||
base_offset: file_header_offset,
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
// 获取可选头数据
|
||||
#[derive(Serialize)]
|
||||
pub struct ResponseOptionalHeaderData {
|
||||
pub fields: ImageOptionalHeader,
|
||||
pub base_offset: usize,
|
||||
}
|
||||
|
||||
|
||||
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 result = ResponseOptionalHeaderData {
|
||||
fields: optional_header.clone(),
|
||||
base_offset: optional_header_offset,
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
@@ -9,6 +9,8 @@ pub mod file;
|
||||
|
||||
// 全局文件路径
|
||||
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
||||
// 文件是否是64位
|
||||
pub static mut GLOBAL_IS_64_BIT: Option<bool> = None;
|
||||
|
||||
pub(crate) struct PeData(pub Vec<u8>);
|
||||
// 实现Deref
|
||||
|
||||
Reference in New Issue
Block a user